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.mail.MailMessage;
34  import com.liferay.portal.kernel.util.ArrayUtil;
35  import com.liferay.portal.kernel.util.Base64;
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, Recurrence 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, Recurrence 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, Recurrence 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, Recurrence 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.getPortletGroupId(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.setRecurrence(Base64.objectToString(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             startDate.setTime(event.getStartDate());
383 
384             long diff =
385                 (startDate.getTime().getTime() - now.getTime().getTime()) /
386                 CheckEventJob.INTERVAL;
387 
388             if ((diff == (event.getFirstReminder() / CheckEventJob.INTERVAL)) ||
389                 (diff ==
390                     (event.getSecondReminder() / CheckEventJob.INTERVAL))) {
391 
392                 remindUser(event, user);
393             }
394         }
395     }
396 
397     public void deleteEvent(long eventId)
398         throws PortalException, SystemException {
399 
400         CalEvent event = calEventPersistence.findByPrimaryKey(eventId);
401 
402         deleteEvent(event);
403     }
404 
405     public void deleteEvent(CalEvent event)
406         throws PortalException, SystemException {
407 
408         // Pool
409 
410         CalEventLocalUtil.clearEventsPool(event.getGroupId());
411 
412         // Social
413 
414         socialActivityLocalService.deleteActivities(
415             CalEvent.class.getName(), event.getEventId());
416 
417         // Resources
418 
419         resourceLocalService.deleteResource(
420             event.getCompanyId(), CalEvent.class.getName(),
421             ResourceConstants.SCOPE_INDIVIDUAL, event.getEventId());
422 
423         // Event
424 
425         calEventPersistence.remove(event.getEventId());
426     }
427 
428     public void deleteEvents(long groupId)
429         throws PortalException, SystemException {
430 
431         Iterator<CalEvent> itr = calEventPersistence.findByGroupId(
432             groupId).iterator();
433 
434         while (itr.hasNext()) {
435             CalEvent event = itr.next();
436 
437             deleteEvent(event);
438         }
439     }
440 
441     public File exportEvent(long userId, long eventId)
442         throws PortalException, SystemException {
443 
444         List<CalEvent> events = new ArrayList<CalEvent>();
445 
446         CalEvent event = calEventPersistence.findByPrimaryKey(eventId);
447 
448         events.add(event);
449 
450         return exportICal4j(toICalCalendar(userId, events), null);
451     }
452 
453     public File exportGroupEvents(long userId, long plid, String fileName)
454         throws PortalException, SystemException {
455 
456         long groupId = PortalUtil.getPortletGroupId(plid);
457 
458         List<CalEvent> events = calEventPersistence.findByGroupId(groupId);
459 
460         return exportICal4j(toICalCalendar(userId, events), fileName);
461     }
462 
463     public CalEvent getEvent(long eventId)
464         throws PortalException, SystemException {
465 
466         return calEventPersistence.findByPrimaryKey(eventId);
467     }
468 
469     public List<CalEvent> getEvents(
470             long groupId, String type, int start, int end)
471         throws SystemException {
472 
473         if (Validator.isNull(type)) {
474             return calEventPersistence.findByGroupId(groupId, start, end);
475         }
476         else {
477             return calEventPersistence.findByG_T(groupId, type, start, end);
478         }
479     }
480 
481     public List<CalEvent> getEvents(long groupId, Calendar cal)
482         throws SystemException {
483 
484         Map<String, List<CalEvent>> eventsPool =
485             CalEventLocalUtil.getEventsPool(groupId);
486 
487         String key = CalUtil.toString(cal);
488 
489         List<CalEvent> events = eventsPool.get(key);
490 
491         if (events == null) {
492 
493             // Time zone sensitive
494 
495             List<CalEvent> events1 = calEventFinder.findByG_SD(
496                 groupId, CalendarUtil.getGTDate(cal),
497                 CalendarUtil.getLTDate(cal), true);
498 
499             // Time zone insensitive
500 
501             Calendar tzICal = CalendarFactoryUtil.getCalendar(
502                 cal.get(Calendar.YEAR),
503                 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                 Recurrence 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.setRecurrence(Base64.objectToString(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             eventsPool.put(key, events);
555         }
556 
557         return events;
558     }
559 
560     public List<CalEvent> getEvents(long groupId, Calendar cal, String type)
561         throws SystemException {
562 
563         List<CalEvent> events = getEvents(groupId, cal);
564 
565         if (Validator.isNull(type)) {
566             return events;
567         }
568         else {
569             events = new ArrayList<CalEvent>(events);
570 
571             Iterator<CalEvent> itr = events.iterator();
572 
573             while (itr.hasNext()) {
574                 CalEvent event = itr.next();
575 
576                 if (!event.getType().equals(type)) {
577                     itr.remove();
578                 }
579             }
580 
581             return events;
582         }
583     }
584 
585     public int getEventsCount(long groupId, String type)
586         throws SystemException {
587 
588         if (Validator.isNull(type)) {
589             return calEventPersistence.countByGroupId(groupId);
590         }
591         else {
592             return calEventPersistence.countByG_T(groupId, type);
593         }
594     }
595 
596     public List<CalEvent> getRepeatingEvents(long groupId)
597         throws SystemException {
598 
599         Map<String, List<CalEvent>> eventsPool =
600             CalEventLocalUtil.getEventsPool(groupId);
601 
602         String key = "recurrence";
603 
604         List<CalEvent> events = eventsPool.get(key);
605 
606         if (events == null) {
607             events = calEventPersistence.findByG_R(groupId, true);
608 
609             eventsPool.put(key, events);
610         }
611 
612         return events;
613     }
614 
615     public boolean hasEvents(long groupId, Calendar cal)
616         throws SystemException {
617 
618         return hasEvents(groupId, cal, null);
619     }
620 
621     public boolean hasEvents(long groupId, Calendar cal, String type)
622         throws SystemException {
623 
624         if (getEvents(groupId, cal, type).size() > 0) {
625             return true;
626         }
627         else {
628             return false;
629         }
630     }
631 
632     public void importICal4j(long userId, long plid, File file)
633         throws PortalException, SystemException {
634 
635         try {
636             CalendarBuilder builder = new CalendarBuilder();
637 
638             net.fortuna.ical4j.model.Calendar calendar = builder.build(
639                 new FileReader(file));
640 
641             Iterator<VEvent> itr = calendar.getComponents(
642                 Component.VEVENT).iterator();
643 
644             while (itr.hasNext()) {
645                 VEvent vEvent = itr.next();
646 
647                 importICal4j(userId, plid, vEvent);
648             }
649         }
650         catch (IOException ioe) {
651             throw new SystemException(ioe.getMessage());
652         }
653         catch (ParserException pe) {
654             throw new SystemException(pe.getMessage());
655         }
656     }
657 
658     public CalEvent updateEvent(
659             long userId, long eventId, String title, String description,
660             int startDateMonth, int startDateDay, int startDateYear,
661             int startDateHour, int startDateMinute, int endDateMonth,
662             int endDateDay, int endDateYear, int durationHour,
663             int durationMinute, boolean allDay, boolean timeZoneSensitive,
664             String type, boolean repeating, Recurrence recurrence,
665             String remindBy, int firstReminder, int secondReminder)
666         throws PortalException, SystemException {
667 
668         // Event
669 
670         User user = userPersistence.findByPrimaryKey(userId);
671 
672         Locale locale = null;
673         TimeZone timeZone = null;
674 
675         if (timeZoneSensitive) {
676             locale = user.getLocale();
677             timeZone = user.getTimeZone();
678         }
679         else {
680             locale = LocaleUtil.getDefault();
681             timeZone = TimeZoneUtil.getDefault();
682         }
683 
684         Calendar startDate = CalendarFactoryUtil.getCalendar(timeZone, locale);
685 
686         startDate.set(Calendar.MONTH, startDateMonth);
687         startDate.set(Calendar.DATE, startDateDay);
688         startDate.set(Calendar.YEAR, startDateYear);
689         startDate.set(Calendar.HOUR_OF_DAY, startDateHour);
690         startDate.set(Calendar.MINUTE, startDateMinute);
691         startDate.set(Calendar.SECOND, 0);
692         startDate.set(Calendar.MILLISECOND, 0);
693 
694         Calendar endDate = CalendarFactoryUtil.getCalendar(timeZone, locale);
695 
696         endDate.set(Calendar.MONTH, endDateMonth);
697         endDate.set(Calendar.DATE, endDateDay);
698         endDate.set(Calendar.YEAR, endDateYear);
699         endDate.set(Calendar.HOUR_OF_DAY, 23);
700         endDate.set(Calendar.MINUTE, 59);
701         endDate.set(Calendar.SECOND, 59);
702         endDate.set(Calendar.MILLISECOND, 999);
703 
704         if (allDay) {
705             startDate.set(Calendar.HOUR_OF_DAY, 0);
706             startDate.set(Calendar.MINUTE, 0);
707 
708             durationHour = 24;
709             durationMinute = 0;
710         }
711 
712         validate(
713             title, startDateMonth, startDateDay, startDateYear, endDateMonth,
714             endDateDay, endDateYear, durationHour, durationMinute, allDay);
715 
716         CalEvent event = calEventPersistence.findByPrimaryKey(eventId);
717 
718         event.setModifiedDate(new Date());
719         event.setTitle(title);
720         event.setDescription(description);
721         event.setStartDate(startDate.getTime());
722         event.setEndDate(endDate.getTime());
723         event.setDurationHour(durationHour);
724         event.setDurationMinute(durationMinute);
725         event.setAllDay(allDay);
726         event.setTimeZoneSensitive(timeZoneSensitive);
727         event.setType(type);
728         event.setRepeating(repeating);
729         event.setRecurrence(Base64.objectToString(recurrence));
730         event.setRemindBy(remindBy);
731         event.setFirstReminder(firstReminder);
732         event.setSecondReminder(secondReminder);
733 
734         calEventPersistence.update(event, false);
735 
736         // Social
737 
738         socialActivityLocalService.addActivity(
739             userId, event.getGroupId(), CalEvent.class.getName(), eventId,
740             CalendarActivityKeys.UPDATE_EVENT, StringPool.BLANK, 0);
741 
742         // Pool
743 
744         CalEventLocalUtil.clearEventsPool(event.getGroupId());
745 
746         return event;
747     }
748 
749     protected File exportICal4j(
750             net.fortuna.ical4j.model.Calendar cal, String fileName)
751         throws SystemException {
752 
753         OutputStream os = null;
754 
755         try {
756             String extension = ".ics";
757 
758             if (Validator.isNull(fileName)) {
759                 fileName = "liferay.";
760             }
761             else {
762                 int pos = fileName.lastIndexOf(StringPool.PERIOD);
763 
764                 if (pos != -1) {
765                     extension = fileName.substring(pos);
766                     fileName = fileName.substring(0, pos);
767                 }
768             }
769 
770             File file = File.createTempFile(fileName, extension);
771 
772             os = new BufferedOutputStream(new FileOutputStream(file.getPath()));
773 
774             CalendarOutputter calOutput = new CalendarOutputter();
775 
776             calOutput.output(cal, os);
777 
778             return file;
779         }
780         catch (Exception e) {
781             _log.error(e, e);
782 
783             throw new SystemException(e);
784         }
785         finally {
786             ServletResponseUtil.cleanUp(os);
787         }
788     }
789 
790     protected Calendar getRecurrenceCal(
791         Calendar cal, Calendar tzICal, CalEvent event) {
792 
793         Calendar eventCal = CalendarFactoryUtil.getCalendar();
794         eventCal.setTime(event.getStartDate());
795 
796         Calendar recurrenceCal = (Calendar)tzICal.clone();
797         recurrenceCal.set(
798             Calendar.HOUR_OF_DAY, eventCal.get(Calendar.HOUR_OF_DAY));
799         recurrenceCal.set(
800             Calendar.MINUTE, eventCal.get(Calendar.MINUTE));
801         recurrenceCal.set(Calendar.SECOND, 0);
802         recurrenceCal.set(Calendar.MILLISECOND, 0);
803 
804         if (event.isTimeZoneSensitive()) {
805             int gmtDate = eventCal.get(Calendar.DATE);
806             long gmtMills = eventCal.getTimeInMillis();
807 
808             eventCal.setTimeZone(cal.getTimeZone());
809 
810             int tziDate = eventCal.get(Calendar.DATE);
811             long tziMills = Time.getDate(eventCal).getTime();
812 
813             if (gmtDate != tziDate) {
814                 int diffDate = 0;
815 
816                 if (gmtMills > tziMills) {
817                     diffDate = (int)Math.ceil(
818                         (double)(gmtMills - tziMills) / Time.DAY);
819                 }
820                 else {
821                     diffDate = (int)Math.floor(
822                         (double)(gmtMills - tziMills) / Time.DAY);
823                 }
824 
825                 recurrenceCal.add(Calendar.DATE, diffDate);
826             }
827         }
828 
829         return recurrenceCal;
830     }
831 
832     protected void importICal4j(
833             long userId, long plid, VEvent event)
834         throws PortalException, SystemException {
835 
836         User user = userPersistence.findByPrimaryKey(userId);
837 
838         TimeZone timeZone = user.getTimeZone();
839 
840         // X iCal property
841 
842         Property timeZoneXProperty = event.getProperty(
843             TimeZoneSensitive.PROPERTY_NAME);
844 
845         boolean timeZoneXPropertyValue = true;
846 
847         if (Validator.isNotNull(timeZoneXProperty) &&
848             timeZoneXProperty.getValue().equals("FALSE")) {
849 
850             timeZoneXPropertyValue = false;
851         }
852 
853         // Title
854 
855         String title = StringPool.BLANK;
856 
857         if (event.getSummary() != null) {
858             title = event.getSummary().getValue();
859         }
860 
861         // Description
862 
863         String description = StringPool.BLANK;
864 
865         if (event.getDescription() != null) {
866             description = event.getDescription().getValue();
867         }
868 
869         // Start date
870 
871         DtStart dtStart = event.getStartDate();
872 
873         Calendar startDate = toCalendar(
874             dtStart, timeZone, timeZoneXPropertyValue);
875 
876         startDate.setTime(dtStart.getDate());
877 
878         // End date
879 
880         Calendar endDate = null;
881 
882         DtEnd dtEnd = event.getEndDate(true);
883 
884         RRule rrule = (RRule)event.getProperty(Property.RRULE);
885 
886         if (Validator.isNotNull(dtEnd)) {
887             endDate = toCalendar(dtEnd, timeZone, timeZoneXPropertyValue);
888 
889             endDate.setTime(dtEnd.getDate());
890         }
891         else {
892             endDate = (Calendar)startDate.clone();
893             endDate.add(Calendar.DATE, 1);
894         }
895 
896         // Duration
897 
898         long diffMillis = 0;
899         long durationHours = 24;
900         long durationMins = 0;
901         boolean multiDayEvent = false;
902 
903         if (Validator.isNotNull(dtEnd)) {
904             diffMillis =
905                 dtEnd.getDate().getTime() - startDate.getTimeInMillis();
906             durationHours = diffMillis / Time.HOUR;
907             durationMins = (diffMillis / Time.MINUTE) - (durationHours * 60);
908 
909             if ((durationHours > 24) ||
910                 ((durationHours == 24) && (durationMins > 0))) {
911 
912                 durationHours = 24;
913                 durationMins = 0;
914                 multiDayEvent = true;
915             }
916         }
917 
918         // All day
919 
920         boolean allDay = false;
921 
922         if (isICal4jDateOnly(event.getStartDate()) || multiDayEvent) {
923             allDay = true;
924         }
925 
926         // Time zone sensitive
927 
928         boolean timeZoneSensitive = true;
929 
930         if (allDay || !timeZoneXPropertyValue) {
931             timeZoneSensitive = false;
932         }
933 
934         // Type
935 
936         String type = StringPool.BLANK;
937 
938         Property comment = event.getProperty(Property.COMMENT);
939 
940         if (Validator.isNotNull(comment) &&
941             ArrayUtil.contains(CalEventImpl.TYPES, comment.getValue())) {
942 
943             type = comment.getValue();
944         }
945 
946         // Recurrence
947 
948         boolean repeating = false;
949         Recurrence recurrence = null;
950 
951         if (multiDayEvent) {
952             repeating = true;
953 
954             Calendar recStartCal = CalendarFactoryUtil.getCalendar(timeZone);
955 
956             recStartCal.setTime(startDate.getTime());
957 
958             com.liferay.portal.kernel.cal.Duration duration =
959                 new com.liferay.portal.kernel.cal.Duration(1, 0, 0, 0);
960 
961             recurrence = new Recurrence(
962                 recStartCal, duration, Recurrence.DAILY);
963 
964             Calendar until = (Calendar) startDate.clone();
965 
966             until.setTimeInMillis(until.getTimeInMillis() + diffMillis);
967 
968             recurrence.setUntil(until);
969 
970             endDate = recurrence.getUntil();
971         }
972         else if (rrule != null) {
973             repeating = true;
974             recurrence = toRecurrence(rrule, timeZone, startDate);
975 
976             if (recurrence.getUntil() != null) {
977                 endDate = recurrence.getUntil();
978             }
979         }
980 
981         // Reminder
982 
983         String remindBy = "none";
984         int firstReminder = 300000;
985         int secondReminder = 300000;
986 
987         // Permissions
988 
989         boolean addCommunityPermissions = false;
990         boolean addGuestPermissions = false;
991 
992         addEvent(
993             userId, plid, title, description, startDate.get(Calendar.MONTH),
994             startDate.get(Calendar.DAY_OF_MONTH), startDate.get(Calendar.YEAR),
995             startDate.get(Calendar.HOUR_OF_DAY),
996             startDate.get(Calendar.MINUTE), endDate.get(Calendar.MONTH),
997             endDate.get(Calendar.DAY_OF_MONTH), endDate.get(Calendar.YEAR),
998             (int)durationHours, (int)durationMins, allDay,
999             timeZoneSensitive, type, repeating, recurrence, remindBy,
1000            firstReminder, secondReminder, addCommunityPermissions,
1001            addGuestPermissions);
1002
1003    }
1004
1005    protected boolean isICal4jDateOnly(DateProperty date) {
1006        if (Validator.isNotNull(date.getParameter(Parameter.VALUE)) &&
1007            date.getParameter(Parameter.VALUE).getValue().equals("DATE")) {
1008
1009            return true;
1010        }
1011
1012        return false;
1013    }
1014
1015    protected void remindUser(CalEvent event, User user) {
1016        String remindBy = event.getRemindBy();
1017
1018        if (remindBy.equals(CalEventImpl.REMIND_BY_NONE)) {
1019            return;
1020        }
1021
1022        try {
1023            long ownerId = event.getGroupId();
1024            int ownerType = PortletKeys.PREFS_OWNER_TYPE_GROUP;
1025            long plid = PortletKeys.PREFS_PLID_SHARED;
1026            String portletId = PortletKeys.CALENDAR;
1027
1028            PortletPreferences prefs =
1029                portletPreferencesLocalService.getPreferences(
1030                    event.getCompanyId(), ownerId, ownerType, plid, portletId);
1031
1032            Company company = companyPersistence.findByPrimaryKey(
1033                user.getCompanyId());
1034
1035            Contact contact = user.getContact();
1036
1037            String portletName = PortalUtil.getPortletTitle(
1038                PortletKeys.CALENDAR, user);
1039
1040            String fromName = CalUtil.getEmailFromName(prefs);
1041            String fromAddress = CalUtil.getEmailFromAddress(prefs);
1042
1043            String toName = user.getFullName();
1044            String toAddress = user.getEmailAddress();
1045
1046            if (remindBy.equals(CalEventImpl.REMIND_BY_SMS)) {
1047                toAddress = contact.getSmsSn();
1048            }
1049
1050            String subject = CalUtil.getEmailEventReminderSubject(prefs);
1051            String body = CalUtil.getEmailEventReminderBody(prefs);
1052
1053            DateFormat dateFormatDateTime = DateFormats.getDateTime(
1054                user.getLocale(), user.getTimeZone());
1055
1056            subject = StringUtil.replace(
1057                subject,
1058                new String[] {
1059                    "[$EVENT_START_DATE$]",
1060                    "[$EVENT_TITLE$]",
1061                    "[$FROM_ADDRESS$]",
1062                    "[$FROM_NAME$]",
1063                    "[$PORTAL_URL$]",
1064                    "[$PORTLET_NAME$]",
1065                    "[$TO_ADDRESS$]",
1066                    "[$TO_NAME$]"
1067                },
1068                new String[] {
1069                    dateFormatDateTime.format(event.getStartDate()),
1070                    event.getTitle(),
1071                    fromAddress,
1072                    fromName,
1073                    company.getVirtualHost(),
1074                    portletName,
1075                    toAddress,
1076                    toName,
1077                });
1078
1079            body = StringUtil.replace(
1080                body,
1081                new String[] {
1082                    "[$EVENT_START_DATE$]",
1083                    "[$EVENT_TITLE$]",
1084                    "[$FROM_ADDRESS$]",
1085                    "[$FROM_NAME$]",
1086                    "[$PORTAL_URL$]",
1087                    "[$PORTLET_NAME$]",
1088                    "[$TO_ADDRESS$]",
1089                    "[$TO_NAME$]"
1090                },
1091                new String[] {
1092                    dateFormatDateTime.format(event.getStartDate()),
1093                    event.getTitle(),
1094                    fromAddress,
1095                    fromName,
1096                    company.getVirtualHost(),
1097                    portletName,
1098                    toAddress,
1099                    toName,
1100                });
1101
1102            if (remindBy.equals(CalEventImpl.REMIND_BY_EMAIL) ||
1103                remindBy.equals(CalEventImpl.REMIND_BY_SMS)) {
1104
1105                InternetAddress from = new InternetAddress(
1106                    fromAddress, fromName);
1107
1108                InternetAddress to = new InternetAddress(toAddress, toName);
1109
1110                MailMessage message = new MailMessage(
1111                    from, to, subject, body, true);
1112
1113                mailService.sendEmail(message);
1114            }
1115            else if (remindBy.equals(CalEventImpl.REMIND_BY_AIM) &&
1116                     Validator.isNotNull(contact.getAimSn())) {
1117
1118                AIMConnector.send(contact.getAimSn(), body);
1119            }
1120            else if (remindBy.equals(CalEventImpl.REMIND_BY_ICQ) &&
1121                     Validator.isNotNull(contact.getIcqSn())) {
1122
1123                ICQConnector.send(contact.getIcqSn(), body);
1124            }
1125            else if (remindBy.equals(CalEventImpl.REMIND_BY_MSN) &&
1126                     Validator.isNotNull(contact.getMsnSn())) {
1127
1128                MSNConnector.send(contact.getMsnSn(), body);
1129            }
1130            else if (remindBy.equals(CalEventImpl.REMIND_BY_YM) &&
1131                     Validator.isNotNull(contact.getYmSn())) {
1132
1133                YMConnector.send(contact.getYmSn(), body);
1134            }
1135        }
1136        catch (Exception e) {
1137            _log.error(e);
1138        }
1139    }
1140
1141    protected Calendar toCalendar(
1142        DateProperty date, TimeZone timeZone, boolean timeZoneSensitive) {
1143
1144        Calendar cal = null;
1145
1146        if (isICal4jDateOnly(date)) {
1147            cal = Calendar.getInstance();
1148        }
1149        else if (!timeZoneSensitive) {
1150            cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
1151        }
1152        else {
1153            cal = Calendar.getInstance(timeZone);
1154        }
1155
1156        return cal;
1157    }
1158
1159    protected int toCalendarWeekDay(WeekDay weekDay) {
1160        int dayOfWeeek = 0;
1161
1162        if (weekDay.getDay().equals(WeekDay.SU.getDay())) {
1163            dayOfWeeek = Calendar.SUNDAY;
1164        }
1165        else if (weekDay.getDay().equals(WeekDay.MO.getDay())) {
1166            dayOfWeeek = Calendar.MONDAY;
1167        }
1168        else if (weekDay.getDay().equals(WeekDay.TU.getDay())) {
1169            dayOfWeeek = Calendar.TUESDAY;
1170        }
1171        else if (weekDay.getDay().equals(WeekDay.WE.getDay())) {
1172            dayOfWeeek = Calendar.WEDNESDAY;
1173        }
1174        else if (weekDay.getDay().equals(WeekDay.TH.getDay())) {
1175            dayOfWeeek = Calendar.THURSDAY;
1176        }
1177        else if (weekDay.getDay().equals(WeekDay.FR.getDay())) {
1178            dayOfWeeek = Calendar.FRIDAY;
1179        }
1180        else if (weekDay.getDay().equals(WeekDay.SA.getDay())) {
1181            dayOfWeeek = Calendar.SATURDAY;
1182        }
1183
1184        return dayOfWeeek;
1185    }
1186
1187    protected net.fortuna.ical4j.model.Calendar toICalCalendar(
1188        long userId, List<CalEvent> events)
1189        throws PortalException, SystemException {
1190
1191        net.fortuna.ical4j.model.Calendar iCal =
1192            new net.fortuna.ical4j.model.Calendar();
1193
1194        ProdId prodId = new ProdId(
1195            "-//Liferay Inc//Liferay Portal " + ReleaseInfo.getVersion() +
1196            "//EN");
1197
1198        PropertyList props = iCal.getProperties();
1199
1200        props.add(prodId);
1201        props.add(Version.VERSION_2_0);
1202        props.add(CalScale.GREGORIAN);
1203
1204        User user = userPersistence.findByPrimaryKey(userId);
1205        TimeZone timeZone = user.getTimeZone();
1206
1207        List<VEvent> components = iCal.getComponents();
1208
1209        Iterator<CalEvent> itr = events.iterator();
1210
1211        while (itr.hasNext()) {
1212            CalEvent event = itr.next();
1213
1214            components.add(toICalVEvent(event, timeZone));
1215        }
1216
1217        return iCal;
1218    }
1219
1220    protected Recur toICalRecurrence(Recurrence recurrence) {
1221        Recur recur = null;
1222
1223        int recurrenceType = recurrence.getFrequency();
1224
1225        int interval = recurrence.getInterval();
1226
1227        if (recurrenceType == Recurrence.DAILY) {
1228            recur = new Recur(Recur.DAILY, -1);
1229
1230            if (interval >= 1) {
1231                recur.setInterval(interval);
1232            }
1233
1234            DayAndPosition[] byDay = recurrence.getByDay();
1235
1236            if (byDay != null) {
1237                for (int i = 0; i < byDay.length; i++) {
1238                    WeekDay weekDay = toICalWeekDay(byDay[i].getDayOfWeek());
1239
1240                    recur.getDayList().add(weekDay);
1241                }
1242            }
1243
1244        }
1245        else if (recurrenceType == Recurrence.WEEKLY) {
1246            recur = new Recur(Recur.WEEKLY, -1);
1247
1248            recur.setInterval(interval);
1249
1250            DayAndPosition[] byDay = recurrence.getByDay();
1251
1252            if (byDay != null) {
1253                for (int i = 0; i < byDay.length; i++) {
1254                    WeekDay weekDay = toICalWeekDay(byDay[i].getDayOfWeek());
1255
1256                    recur.getDayList().add(weekDay);
1257                }
1258            }
1259        }
1260        else if (recurrenceType == Recurrence.MONTHLY) {
1261            recur = new Recur(Recur.MONTHLY, -1);
1262
1263            recur.setInterval(interval);
1264
1265            int[] byMonthDay = recurrence.getByMonthDay();
1266
1267            if (byMonthDay != null) {
1268                Integer monthDay = new Integer(byMonthDay[0]);
1269
1270                recur.getMonthDayList().add(monthDay);
1271            }
1272            else if (recurrence.getByDay() != null){
1273                DayAndPosition[] byDay = recurrence.getByDay();
1274
1275                WeekDay weekDay = toICalWeekDay(byDay[0].getDayOfWeek());
1276
1277                recur.getDayList().add(weekDay);
1278
1279                Integer position = new Integer(byDay[0].getDayPosition());
1280
1281                recur.getSetPosList().add(position);
1282            }
1283        }
1284        else if (recurrenceType == Recurrence.YEARLY) {
1285            recur = new Recur(Recur.YEARLY, -1);
1286
1287            recur.setInterval(interval);
1288        }
1289
1290        Calendar until = recurrence.getUntil();
1291
1292        if (until != null) {
1293            DateTime dateTime = new DateTime(until.getTime());
1294
1295            recur.setUntil(dateTime);
1296        }
1297
1298        return recur;
1299    }
1300
1301    protected VEvent toICalVEvent(CalEvent event, TimeZone timeZone){
1302        VEvent vEvent = new VEvent();
1303
1304        PropertyList eventProps = vEvent.getProperties();
1305
1306        // UID
1307
1308        Uid uid = new Uid(PortalUUIDUtil.generate());
1309
1310        eventProps.add(uid);
1311
1312        if (event.isAllDay()) {
1313
1314            // Start date
1315
1316            DtStart dtStart = new DtStart(
1317                new net.fortuna.ical4j.model.Date(event.getStartDate()));
1318
1319            eventProps.add(dtStart);
1320
1321            Property dtStartProperty = eventProps.getProperty(Property.DTSTART);
1322
1323            dtStartProperty.getParameters().add(Value.DATE);
1324        }
1325        else {
1326
1327            // Start date
1328
1329            DtStart dtStart = new DtStart(new DateTime(event.getStartDate()));
1330
1331            eventProps.add(dtStart);
1332
1333            // Duration
1334
1335            Duration duration = new Duration(
1336                new Dur(
1337                    0, event.getDurationHour(), event.getDurationMinute(), 0));
1338
1339            eventProps.add(duration);
1340        }
1341
1342        // Summary
1343
1344        Summary summary = new Summary(event.getTitle());
1345
1346        eventProps.add(summary);
1347
1348        // Description
1349
1350        Description description = new Description(event.getDescription());
1351
1352        eventProps.add(description);
1353
1354        // Comment
1355
1356        Comment comment = new Comment(event.getType());
1357
1358        eventProps.add(comment);
1359
1360        // Recurrence rule
1361
1362        if (event.isRepeating()) {
1363            Recur recur = toICalRecurrence(event.getRecurrenceObj());
1364
1365            RRule rRule = new RRule(recur);
1366
1367            eventProps.add(rRule);
1368        }
1369
1370        // Time zone sensitive
1371
1372        if (!event.getTimeZoneSensitive()) {
1373            eventProps.add(new TimeZoneSensitive("FALSE"));
1374        }
1375
1376        return vEvent;
1377    }
1378
1379    protected WeekDay toICalWeekDay(int dayOfWeek) {
1380        WeekDay weekDay = null;
1381
1382        if (dayOfWeek == Calendar.SUNDAY) {
1383            weekDay = WeekDay.SU;
1384        }
1385        else if (dayOfWeek == Calendar.MONDAY) {
1386            weekDay = WeekDay.MO;
1387        }
1388        else if (dayOfWeek == Calendar.TUESDAY) {
1389            weekDay = WeekDay.TU;
1390        }
1391        else if (dayOfWeek == Calendar.WEDNESDAY) {
1392            weekDay = WeekDay.WE;
1393        }
1394        else if (dayOfWeek == Calendar.THURSDAY) {
1395            weekDay = WeekDay.TH;
1396        }
1397        else if (dayOfWeek == Calendar.FRIDAY) {
1398            weekDay = WeekDay.FR;
1399        }
1400        else if (dayOfWeek == Calendar.SATURDAY) {
1401            weekDay = WeekDay.SA;
1402        }
1403
1404        return weekDay;
1405    }
1406
1407    protected Recurrence toRecurrence(
1408        RRule rRule, TimeZone timeZone, Calendar startDate) {
1409
1410        Recur recur = rRule.getRecur();
1411
1412        Calendar recStartCal = CalendarFactoryUtil.getCalendar(timeZone);
1413
1414        recStartCal.setTime(startDate.getTime());
1415
1416        Recurrence recurrence = new Recurrence(
1417            recStartCal,
1418            new com.liferay.portal.kernel.cal.Duration(1, 0, 0, 0));
1419
1420        recurrence.setWeekStart(Calendar.SUNDAY);
1421
1422        if (recur.getInterval() > 1){
1423            recurrence.setInterval(recur.getInterval());
1424        }
1425
1426        Calendar until = Calendar.getInstance(timeZone);
1427
1428        String frequency = recur.getFrequency();
1429
1430        if (Validator.isNotNull(recur.getUntil())) {
1431            until.setTime(recur.getUntil());
1432
1433            recurrence.setUntil(until);
1434        }
1435        else if (rRule.getValue().indexOf("COUNT") >= 0) {
1436            until.setTimeInMillis(startDate.getTimeInMillis());
1437
1438            int addField = 0;
1439
1440            if (Recur.DAILY.equals(frequency)) {
1441                addField = Calendar.DAY_OF_YEAR;
1442            }
1443            else if (Recur.WEEKLY.equals(frequency)) {
1444                addField = Calendar.WEEK_OF_YEAR;
1445            }
1446            else if (Recur.MONTHLY.equals(frequency)) {
1447                addField = Calendar.MONTH;
1448            }
1449            else if (Recur.YEARLY.equals(frequency)) {
1450                addField = Calendar.YEAR;
1451            }
1452
1453            int addAmount = recurrence.getInterval() * recur.getCount();
1454
1455            until.add(addField, addAmount);
1456            until.add(Calendar.DAY_OF_YEAR, -1);
1457
1458            recurrence.setUntil(until);
1459        }
1460
1461        if (Recur.DAILY.equals(frequency)) {
1462            recurrence.setFrequency(Recurrence.DAILY);
1463
1464            List<DayAndPosition> dayPosList = new ArrayList<DayAndPosition>();
1465
1466            Iterator<WeekDay> itr = recur.getDayList().iterator();
1467
1468            while (itr.hasNext()) {
1469                WeekDay weekDay = itr.next();
1470
1471                dayPosList.add(
1472                    new DayAndPosition(toCalendarWeekDay(weekDay), 0));
1473            }
1474
1475            if (!dayPosList.isEmpty()) {
1476                recurrence.setByDay(
1477                    dayPosList.toArray(new DayAndPosition[dayPosList.size()]));
1478            }
1479        }
1480        else if (Recur.WEEKLY.equals(frequency)) {
1481            recurrence.setFrequency(Recurrence.WEEKLY);
1482
1483            List<DayAndPosition> dayPosList = new ArrayList<DayAndPosition>();
1484
1485            Iterator<WeekDay> itr = recur.getDayList().iterator();
1486
1487            while (itr.hasNext()) {
1488                WeekDay weekDay = itr.next();
1489
1490                dayPosList.add(
1491                    new DayAndPosition(toCalendarWeekDay(weekDay), 0));
1492            }
1493
1494            if (!dayPosList.isEmpty()) {
1495                recurrence.setByDay(
1496                    dayPosList.toArray(new DayAndPosition[dayPosList.size()]));
1497            }
1498        }
1499        else if (Recur.MONTHLY.equals(frequency)) {
1500            recurrence.setFrequency(Recurrence.MONTHLY);
1501
1502            Iterator<Integer> monthDayListItr =
1503                recur.getMonthDayList().iterator();
1504
1505            if (monthDayListItr.hasNext()) {
1506                Integer monthDay = monthDayListItr.next();
1507
1508                recurrence.setByMonthDay(new int[] {monthDay.intValue()});
1509            }
1510
1511            Iterator<WeekDay> dayListItr = recur.getDayList().iterator();
1512
1513            if (dayListItr.hasNext()) {
1514                WeekDay weekDay = dayListItr.next();
1515
1516                DayAndPosition[] dayPos = {
1517                    new DayAndPosition(toCalendarWeekDay(weekDay),
1518                    weekDay.getOffset())
1519                };
1520
1521                recurrence.setByDay(dayPos);
1522            }
1523        }
1524        else if (Recur.YEARLY.equals(frequency)) {
1525            recurrence.setFrequency(Recurrence.YEARLY);
1526        }
1527
1528        return recurrence;
1529    }
1530
1531    protected void validate(
1532            String title, int startDateMonth, int startDateDay,
1533            int startDateYear, int endDateMonth, int endDateDay,
1534            int endDateYear, int durationHour, int durationMinute,
1535            boolean allDay)
1536        throws PortalException {
1537
1538        if (Validator.isNull(title)) {
1539            throw new EventTitleException();
1540        }
1541        else if (!Validator.isDate(
1542                startDateMonth, startDateDay, startDateYear)) {
1543
1544            throw new EventStartDateException();
1545        }
1546        else if (!Validator.isDate(endDateMonth, endDateDay, endDateYear)) {
1547            throw new EventEndDateException();
1548        }
1549
1550        if (!allDay && durationHour <= 0 && durationMinute <= 0) {
1551            throw new EventDurationException();
1552        }
1553
1554        Calendar startDate = CalendarFactoryUtil.getCalendar(
1555            startDateYear, startDateMonth, startDateDay);
1556
1557        Calendar endDate = CalendarFactoryUtil.getCalendar(
1558            endDateYear, endDateMonth, endDateDay);
1559
1560        if (startDate.after(endDate)) {
1561            throw new EventEndDateException();
1562        }
1563    }
1564
1565    private static Log _log = LogFactory.getLog(CalEventLocalServiceImpl.class);
1566
1567}