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