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