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