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