From da19058445c810f0c3be4374a7fe55a974efe241 Mon Sep 17 00:00:00 2001 From: GouadriaHanen <49310007+GouadriaHanen@users.noreply.github.com> Date: Mon, 22 Jan 2024 17:30:25 +0100 Subject: [PATCH 1/2] fix: Recurrent events only one event is displayed on exchange agenda- EXO-68948 (#97) before this change, when a recurrent event is added only one event is added to the exchange data without any recurrence info causing the non-display of all the events After this change, the recurrence info is added to the event and all recurrent events are displayed --- .../service/ExchangeConnectorServiceImpl.java | 109 +++++++++++++++++- .../ExchangeConnectorServiceImplTest.java | 80 ++++++++++++- 2 files changed, 179 insertions(+), 10 deletions(-) diff --git a/agenda-connectors-services/src/main/java/org/exoplatform/agendaconnector/service/ExchangeConnectorServiceImpl.java b/agenda-connectors-services/src/main/java/org/exoplatform/agendaconnector/service/ExchangeConnectorServiceImpl.java index acab459c..952a04d8 100644 --- a/agenda-connectors-services/src/main/java/org/exoplatform/agendaconnector/service/ExchangeConnectorServiceImpl.java +++ b/agenda-connectors-services/src/main/java/org/exoplatform/agendaconnector/service/ExchangeConnectorServiceImpl.java @@ -18,14 +18,19 @@ import java.time.ZoneId; import java.time.ZonedDateTime; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.Objects; +import java.time.format.TextStyle; +import java.util.*; +import microsoft.exchange.webservices.data.core.enumeration.property.time.DayOfTheWeek; +import microsoft.exchange.webservices.data.core.enumeration.property.time.Month; +import microsoft.exchange.webservices.data.core.exception.misc.ArgumentOutOfRangeException; +import microsoft.exchange.webservices.data.property.complex.recurrence.pattern.Recurrence; +import org.apache.commons.lang3.StringUtils; +import org.exoplatform.agenda.model.Event; +import org.exoplatform.agenda.model.EventRecurrence; import org.exoplatform.agenda.model.RemoteEvent; import org.exoplatform.agenda.rest.model.EventEntity; +import org.exoplatform.agenda.service.AgendaEventService; import org.exoplatform.agenda.service.AgendaRemoteEventService; import org.exoplatform.agenda.util.AgendaDateUtils; import org.exoplatform.agendaconnector.model.ExchangeUserSetting; @@ -58,13 +63,17 @@ public class ExchangeConnectorServiceImpl implements ExchangeConnectorService { private AgendaRemoteEventService agendaRemoteEventService; + private AgendaEventService agendaEventService; + private static final Log LOG = ExoLogger.getLogger(ExchangeConnectorServiceImpl.class); public ExchangeConnectorServiceImpl(ExchangeConnectorStorage exchangeConnectorStorage, - AgendaRemoteEventService agendaRemoteEventService) { + AgendaRemoteEventService agendaRemoteEventService, + AgendaEventService agendaEventService) { this.exchangeConnectorStorage = exchangeConnectorStorage; this.agendaRemoteEventService = agendaRemoteEventService; + this.agendaEventService = agendaEventService; } @Override @@ -179,6 +188,7 @@ public void pushEventToExchange(long userIdentityId, EventEntity event, ZoneId u ZonedDateTime endDate = AgendaDateUtils.parseRFC3339ToZonedDateTime(event.getEnd(), userTimeZone); appointment.setStart(AgendaDateUtils.toDate(startDate)); appointment.setEnd(AgendaDateUtils.toDate(endDate)); + appointment.setRecurrence(getEventRecurrence(event.getId())); appointment.save(new FolderId(WellKnownFolderName.Calendar), SendInvitationsMode.SendToAllAndSaveCopy); remoteEvent = new RemoteEvent(); remoteEvent.setIdentityId(userIdentityId); @@ -224,4 +234,91 @@ public void deleteExchangeEvent(long userIdentityId, long eventId) throws Illega throw new IllegalAccessException("User '" + userIdentityId + "' is not allowed to connect to exchange server"); } } + + private Recurrence getEventRecurrence(long eventId) throws ArgumentOutOfRangeException { + Event event = agendaEventService.getEventById(eventId); + EventRecurrence eventRecurrence = event.getRecurrence(); + if (eventRecurrence == null) { + return null; + } + ZonedDateTime startDate = eventRecurrence.getOverallStart(); + Recurrence recurrence; + switch (eventRecurrence.getType()) { + case DAILY: + recurrence = new Recurrence.DailyPattern(); + recurrence.setStartDate(AgendaDateUtils.toDate(startDate)); + break; + case WEEKLY: + DayOfTheWeek day = + DayOfTheWeek.valueOf(StringUtils.capitalize(AgendaDateUtils.getDayNameFromDayAbbreviation(eventRecurrence.getByDay()))); + recurrence = new Recurrence.WeeklyPattern(AgendaDateUtils.toDate(startDate), 1, day); + break; + case WEEK_DAYS: + recurrence = new Recurrence.WeeklyPattern(AgendaDateUtils.toDate(startDate), + 1, + DayOfTheWeek.Monday, + DayOfTheWeek.Tuesday, + DayOfTheWeek.Wednesday, + DayOfTheWeek.Thursday, + DayOfTheWeek.Friday); + break; + case MONTHLY: + recurrence = new Recurrence.MonthlyPattern(AgendaDateUtils.toDate(startDate), + eventRecurrence.getInterval(), + Integer.valueOf(eventRecurrence.getByMonthDay().get(0))); + break; + case YEARLY: + recurrence = new Recurrence.YearlyPattern(AgendaDateUtils.toDate(startDate), + Month.valueOf(java.time.Month.of(Integer.parseInt(eventRecurrence.getByMonth() + .get(0))) + .getDisplayName(TextStyle.FULL, Locale.ENGLISH)), + Integer.valueOf(eventRecurrence.getByMonthDay().get(0))); + break; + case CUSTOM: + recurrence = getCustomEventRecurrence(eventRecurrence); + break; + default: + throw new IllegalStateException("Can't handle type: " + eventRecurrence.getType()); + } + return recurrence; + } + + private Recurrence getCustomEventRecurrence(EventRecurrence eventRecurrence) throws ArgumentOutOfRangeException { + Recurrence recurrence; + ZonedDateTime startDate = eventRecurrence.getOverallStart(); + ZonedDateTime endDate = eventRecurrence.getOverallEnd(); + switch (eventRecurrence.getFrequency()) { + case YEARLY: + recurrence = new Recurrence.YearlyPattern(AgendaDateUtils.toDate(startDate), + Month.valueOf(java.time.Month.of(Integer.parseInt(eventRecurrence.getByMonth() + .get(0))) + .getDisplayName(TextStyle.FULL, Locale.ENGLISH)), + Integer.valueOf(eventRecurrence.getByMonthDay().get(0))); + break; + case MONTHLY: + recurrence = new Recurrence.MonthlyPattern(AgendaDateUtils.toDate(startDate), + eventRecurrence.getInterval(), + Integer.valueOf(eventRecurrence.getByMonthDay().get(0))); + break; + case WEEKLY: + List weekDays = + eventRecurrence.getByDay() + .stream() + .map(day -> DayOfTheWeek.valueOf(StringUtils.capitalize(AgendaDateUtils.getDayNameFromDayAbbreviation(Collections.singletonList(day))))) + .toList(); + recurrence = new Recurrence.WeeklyPattern(AgendaDateUtils.toDate(startDate), + eventRecurrence.getInterval(), + weekDays.toArray(new DayOfTheWeek[weekDays.size()])); + recurrence.setStartDate(AgendaDateUtils.toDate(startDate)); + recurrence.setEndDate(AgendaDateUtils.toDate(endDate)); + break; + case DAILY: + recurrence = new Recurrence.DailyPattern(); + recurrence.setStartDate(AgendaDateUtils.toDate(startDate)); + break; + default: + throw new IllegalStateException("Can't handle type: " + eventRecurrence.getType()); + } + return recurrence; + } } diff --git a/agenda-connectors-services/src/test/java/org/exoplatform/agendaconnector/service/ExchangeConnectorServiceImplTest.java b/agenda-connectors-services/src/test/java/org/exoplatform/agendaconnector/service/ExchangeConnectorServiceImplTest.java index 1f62b2e7..393053e3 100644 --- a/agenda-connectors-services/src/test/java/org/exoplatform/agendaconnector/service/ExchangeConnectorServiceImplTest.java +++ b/agenda-connectors-services/src/test/java/org/exoplatform/agendaconnector/service/ExchangeConnectorServiceImplTest.java @@ -11,8 +11,15 @@ import java.time.LocalTime; import java.time.ZoneId; import java.time.ZonedDateTime; +import java.util.Collections; import java.util.List; +import org.apache.ecs.html.Col; +import org.exoplatform.agenda.constant.EventRecurrenceFrequency; +import org.exoplatform.agenda.constant.EventRecurrenceType; +import org.exoplatform.agenda.model.Event; +import org.exoplatform.agenda.model.EventRecurrence; +import org.exoplatform.agenda.service.AgendaEventService; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -49,13 +56,18 @@ public class ExchangeConnectorServiceImplTest { private ExchangeConnectorStorage exchangeConnectorStorage; + private AgendaEventService agendaEventService; + @Before public void setUp() throws Exception { agendaRemoteEventService = mock(AgendaRemoteEventService.class); exchangeConnectorStorage = mock(ExchangeConnectorStorage.class); + agendaEventService = mock(AgendaEventService.class); exchangeService = PowerMockito.mock(ExchangeService.class); PowerMockito.whenNew(ExchangeService.class).withArguments(any()).thenReturn(exchangeService); - exchangeConnectorService = new ExchangeConnectorServiceImpl(exchangeConnectorStorage, agendaRemoteEventService); + exchangeConnectorService = new ExchangeConnectorServiceImpl(exchangeConnectorStorage, + agendaRemoteEventService, + agendaEventService); } @Test @@ -104,10 +116,71 @@ public void testCreateExchangeEvent() throws Exception { eventEntity.setEnd(AgendaDateUtils.toRFC3339Date(endDate)); eventEntity.setRemoteProviderId(1); eventEntity.setRemoteProviderName("agenda.exchangeCalendar"); + Event event = new Event(); + when(agendaEventService.getEventById(eventEntity.getId())).thenReturn(event); exchangeConnectorService.pushEventToExchange(1, eventEntity, dstTimeZone); - - // Then verify(agendaRemoteEventService, times(1)).saveRemoteEvent(any()); + EventRecurrence eventRecurrence = new EventRecurrence(); + eventRecurrence.setType(EventRecurrenceType.DAILY); + eventRecurrence.setOverallStart(ZonedDateTime.now()); + event.setRecurrence(eventRecurrence); + when(agendaEventService.getEventById(eventEntity.getId())).thenReturn(event); + exchangeConnectorService.pushEventToExchange(1, eventEntity, dstTimeZone); + verify(agendaRemoteEventService, times(2)).saveRemoteEvent(any()); + + eventRecurrence.setType(EventRecurrenceType.WEEK_DAYS); + event.setRecurrence(eventRecurrence); + when(agendaEventService.getEventById(eventEntity.getId())).thenReturn(event); + exchangeConnectorService.pushEventToExchange(1, eventEntity, dstTimeZone); + verify(agendaRemoteEventService, times(3)).saveRemoteEvent(any()); + + eventRecurrence.setType(EventRecurrenceType.WEEKLY); + eventRecurrence.setByDay(Collections.singletonList("WE")); + event.setRecurrence(eventRecurrence); + when(agendaEventService.getEventById(eventEntity.getId())).thenReturn(event); + exchangeConnectorService.pushEventToExchange(1, eventEntity, dstTimeZone); + verify(agendaRemoteEventService, times(4)).saveRemoteEvent(any()); + + eventRecurrence.setType(EventRecurrenceType.MONTHLY); + eventRecurrence.setByMonth(Collections.singletonList("1")); + eventRecurrence.setByMonthDay(Collections.singletonList("1")); + eventRecurrence.setInterval(1); + event.setRecurrence(eventRecurrence); + when(agendaEventService.getEventById(eventEntity.getId())).thenReturn(event); + exchangeConnectorService.pushEventToExchange(1, eventEntity, dstTimeZone); + verify(agendaRemoteEventService, times(5)).saveRemoteEvent(any()); + + eventRecurrence.setType(EventRecurrenceType.YEARLY); + event.setRecurrence(eventRecurrence); + when(agendaEventService.getEventById(eventEntity.getId())).thenReturn(event); + exchangeConnectorService.pushEventToExchange(1, eventEntity, dstTimeZone); + verify(agendaRemoteEventService, times(6)).saveRemoteEvent(any()); + + eventRecurrence.setType(EventRecurrenceType.CUSTOM); + + eventRecurrence.setFrequency(EventRecurrenceFrequency.YEARLY); + event.setRecurrence(eventRecurrence); + when(agendaEventService.getEventById(eventEntity.getId())).thenReturn(event); + exchangeConnectorService.pushEventToExchange(1, eventEntity, dstTimeZone); + verify(agendaRemoteEventService, times(7)).saveRemoteEvent(any()); + + eventRecurrence.setFrequency(EventRecurrenceFrequency.MONTHLY); + event.setRecurrence(eventRecurrence); + when(agendaEventService.getEventById(eventEntity.getId())).thenReturn(event); + exchangeConnectorService.pushEventToExchange(1, eventEntity, dstTimeZone); + verify(agendaRemoteEventService, times(8)).saveRemoteEvent(any()); + + eventRecurrence.setFrequency(EventRecurrenceFrequency.WEEKLY); + event.setRecurrence(eventRecurrence); + when(agendaEventService.getEventById(eventEntity.getId())).thenReturn(event); + exchangeConnectorService.pushEventToExchange(1, eventEntity, dstTimeZone); + verify(agendaRemoteEventService, times(9)).saveRemoteEvent(any()); + + eventRecurrence.setFrequency(EventRecurrenceFrequency.DAILY); + event.setRecurrence(eventRecurrence); + when(agendaEventService.getEventById(eventEntity.getId())).thenReturn(event); + exchangeConnectorService.pushEventToExchange(1, eventEntity, dstTimeZone); + verify(agendaRemoteEventService, times(10)).saveRemoteEvent(any()); } @Test @@ -141,7 +214,6 @@ public void testUpdateExchangeEvent() throws Exception { eventEntity.setRemoteProviderId(1); eventEntity.setRemoteProviderName("agenda.exchangeCalendar"); exchangeConnectorService.pushEventToExchange(1, eventEntity, dstTimeZone); - // Then verify(appointment, times(1)).update(any(), any()); } From 8960d2615bb2461fdf295613d0d8b737be10f74c Mon Sep 17 00:00:00 2001 From: GouadriaHanen <49310007+GouadriaHanen@users.noreply.github.com> Date: Tue, 23 Jan 2024 15:31:51 +0100 Subject: [PATCH 2/2] fix:fix update an event to recurrent events only one event is displayed on exchange agenda - EXO-68948 (#98) before this change, when an event is updated only one event is updated into the exchange data without any recurrence info causing the non-display of all the events After this change, the recurrence info is updated to the event and all recurrent events are displayed --- .../agendaconnector/service/ExchangeConnectorServiceImpl.java | 1 + .../service/ExchangeConnectorServiceImplTest.java | 2 ++ 2 files changed, 3 insertions(+) diff --git a/agenda-connectors-services/src/main/java/org/exoplatform/agendaconnector/service/ExchangeConnectorServiceImpl.java b/agenda-connectors-services/src/main/java/org/exoplatform/agendaconnector/service/ExchangeConnectorServiceImpl.java index 952a04d8..bcff7bf9 100644 --- a/agenda-connectors-services/src/main/java/org/exoplatform/agendaconnector/service/ExchangeConnectorServiceImpl.java +++ b/agenda-connectors-services/src/main/java/org/exoplatform/agendaconnector/service/ExchangeConnectorServiceImpl.java @@ -205,6 +205,7 @@ public void pushEventToExchange(long userIdentityId, EventEntity event, ZoneId u ZonedDateTime endDate = AgendaDateUtils.parseRFC3339ToZonedDateTime(event.getEnd(), userTimeZone); appointment.setStart(AgendaDateUtils.toDate(startDate)); appointment.setEnd(AgendaDateUtils.toDate(endDate)); + appointment.setRecurrence(getEventRecurrence(event.getId())); appointment.update(ConflictResolutionMode.AlwaysOverwrite, SendInvitationsOrCancellationsMode.SendToAllAndSaveCopy); } } catch (ServiceLocalException e) { diff --git a/agenda-connectors-services/src/test/java/org/exoplatform/agendaconnector/service/ExchangeConnectorServiceImplTest.java b/agenda-connectors-services/src/test/java/org/exoplatform/agendaconnector/service/ExchangeConnectorServiceImplTest.java index 393053e3..48f3b634 100644 --- a/agenda-connectors-services/src/test/java/org/exoplatform/agendaconnector/service/ExchangeConnectorServiceImplTest.java +++ b/agenda-connectors-services/src/test/java/org/exoplatform/agendaconnector/service/ExchangeConnectorServiceImplTest.java @@ -213,6 +213,8 @@ public void testUpdateExchangeEvent() throws Exception { eventEntity.setEnd(AgendaDateUtils.toRFC3339Date(endDate)); eventEntity.setRemoteProviderId(1); eventEntity.setRemoteProviderName("agenda.exchangeCalendar"); + Event event = new Event(); + when(agendaEventService.getEventById(eventEntity.getId())).thenReturn(event); exchangeConnectorService.pushEventToExchange(1, eventEntity, dstTimeZone); // Then verify(appointment, times(1)).update(any(), any());