001    /**
002     * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
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(
1009                                    TimeZoneUtil.getTimeZone(StringPool.UTC));
1010    
1011                            recStartCal.setTime(startDate.getTime());
1012    
1013                            com.liferay.portal.kernel.cal.Duration duration =
1014                                    new com.liferay.portal.kernel.cal.Duration(1, 0, 0, 0);
1015    
1016                            recurrence = new TZSRecurrence(
1017                                    recStartCal, duration, Recurrence.DAILY);
1018    
1019                            Calendar until = CalendarFactoryUtil.getCalendar(
1020                                    TimeZoneUtil.getTimeZone(StringPool.UTC));
1021    
1022                            until.setTimeInMillis(until.getTimeInMillis() + diffMillis);
1023    
1024                            recurrence.setUntil(until);
1025    
1026                            endDate.setTime(recurrence.getUntil().getTime());
1027                    }
1028                    else if (rrule != null) {
1029                            repeating = true;
1030                            recurrence = toRecurrence(rrule, startDate);
1031    
1032                            if (recurrence.getUntil() != null) {
1033                                    endDate.setTime(recurrence.getUntil().getTime());
1034                            }
1035                    }
1036    
1037                    // Reminder
1038    
1039                    int remindBy = CalEventConstants.REMIND_BY_NONE;
1040                    int firstReminder = 300000;
1041                    int secondReminder = 300000;
1042    
1043                    // Permissions
1044    
1045                    ServiceContext serviceContext = new ServiceContext();
1046    
1047                    serviceContext.setAddCommunityPermissions(true);
1048                    serviceContext.setAddGuestPermissions(true);
1049                    serviceContext.setScopeGroupId(groupId);
1050    
1051                    addEvent(
1052                            userId, title, description, startDate.get(Calendar.MONTH),
1053                            startDate.get(Calendar.DAY_OF_MONTH), startDate.get(Calendar.YEAR),
1054                            startDate.get(Calendar.HOUR_OF_DAY),
1055                            startDate.get(Calendar.MINUTE), endDate.get(Calendar.MONTH),
1056                            endDate.get(Calendar.DAY_OF_MONTH), endDate.get(Calendar.YEAR),
1057                            (int)durationHours, (int)durationMins, allDay,
1058                            timeZoneSensitive, type, repeating, recurrence, remindBy,
1059                            firstReminder, secondReminder, serviceContext);
1060    
1061            }
1062    
1063            protected boolean isICal4jDateOnly(DateProperty dateProperty) {
1064                    Parameter valueParameter = dateProperty.getParameter(Parameter.VALUE);
1065    
1066                    if ((valueParameter != null) &&
1067                            valueParameter.getValue().equals("DATE")) {
1068    
1069                            return true;
1070                    }
1071    
1072                    return false;
1073            }
1074    
1075            protected void remindUser(CalEvent event, User user, Calendar startDate) {
1076                    int remindBy = event.getRemindBy();
1077    
1078                    if (remindBy == CalEventConstants.REMIND_BY_NONE) {
1079                            return;
1080                    }
1081    
1082                    try {
1083                            long ownerId = event.getGroupId();
1084                            int ownerType = PortletKeys.PREFS_OWNER_TYPE_GROUP;
1085                            long plid = PortletKeys.PREFS_PLID_SHARED;
1086                            String portletId = PortletKeys.CALENDAR;
1087    
1088                            PortletPreferences preferences =
1089                                    portletPreferencesLocalService.getPreferences(
1090                                            event.getCompanyId(), ownerId, ownerType, plid, portletId);
1091    
1092                            Company company = companyPersistence.findByPrimaryKey(
1093                                    user.getCompanyId());
1094    
1095                            Contact contact = user.getContact();
1096    
1097                            String portletName = PortalUtil.getPortletTitle(
1098                                    PortletKeys.CALENDAR, user);
1099    
1100                            String fromName = CalUtil.getEmailFromName(preferences);
1101                            String fromAddress = CalUtil.getEmailFromAddress(preferences);
1102    
1103                            String toName = user.getFullName();
1104                            String toAddress = user.getEmailAddress();
1105    
1106                            if (remindBy == CalEventConstants.REMIND_BY_SMS) {
1107                                    toAddress = contact.getSmsSn();
1108                            }
1109    
1110                            String subject = CalUtil.getEmailEventReminderSubject(preferences);
1111                            String body = CalUtil.getEmailEventReminderBody(preferences);
1112    
1113                            Format dateFormatDateTime = FastDateFormatFactoryUtil.getDateTime(
1114                                    user.getLocale(), user.getTimeZone());
1115    
1116                            subject = StringUtil.replace(
1117                                    subject,
1118                                    new String[] {
1119                                            "[$EVENT_START_DATE$]",
1120                                            "[$EVENT_TITLE$]",
1121                                            "[$FROM_ADDRESS$]",
1122                                            "[$FROM_NAME$]",
1123                                            "[$PORTAL_URL$]",
1124                                            "[$PORTLET_NAME$]",
1125                                            "[$TO_ADDRESS$]",
1126                                            "[$TO_NAME$]"
1127                                    },
1128                                    new String[] {
1129                                            dateFormatDateTime.format(startDate.getTime()),
1130                                            event.getTitle(),
1131                                            fromAddress,
1132                                            fromName,
1133                                            company.getVirtualHost(),
1134                                            portletName,
1135                                            toAddress,
1136                                            toName,
1137                                    });
1138    
1139                            body = StringUtil.replace(
1140                                    body,
1141                                    new String[] {
1142                                            "[$EVENT_START_DATE$]",
1143                                            "[$EVENT_TITLE$]",
1144                                            "[$FROM_ADDRESS$]",
1145                                            "[$FROM_NAME$]",
1146                                            "[$PORTAL_URL$]",
1147                                            "[$PORTLET_NAME$]",
1148                                            "[$TO_ADDRESS$]",
1149                                            "[$TO_NAME$]"
1150                                    },
1151                                    new String[] {
1152                                            dateFormatDateTime.format(startDate.getTime()),
1153                                            event.getTitle(),
1154                                            fromAddress,
1155                                            fromName,
1156                                            company.getVirtualHost(),
1157                                            portletName,
1158                                            toAddress,
1159                                            toName,
1160                                    });
1161    
1162                            if ((remindBy == CalEventConstants.REMIND_BY_EMAIL) ||
1163                                    (remindBy == CalEventConstants.REMIND_BY_SMS)) {
1164    
1165                                    InternetAddress from = new InternetAddress(
1166                                            fromAddress, fromName);
1167    
1168                                    InternetAddress to = new InternetAddress(toAddress, toName);
1169    
1170                                    MailMessage message = new MailMessage(
1171                                            from, to, subject, body, true);
1172    
1173                                    mailService.sendEmail(message);
1174                            }
1175                            else if ((remindBy == CalEventConstants.REMIND_BY_AIM) &&
1176                                             (Validator.isNotNull(contact.getAimSn()))) {
1177    
1178                                    AIMConnector.send(contact.getAimSn(), body);
1179                            }
1180                            else if ((remindBy == CalEventConstants.REMIND_BY_ICQ) &&
1181                                             (Validator.isNotNull(contact.getIcqSn()))) {
1182    
1183                                    ICQConnector.send(contact.getIcqSn(), body);
1184                            }
1185                            else if ((remindBy == CalEventConstants.REMIND_BY_MSN) &&
1186                                             (Validator.isNotNull(contact.getMsnSn()))) {
1187    
1188                                    MSNConnector.send(contact.getMsnSn(), body);
1189                            }
1190                            else if ((remindBy == CalEventConstants.REMIND_BY_YM) &&
1191                                             (Validator.isNotNull(contact.getYmSn()))) {
1192    
1193                                    YMConnector.send(contact.getYmSn(), body);
1194                            }
1195                    }
1196                    catch (Exception e) {
1197                            _log.error(e);
1198                    }
1199            }
1200    
1201            protected void remindUser(
1202                    CalEvent event, User user, Calendar startDate, Calendar now) {
1203    
1204                    long diff =
1205                            (startDate.getTime().getTime() - now.getTime().getTime()) /
1206                                    _eventCheckInterval;
1207    
1208                    if ((diff == (event.getFirstReminder() / _eventCheckInterval)) ||
1209                            (diff == (event.getSecondReminder() / _eventCheckInterval))) {
1210    
1211                            remindUser(event, user, startDate);
1212                    }
1213            }
1214    
1215            protected Calendar toCalendar(
1216                    DateProperty date, TimeZone timeZone, boolean timeZoneSensitive) {
1217    
1218                    Calendar cal = null;
1219    
1220                    if (isICal4jDateOnly(date)) {
1221                            cal = Calendar.getInstance();
1222                    }
1223                    else if (!timeZoneSensitive) {
1224                            cal = Calendar.getInstance(
1225                                    TimeZoneUtil.getTimeZone(StringPool.UTC));
1226                    }
1227                    else {
1228                            cal = Calendar.getInstance(timeZone);
1229                    }
1230    
1231                    return cal;
1232            }
1233    
1234            protected int toCalendarWeekDay(WeekDay weekDay) {
1235                    int dayOfWeeek = 0;
1236    
1237                    if (weekDay.getDay().equals(WeekDay.SU.getDay())) {
1238                            dayOfWeeek = Calendar.SUNDAY;
1239                    }
1240                    else if (weekDay.getDay().equals(WeekDay.MO.getDay())) {
1241                            dayOfWeeek = Calendar.MONDAY;
1242                    }
1243                    else if (weekDay.getDay().equals(WeekDay.TU.getDay())) {
1244                            dayOfWeeek = Calendar.TUESDAY;
1245                    }
1246                    else if (weekDay.getDay().equals(WeekDay.WE.getDay())) {
1247                            dayOfWeeek = Calendar.WEDNESDAY;
1248                    }
1249                    else if (weekDay.getDay().equals(WeekDay.TH.getDay())) {
1250                            dayOfWeeek = Calendar.THURSDAY;
1251                    }
1252                    else if (weekDay.getDay().equals(WeekDay.FR.getDay())) {
1253                            dayOfWeeek = Calendar.FRIDAY;
1254                    }
1255                    else if (weekDay.getDay().equals(WeekDay.SA.getDay())) {
1256                            dayOfWeeek = Calendar.SATURDAY;
1257                    }
1258    
1259                    return dayOfWeeek;
1260            }
1261    
1262            protected net.fortuna.ical4j.model.Calendar toICalCalendar(
1263                    long userId, List<CalEvent> events)
1264                    throws PortalException, SystemException {
1265    
1266                    net.fortuna.ical4j.model.Calendar iCal =
1267                            new net.fortuna.ical4j.model.Calendar();
1268    
1269                    ProdId prodId = new ProdId(
1270                            "-//Liferay Inc//Liferay Portal " + ReleaseInfo.getVersion() +
1271                            "//EN");
1272    
1273                    PropertyList props = iCal.getProperties();
1274    
1275                    props.add(prodId);
1276                    props.add(Version.VERSION_2_0);
1277                    props.add(CalScale.GREGORIAN);
1278    
1279                    // LPS-6058
1280    
1281                    props.add(Method.PUBLISH);
1282    
1283                    User user = userPersistence.findByPrimaryKey(userId);
1284                    TimeZone timeZone = user.getTimeZone();
1285    
1286                    List<VEvent> components = iCal.getComponents();
1287    
1288                    Iterator<CalEvent> itr = events.iterator();
1289    
1290                    while (itr.hasNext()) {
1291                            CalEvent event = itr.next();
1292    
1293                            components.add(toICalVEvent(event, timeZone));
1294                    }
1295    
1296                    return iCal;
1297            }
1298    
1299            protected Recur toICalRecurrence(TZSRecurrence recurrence) {
1300                    Recur recur = null;
1301    
1302                    int recurrenceType = recurrence.getFrequency();
1303    
1304                    int interval = recurrence.getInterval();
1305    
1306                    if (recurrenceType == Recurrence.DAILY) {
1307                            recur = new Recur(Recur.DAILY, -1);
1308    
1309                            if (interval >= 1) {
1310                                    recur.setInterval(interval);
1311                            }
1312    
1313                            DayAndPosition[] byDay = recurrence.getByDay();
1314    
1315                            if (byDay != null) {
1316                                    for (int i = 0; i < byDay.length; i++) {
1317                                            WeekDay weekDay = toICalWeekDay(byDay[i].getDayOfWeek());
1318    
1319                                            recur.getDayList().add(weekDay);
1320                                    }
1321                            }
1322    
1323                    }
1324                    else if (recurrenceType == Recurrence.WEEKLY) {
1325                            recur = new Recur(Recur.WEEKLY, -1);
1326    
1327                            recur.setInterval(interval);
1328    
1329                            DayAndPosition[] byDay = recurrence.getByDay();
1330    
1331                            if (byDay != null) {
1332                                    for (int i = 0; i < byDay.length; i++) {
1333                                            WeekDay weekDay = toICalWeekDay(byDay[i].getDayOfWeek());
1334    
1335                                            recur.getDayList().add(weekDay);
1336                                    }
1337                            }
1338                    }
1339                    else if (recurrenceType == Recurrence.MONTHLY) {
1340                            recur = new Recur(Recur.MONTHLY, -1);
1341    
1342                            recur.setInterval(interval);
1343    
1344                            int[] byMonthDay = recurrence.getByMonthDay();
1345    
1346                            if (byMonthDay != null) {
1347                                    Integer monthDay = new Integer(byMonthDay[0]);
1348    
1349                                    recur.getMonthDayList().add(monthDay);
1350                            }
1351                            else if (recurrence.getByDay() != null) {
1352                                    DayAndPosition[] byDay = recurrence.getByDay();
1353    
1354                                    WeekDay weekDay = toICalWeekDay(byDay[0].getDayOfWeek());
1355    
1356                                    recur.getDayList().add(weekDay);
1357    
1358                                    Integer position = new Integer(byDay[0].getDayPosition());
1359    
1360                                    recur.getSetPosList().add(position);
1361                            }
1362                    }
1363                    else if (recurrenceType == Recurrence.YEARLY) {
1364                            recur = new Recur(Recur.YEARLY, -1);
1365    
1366                            recur.setInterval(interval);
1367                    }
1368    
1369                    Calendar until = recurrence.getUntil();
1370    
1371                    if (until != null) {
1372                            DateTime dateTime = new DateTime(until.getTime());
1373    
1374                            recur.setUntil(dateTime);
1375                    }
1376    
1377                    return recur;
1378            }
1379    
1380            protected VEvent toICalVEvent(CalEvent event, TimeZone timeZone) {
1381                    VEvent vEvent = new VEvent();
1382    
1383                    PropertyList eventProps = vEvent.getProperties();
1384    
1385                    // UID
1386    
1387                    Uid uid = new Uid(PortalUUIDUtil.generate());
1388    
1389                    eventProps.add(uid);
1390    
1391                    if (event.isAllDay()) {
1392    
1393                            // Start date
1394    
1395                            DtStart dtStart = new DtStart(
1396                                    new net.fortuna.ical4j.model.Date(event.getStartDate()));
1397    
1398                            eventProps.add(dtStart);
1399    
1400                            Property dtStartProperty = eventProps.getProperty(Property.DTSTART);
1401    
1402                            dtStartProperty.getParameters().add(Value.DATE);
1403                    }
1404                    else {
1405    
1406                            // Start date
1407    
1408                            DtStart dtStart = new DtStart(new DateTime(event.getStartDate()));
1409    
1410                            eventProps.add(dtStart);
1411    
1412                            // Duration
1413    
1414                            Duration duration = new Duration(
1415                                    new Dur(
1416                                            0, event.getDurationHour(), event.getDurationMinute(), 0));
1417    
1418                            eventProps.add(duration);
1419                    }
1420    
1421                    // Summary
1422    
1423                    Summary summary = new Summary(event.getTitle());
1424    
1425                    eventProps.add(summary);
1426    
1427                    // Description
1428    
1429                    Description description = new Description(event.getDescription());
1430    
1431                    eventProps.add(description);
1432    
1433                    // Comment
1434    
1435                    Comment comment = new Comment(event.getType());
1436    
1437                    eventProps.add(comment);
1438    
1439                    // Recurrence rule
1440    
1441                    if (event.isRepeating()) {
1442                            Recur recur = toICalRecurrence(event.getRecurrenceObj());
1443    
1444                            RRule rRule = new RRule(recur);
1445    
1446                            eventProps.add(rRule);
1447                    }
1448    
1449                    // Time zone sensitive
1450    
1451                    if (!event.getTimeZoneSensitive()) {
1452                            eventProps.add(new TimeZoneSensitive("FALSE"));
1453                    }
1454    
1455                    return vEvent;
1456            }
1457    
1458            protected WeekDay toICalWeekDay(int dayOfWeek) {
1459                    WeekDay weekDay = null;
1460    
1461                    if (dayOfWeek == Calendar.SUNDAY) {
1462                            weekDay = WeekDay.SU;
1463                    }
1464                    else if (dayOfWeek == Calendar.MONDAY) {
1465                            weekDay = WeekDay.MO;
1466                    }
1467                    else if (dayOfWeek == Calendar.TUESDAY) {
1468                            weekDay = WeekDay.TU;
1469                    }
1470                    else if (dayOfWeek == Calendar.WEDNESDAY) {
1471                            weekDay = WeekDay.WE;
1472                    }
1473                    else if (dayOfWeek == Calendar.THURSDAY) {
1474                            weekDay = WeekDay.TH;
1475                    }
1476                    else if (dayOfWeek == Calendar.FRIDAY) {
1477                            weekDay = WeekDay.FR;
1478                    }
1479                    else if (dayOfWeek == Calendar.SATURDAY) {
1480                            weekDay = WeekDay.SA;
1481                    }
1482    
1483                    return weekDay;
1484            }
1485    
1486            protected TZSRecurrence toRecurrence(RRule rRule, Calendar startDate) {
1487                    Recur recur = rRule.getRecur();
1488    
1489                    Calendar recStartCal = CalendarFactoryUtil.getCalendar(
1490                            TimeZoneUtil.getTimeZone(StringPool.UTC));
1491    
1492                    recStartCal.setTime(startDate.getTime());
1493    
1494                    TZSRecurrence recurrence = new TZSRecurrence(
1495                            recStartCal,
1496                            new com.liferay.portal.kernel.cal.Duration(1, 0, 0, 0));
1497    
1498                    recurrence.setWeekStart(Calendar.SUNDAY);
1499    
1500                    if (recur.getInterval() > 1) {
1501                            recurrence.setInterval(recur.getInterval());
1502                    }
1503    
1504                    Calendar until = Calendar.getInstance(
1505                            TimeZoneUtil.getTimeZone(StringPool.UTC));
1506    
1507                    String frequency = recur.getFrequency();
1508    
1509                    if (recur.getUntil() != null) {
1510                            until.setTime(recur.getUntil());
1511    
1512                            recurrence.setUntil(until);
1513                    }
1514                    else if (rRule.getValue().indexOf("COUNT") >= 0) {
1515                            until.setTimeInMillis(startDate.getTimeInMillis());
1516    
1517                            int addField = 0;
1518    
1519                            if (Recur.DAILY.equals(frequency)) {
1520                                    addField = Calendar.DAY_OF_YEAR;
1521                            }
1522                            else if (Recur.WEEKLY.equals(frequency)) {
1523                                    addField = Calendar.WEEK_OF_YEAR;
1524                            }
1525                            else if (Recur.MONTHLY.equals(frequency)) {
1526                                    addField = Calendar.MONTH;
1527                            }
1528                            else if (Recur.YEARLY.equals(frequency)) {
1529                                    addField = Calendar.YEAR;
1530                            }
1531    
1532                            int addAmount = recurrence.getInterval() * recur.getCount();
1533    
1534                            until.add(addField, addAmount);
1535                            until.add(Calendar.DAY_OF_YEAR, -1);
1536    
1537                            recurrence.setUntil(until);
1538                    }
1539    
1540                    if (Recur.DAILY.equals(frequency)) {
1541                            recurrence.setFrequency(Recurrence.DAILY);
1542    
1543                            List<DayAndPosition> dayPosList = new ArrayList<DayAndPosition>();
1544    
1545                            Iterator<WeekDay> itr = recur.getDayList().iterator();
1546    
1547                            while (itr.hasNext()) {
1548                                    WeekDay weekDay = itr.next();
1549    
1550                                    dayPosList.add(
1551                                            new DayAndPosition(toCalendarWeekDay(weekDay), 0));
1552                            }
1553    
1554                            if (!dayPosList.isEmpty()) {
1555                                    recurrence.setByDay(
1556                                            dayPosList.toArray(new DayAndPosition[dayPosList.size()]));
1557                            }
1558                    }
1559                    else if (Recur.WEEKLY.equals(frequency)) {
1560                            recurrence.setFrequency(Recurrence.WEEKLY);
1561    
1562                            List<DayAndPosition> dayPosList = new ArrayList<DayAndPosition>();
1563    
1564                            Iterator<WeekDay> itr = recur.getDayList().iterator();
1565    
1566                            while (itr.hasNext()) {
1567                                    WeekDay weekDay = itr.next();
1568    
1569                                    dayPosList.add(
1570                                            new DayAndPosition(toCalendarWeekDay(weekDay), 0));
1571                            }
1572    
1573                            if (!dayPosList.isEmpty()) {
1574                                    recurrence.setByDay(
1575                                            dayPosList.toArray(new DayAndPosition[dayPosList.size()]));
1576                            }
1577                    }
1578                    else if (Recur.MONTHLY.equals(frequency)) {
1579                            recurrence.setFrequency(Recurrence.MONTHLY);
1580    
1581                            Iterator<Integer> monthDayListItr =
1582                                    recur.getMonthDayList().iterator();
1583    
1584                            if (monthDayListItr.hasNext()) {
1585                                    Integer monthDay = monthDayListItr.next();
1586    
1587                                    recurrence.setByMonthDay(new int[] {monthDay.intValue()});
1588                            }
1589    
1590                            Iterator<WeekDay> dayListItr = recur.getDayList().iterator();
1591    
1592                            if (dayListItr.hasNext()) {
1593                                    WeekDay weekDay = dayListItr.next();
1594    
1595                                    DayAndPosition[] dayPos = {
1596                                            new DayAndPosition(toCalendarWeekDay(weekDay),
1597                                            weekDay.getOffset())
1598                                    };
1599    
1600                                    recurrence.setByDay(dayPos);
1601                            }
1602                    }
1603                    else if (Recur.YEARLY.equals(frequency)) {
1604                            recurrence.setFrequency(Recurrence.YEARLY);
1605                    }
1606    
1607                    return recurrence;
1608            }
1609    
1610            protected void validate(
1611                            String title, int startDateMonth, int startDateDay,
1612                            int startDateYear, int endDateMonth, int endDateDay,
1613                            int endDateYear, int durationHour, int durationMinute,
1614                            boolean allDay, boolean repeating, TZSRecurrence recurrence)
1615                    throws PortalException {
1616    
1617                    if (Validator.isNull(title)) {
1618                            throw new EventTitleException();
1619                    }
1620                    else if (!Validator.isDate(
1621                                    startDateMonth, startDateDay, startDateYear)) {
1622    
1623                            throw new EventStartDateException();
1624                    }
1625                    else if (!Validator.isDate(endDateMonth, endDateDay, endDateYear)) {
1626                            throw new EventEndDateException();
1627                    }
1628    
1629                    if (!allDay && durationHour <= 0 && durationMinute <= 0) {
1630                            throw new EventDurationException();
1631                    }
1632    
1633                    Calendar startDate = CalendarFactoryUtil.getCalendar(
1634                            startDateYear, startDateMonth, startDateDay);
1635    
1636                    if (repeating) {
1637                            Calendar until = recurrence.getUntil();
1638    
1639                            if (startDate.after(until)) {
1640                                    throw new EventEndDateException();
1641                            }
1642                    }
1643            }
1644    
1645            private static Log _log = LogFactoryUtil.getLog(
1646                    CalEventLocalServiceImpl.class);
1647    
1648            private long _eventCheckInterval =
1649                    PropsValues.CALENDAR_EVENT_CHECK_INTERVAL * Time.MINUTE;
1650    
1651    }