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