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