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