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$]", "[$EVENT_START_DATE$]",
1225                                            "[$EVENT_TITLE$]", "[$FROM_ADDRESS$]", "[$FROM_NAME$]",
1226                                            "[$PORTAL_URL$]", "[$PORTLET_NAME$]", "[$TO_ADDRESS$]",
1227                                            "[$TO_NAME$]"
1228                                    },
1229                                    new String[] {
1230                                            event.getLocation(),
1231                                            dateFormatDateTime.format(startDate.getTime()),
1232                                            event.getTitle(), fromAddress, fromName,
1233                                            company.getPortalURL(event.getGroupId()), portletName,
1234                                            HtmlUtil.escape(toAddress), HtmlUtil.escape(toName),
1235                                    });
1236    
1237                            body = StringUtil.replace(
1238                                    body,
1239                                    new String[] {
1240                                            "[$EVENT_LOCATION$]", "[$EVENT_START_DATE$]",
1241                                            "[$EVENT_TITLE$]", "[$FROM_ADDRESS$]", "[$FROM_NAME$]",
1242                                            "[$PORTAL_URL$]", "[$PORTLET_NAME$]", "[$TO_ADDRESS$]",
1243                                            "[$TO_NAME$]"
1244                                    },
1245                                    new String[] {
1246                                            event.getLocation(),
1247                                            dateFormatDateTime.format(startDate.getTime()),
1248                                            event.getTitle(), fromAddress, fromName,
1249                                            company.getPortalURL(event.getGroupId()), portletName,
1250                                            HtmlUtil.escape(toAddress), HtmlUtil.escape(toName),
1251                                    });
1252    
1253                            if ((remindBy == CalEventConstants.REMIND_BY_EMAIL) ||
1254                                    (remindBy == CalEventConstants.REMIND_BY_SMS)) {
1255    
1256                                    InternetAddress from = new InternetAddress(
1257                                            fromAddress, fromName);
1258    
1259                                    InternetAddress to = new InternetAddress(toAddress, toName);
1260    
1261                                    MailMessage message = new MailMessage(
1262                                            from, to, subject, body, true);
1263    
1264                                    mailService.sendEmail(message);
1265                            }
1266                            else if ((remindBy == CalEventConstants.REMIND_BY_AIM) &&
1267                                             (Validator.isNotNull(contact.getAimSn()))) {
1268    
1269                                    AIMConnector.send(contact.getAimSn(), body);
1270                            }
1271                            else if ((remindBy == CalEventConstants.REMIND_BY_ICQ) &&
1272                                             (Validator.isNotNull(contact.getIcqSn()))) {
1273    
1274                                    ICQConnector.send(contact.getIcqSn(), body);
1275                            }
1276                            else if ((remindBy == CalEventConstants.REMIND_BY_MSN) &&
1277                                             (Validator.isNotNull(contact.getMsnSn()))) {
1278    
1279                                    MSNConnector.send(contact.getMsnSn(), body);
1280                            }
1281                            else if ((remindBy == CalEventConstants.REMIND_BY_YM) &&
1282                                             (Validator.isNotNull(contact.getYmSn()))) {
1283    
1284                                    YMConnector.send(contact.getYmSn(), body);
1285                            }
1286                    }
1287                    catch (Exception e) {
1288                            _log.error(e, e);
1289                    }
1290            }
1291    
1292            protected void remindUser(
1293                    CalEvent event, User user, Calendar startDate, Calendar now) {
1294    
1295                    long diff =
1296                            (startDate.getTime().getTime() - now.getTime().getTime()) /
1297                                    _CALENDAR_EVENT_CHECK_INTERVAL;
1298    
1299                    if ((diff ==
1300                                    (event.getFirstReminder() / _CALENDAR_EVENT_CHECK_INTERVAL)) ||
1301                            (diff ==
1302                                    (event.getSecondReminder() / _CALENDAR_EVENT_CHECK_INTERVAL))) {
1303    
1304                            remindUser(event, user, startDate);
1305                    }
1306            }
1307    
1308            protected Calendar toCalendar(
1309                    DateProperty date, TimeZone timeZone, boolean timeZoneSensitive) {
1310    
1311                    Calendar cal = null;
1312    
1313                    if (isICal4jDateOnly(date)) {
1314                            cal = Calendar.getInstance();
1315                    }
1316                    else if (!timeZoneSensitive) {
1317                            cal = Calendar.getInstance(
1318                                    TimeZoneUtil.getTimeZone(StringPool.UTC));
1319                    }
1320                    else {
1321                            cal = Calendar.getInstance(timeZone);
1322                    }
1323    
1324                    return cal;
1325            }
1326    
1327            protected int toCalendarWeekDay(WeekDay weekDay) {
1328                    int dayOfWeeek = 0;
1329    
1330                    if (weekDay.getDay().equals(WeekDay.SU.getDay())) {
1331                            dayOfWeeek = Calendar.SUNDAY;
1332                    }
1333                    else if (weekDay.getDay().equals(WeekDay.MO.getDay())) {
1334                            dayOfWeeek = Calendar.MONDAY;
1335                    }
1336                    else if (weekDay.getDay().equals(WeekDay.TU.getDay())) {
1337                            dayOfWeeek = Calendar.TUESDAY;
1338                    }
1339                    else if (weekDay.getDay().equals(WeekDay.WE.getDay())) {
1340                            dayOfWeeek = Calendar.WEDNESDAY;
1341                    }
1342                    else if (weekDay.getDay().equals(WeekDay.TH.getDay())) {
1343                            dayOfWeeek = Calendar.THURSDAY;
1344                    }
1345                    else if (weekDay.getDay().equals(WeekDay.FR.getDay())) {
1346                            dayOfWeeek = Calendar.FRIDAY;
1347                    }
1348                    else if (weekDay.getDay().equals(WeekDay.SA.getDay())) {
1349                            dayOfWeeek = Calendar.SATURDAY;
1350                    }
1351    
1352                    return dayOfWeeek;
1353            }
1354    
1355            protected net.fortuna.ical4j.model.Calendar toICalCalendar(
1356                    long userId, List<CalEvent> events)
1357                    throws PortalException, SystemException {
1358    
1359                    net.fortuna.ical4j.model.Calendar iCal =
1360                            new net.fortuna.ical4j.model.Calendar();
1361    
1362                    ProdId prodId = new ProdId(
1363                            "-//Liferay Inc//Liferay Portal " + ReleaseInfo.getVersion() +
1364                            "//EN");
1365    
1366                    PropertyList propertiesList = iCal.getProperties();
1367    
1368                    propertiesList.add(prodId);
1369                    propertiesList.add(Version.VERSION_2_0);
1370                    propertiesList.add(CalScale.GREGORIAN);
1371    
1372                    // LPS-6058
1373    
1374                    propertiesList.add(Method.PUBLISH);
1375    
1376                    User user = userPersistence.findByPrimaryKey(userId);
1377                    TimeZone timeZone = user.getTimeZone();
1378    
1379                    List<VEvent> components = iCal.getComponents();
1380    
1381                    Iterator<CalEvent> itr = events.iterator();
1382    
1383                    while (itr.hasNext()) {
1384                            CalEvent event = itr.next();
1385    
1386                            components.add(toICalVEvent(event, timeZone));
1387                    }
1388    
1389                    return iCal;
1390            }
1391    
1392            protected Recur toICalRecurrence(TZSRecurrence recurrence) {
1393                    Recur recur = null;
1394    
1395                    int recurrenceType = recurrence.getFrequency();
1396    
1397                    int interval = recurrence.getInterval();
1398    
1399                    if (recurrenceType == Recurrence.DAILY) {
1400                            recur = new Recur(Recur.DAILY, -1);
1401    
1402                            if (interval >= 1) {
1403                                    recur.setInterval(interval);
1404                            }
1405    
1406                            DayAndPosition[] byDay = recurrence.getByDay();
1407    
1408                            if (byDay != null) {
1409                                    for (int i = 0; i < byDay.length; i++) {
1410                                            WeekDay weekDay = toICalWeekDay(byDay[i].getDayOfWeek());
1411    
1412                                            recur.getDayList().add(weekDay);
1413                                    }
1414                            }
1415    
1416                    }
1417                    else if (recurrenceType == Recurrence.WEEKLY) {
1418                            recur = new Recur(Recur.WEEKLY, -1);
1419    
1420                            recur.setInterval(interval);
1421    
1422                            DayAndPosition[] byDay = recurrence.getByDay();
1423    
1424                            if (byDay != null) {
1425                                    for (int i = 0; i < byDay.length; i++) {
1426                                            WeekDay weekDay = toICalWeekDay(byDay[i].getDayOfWeek());
1427    
1428                                            recur.getDayList().add(weekDay);
1429                                    }
1430                            }
1431                    }
1432                    else if (recurrenceType == Recurrence.MONTHLY) {
1433                            recur = new Recur(Recur.MONTHLY, -1);
1434    
1435                            recur.setInterval(interval);
1436    
1437                            int[] byMonthDay = recurrence.getByMonthDay();
1438    
1439                            if (byMonthDay != null) {
1440                                    Integer monthDay = new Integer(byMonthDay[0]);
1441    
1442                                    recur.getMonthDayList().add(monthDay);
1443                            }
1444                            else if (recurrence.getByDay() != null) {
1445                                    DayAndPosition[] byDay = recurrence.getByDay();
1446    
1447                                    WeekDay weekDay = toICalWeekDay(byDay[0].getDayOfWeek());
1448    
1449                                    recur.getDayList().add(weekDay);
1450    
1451                                    Integer position = new Integer(byDay[0].getDayPosition());
1452    
1453                                    recur.getSetPosList().add(position);
1454                            }
1455                    }
1456                    else if (recurrenceType == Recurrence.YEARLY) {
1457                            recur = new Recur(Recur.YEARLY, -1);
1458    
1459                            recur.setInterval(interval);
1460                    }
1461    
1462                    Calendar until = recurrence.getUntil();
1463    
1464                    if (until != null) {
1465                            DateTime dateTime = new DateTime(until.getTime());
1466    
1467                            recur.setUntil(dateTime);
1468                    }
1469    
1470                    return recur;
1471            }
1472    
1473            protected VEvent toICalVEvent(CalEvent event, TimeZone timeZone) {
1474                    VEvent vEvent = new VEvent();
1475    
1476                    PropertyList eventProps = vEvent.getProperties();
1477    
1478                    // UID
1479    
1480                    Uid uid = new Uid(event.getUuid());
1481    
1482                    eventProps.add(uid);
1483    
1484                    if (event.isAllDay()) {
1485    
1486                            // Start date
1487    
1488                            DtStart dtStart = new DtStart(
1489                                    new net.fortuna.ical4j.model.Date(event.getStartDate()));
1490    
1491                            eventProps.add(dtStart);
1492                    }
1493                    else {
1494    
1495                            // Start date
1496    
1497                            DtStart dtStart = new DtStart(new DateTime(event.getStartDate()));
1498    
1499                            eventProps.add(dtStart);
1500    
1501                            // Duration
1502    
1503                            Dur dur = new Dur(
1504                                    0, event.getDurationHour(), event.getDurationMinute(), 0);
1505    
1506                            DtEnd dtEnd = new DtEnd(new DateTime(dur.getTime(
1507                                    event.getStartDate())));
1508    
1509                            eventProps.add(dtEnd);
1510                    }
1511    
1512                    // Summary
1513    
1514                    Summary summary = new Summary(event.getTitle());
1515    
1516                    eventProps.add(summary);
1517    
1518                    // Description
1519    
1520                    Description description = new Description(event.getDescription());
1521    
1522                    eventProps.add(description);
1523    
1524                    // Location
1525    
1526                    Location location = new Location(event.getLocation());
1527    
1528                    eventProps.add(location);
1529    
1530                    // Comment
1531    
1532                    Comment comment = new Comment(event.getType());
1533    
1534                    eventProps.add(comment);
1535    
1536                    // Recurrence rule
1537    
1538                    if (event.isRepeating()) {
1539                            Recur recur = toICalRecurrence(event.getRecurrenceObj());
1540    
1541                            RRule rRule = new RRule(recur);
1542    
1543                            eventProps.add(rRule);
1544                    }
1545    
1546                    // Time zone sensitive
1547    
1548                    if (!event.getTimeZoneSensitive()) {
1549                            eventProps.add(new TimeZoneSensitive("FALSE"));
1550                    }
1551    
1552                    return vEvent;
1553            }
1554    
1555            protected WeekDay toICalWeekDay(int dayOfWeek) {
1556                    WeekDay weekDay = null;
1557    
1558                    if (dayOfWeek == Calendar.SUNDAY) {
1559                            weekDay = WeekDay.SU;
1560                    }
1561                    else if (dayOfWeek == Calendar.MONDAY) {
1562                            weekDay = WeekDay.MO;
1563                    }
1564                    else if (dayOfWeek == Calendar.TUESDAY) {
1565                            weekDay = WeekDay.TU;
1566                    }
1567                    else if (dayOfWeek == Calendar.WEDNESDAY) {
1568                            weekDay = WeekDay.WE;
1569                    }
1570                    else if (dayOfWeek == Calendar.THURSDAY) {
1571                            weekDay = WeekDay.TH;
1572                    }
1573                    else if (dayOfWeek == Calendar.FRIDAY) {
1574                            weekDay = WeekDay.FR;
1575                    }
1576                    else if (dayOfWeek == Calendar.SATURDAY) {
1577                            weekDay = WeekDay.SA;
1578                    }
1579    
1580                    return weekDay;
1581            }
1582    
1583            protected TZSRecurrence toRecurrence(RRule rRule, Calendar startDate) {
1584                    Recur recur = rRule.getRecur();
1585    
1586                    Calendar recStartCal = CalendarFactoryUtil.getCalendar(
1587                            TimeZoneUtil.getTimeZone(StringPool.UTC));
1588    
1589                    recStartCal.setTime(startDate.getTime());
1590    
1591                    TZSRecurrence recurrence = new TZSRecurrence(
1592                            recStartCal,
1593                            new com.liferay.portal.kernel.cal.Duration(1, 0, 0, 0));
1594    
1595                    recurrence.setWeekStart(Calendar.SUNDAY);
1596    
1597                    if (recur.getInterval() > 1) {
1598                            recurrence.setInterval(recur.getInterval());
1599                    }
1600    
1601                    Calendar until = Calendar.getInstance(
1602                            TimeZoneUtil.getTimeZone(StringPool.UTC));
1603    
1604                    String frequency = recur.getFrequency();
1605    
1606                    if (recur.getUntil() != null) {
1607                            until.setTime(recur.getUntil());
1608    
1609                            recurrence.setUntil(until);
1610                    }
1611                    else if (rRule.getValue().indexOf("COUNT") >= 0) {
1612                            until.setTimeInMillis(startDate.getTimeInMillis());
1613    
1614                            int addField = 0;
1615    
1616                            if (Recur.DAILY.equals(frequency)) {
1617                                    addField = Calendar.DAY_OF_YEAR;
1618                            }
1619                            else if (Recur.WEEKLY.equals(frequency)) {
1620                                    addField = Calendar.WEEK_OF_YEAR;
1621                            }
1622                            else if (Recur.MONTHLY.equals(frequency)) {
1623                                    addField = Calendar.MONTH;
1624                            }
1625                            else if (Recur.YEARLY.equals(frequency)) {
1626                                    addField = Calendar.YEAR;
1627                            }
1628    
1629                            int addAmount = recurrence.getInterval() * recur.getCount();
1630    
1631                            until.add(addField, addAmount);
1632                            until.add(Calendar.DAY_OF_YEAR, -1);
1633    
1634                            recurrence.setUntil(until);
1635                    }
1636    
1637                    if (Recur.DAILY.equals(frequency)) {
1638                            recurrence.setFrequency(Recurrence.DAILY);
1639    
1640                            List<DayAndPosition> dayPosList = new ArrayList<DayAndPosition>();
1641    
1642                            Iterator<WeekDay> itr = recur.getDayList().iterator();
1643    
1644                            while (itr.hasNext()) {
1645                                    WeekDay weekDay = itr.next();
1646    
1647                                    dayPosList.add(
1648                                            new DayAndPosition(toCalendarWeekDay(weekDay), 0));
1649                            }
1650    
1651                            if (!dayPosList.isEmpty()) {
1652                                    recurrence.setByDay(
1653                                            dayPosList.toArray(new DayAndPosition[dayPosList.size()]));
1654                            }
1655                    }
1656                    else if (Recur.WEEKLY.equals(frequency)) {
1657                            recurrence.setFrequency(Recurrence.WEEKLY);
1658    
1659                            List<DayAndPosition> dayPosList = new ArrayList<DayAndPosition>();
1660    
1661                            Iterator<WeekDay> itr = recur.getDayList().iterator();
1662    
1663                            while (itr.hasNext()) {
1664                                    WeekDay weekDay = itr.next();
1665    
1666                                    dayPosList.add(
1667                                            new DayAndPosition(toCalendarWeekDay(weekDay), 0));
1668                            }
1669    
1670                            if (!dayPosList.isEmpty()) {
1671                                    recurrence.setByDay(
1672                                            dayPosList.toArray(new DayAndPosition[dayPosList.size()]));
1673                            }
1674                    }
1675                    else if (Recur.MONTHLY.equals(frequency)) {
1676                            recurrence.setFrequency(Recurrence.MONTHLY);
1677    
1678                            Iterator<Integer> monthDayListItr =
1679                                    recur.getMonthDayList().iterator();
1680    
1681                            if (monthDayListItr.hasNext()) {
1682                                    Integer monthDay = monthDayListItr.next();
1683    
1684                                    recurrence.setByMonthDay(new int[] {monthDay.intValue()});
1685                            }
1686    
1687                            Iterator<WeekDay> dayListItr = recur.getDayList().iterator();
1688    
1689                            if (dayListItr.hasNext()) {
1690                                    WeekDay weekDay = dayListItr.next();
1691    
1692                                    DayAndPosition[] dayPos = {
1693                                            new DayAndPosition(toCalendarWeekDay(weekDay),
1694                                            weekDay.getOffset())
1695                                    };
1696    
1697                                    recurrence.setByDay(dayPos);
1698                            }
1699                    }
1700                    else if (Recur.YEARLY.equals(frequency)) {
1701                            recurrence.setFrequency(Recurrence.YEARLY);
1702                    }
1703    
1704                    return recurrence;
1705            }
1706    
1707            protected void validate(
1708                            String title, int startDateMonth, int startDateDay,
1709                            int startDateYear, int endDateMonth, int endDateDay,
1710                            int endDateYear, int durationHour, int durationMinute,
1711                            boolean allDay, boolean repeating, TZSRecurrence recurrence)
1712                    throws PortalException {
1713    
1714                    if (Validator.isNull(title)) {
1715                            throw new EventTitleException();
1716                    }
1717                    else if (!Validator.isDate(
1718                                    startDateMonth, startDateDay, startDateYear)) {
1719    
1720                            throw new EventStartDateException();
1721                    }
1722                    else if (!Validator.isDate(endDateMonth, endDateDay, endDateYear)) {
1723                            throw new EventEndDateException();
1724                    }
1725    
1726                    if (!allDay && durationHour <= 0 && durationMinute <= 0) {
1727                            throw new EventDurationException();
1728                    }
1729    
1730                    Calendar startDate = CalendarFactoryUtil.getCalendar(
1731                            startDateYear, startDateMonth, startDateDay);
1732    
1733                    if (repeating) {
1734                            Calendar until = recurrence.getUntil();
1735    
1736                            if (startDate.after(until)) {
1737                                    throw new EventEndDateException();
1738                            }
1739                    }
1740            }
1741    
1742            private static final long _CALENDAR_EVENT_CHECK_INTERVAL =
1743                    PropsValues.CALENDAR_EVENT_CHECK_INTERVAL * Time.MINUTE;
1744    
1745            private static Log _log = LogFactoryUtil.getLog(
1746                    CalEventLocalServiceImpl.class);
1747    
1748    }