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