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