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