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