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