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