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