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