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