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