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