diff --git a/schoolDomain/src/main/kotlin/com/intelligentbackpack/schooldomain/entities/calendar/alteration/AlterationEvent.kt b/schoolDomain/src/main/kotlin/com/intelligentbackpack/schooldomain/entities/calendar/alteration/AlterationEvent.kt new file mode 100644 index 00000000..f258a63d --- /dev/null +++ b/schoolDomain/src/main/kotlin/com/intelligentbackpack/schooldomain/entities/calendar/alteration/AlterationEvent.kt @@ -0,0 +1,12 @@ +package com.intelligentbackpack.schooldomain.entities.calendar.alteration + +import com.intelligentbackpack.schooldomain.entities.calendar.CalendarEvent + +/** + * Represents an event that alters the original calendar. + * + * @property event the event that alters the original calendar + */ +interface AlterationEvent { + val event: CalendarEvent +} diff --git a/schoolDomain/src/main/kotlin/com/intelligentbackpack/schooldomain/entities/calendar/alteration/AlterationFactory.kt b/schoolDomain/src/main/kotlin/com/intelligentbackpack/schooldomain/entities/calendar/alteration/AlterationFactory.kt new file mode 100644 index 00000000..d575efc1 --- /dev/null +++ b/schoolDomain/src/main/kotlin/com/intelligentbackpack/schooldomain/entities/calendar/alteration/AlterationFactory.kt @@ -0,0 +1,235 @@ +package com.intelligentbackpack.schooldomain.entities.calendar.alteration + +import com.intelligentbackpack.schooldomain.entities.calendar.CalendarEvent +import com.intelligentbackpack.schooldomain.entities.calendar.DateEvent +import com.intelligentbackpack.schooldomain.entities.calendar.WeekEvent +import com.intelligentbackpack.schooldomain.exceptions.EventDateException +import java.time.LocalDate + +/** + * Factory for creating alteration of events. + * + */ +object AlterationFactory { + private fun isEventOnDate(event: CalendarEvent, date: LocalDate): Boolean = + when (event) { + is DateEvent -> event.date == date + is WeekEvent -> + event.day == date.dayOfWeek && + event.fromDate <= date && event.toDate >= date + + else -> false + } + + /** + * Creates an alteration for a new event. + * + * @param newEvent the new event + * @return the alteration for the new event + */ + fun createNewEvent(newEvent: CalendarEvent): AlterationEvent = + object : NewEvent { + override fun isNewEventOnDate(date: LocalDate): Boolean = isEventOnDate(newEvent, date) + + override val event: CalendarEvent + get() = newEvent + } + + private fun checkCancelOriginalEventSingleDay( + originalEvent: CalendarEvent, + date: LocalDate, + alterationEvent: AlterationEvent, + ): AlterationEvent { + when (originalEvent) { + is DateEvent -> { + if (originalEvent.date != date) { + throw EventDateException() + } else { + return alterationEvent + } + } + + is WeekEvent -> { + if (originalEvent.day != date.dayOfWeek) { + throw EventDateException() + } else if (originalEvent.fromDate.isAfter(date) || originalEvent.toDate.isBefore(date)) { + throw EventDateException() + } else { + return alterationEvent + } + } + + else -> { + throw IllegalArgumentException("Original event must be a DateEvent or WeekEvent") + } + } + } + + private fun checkCancelOriginalEventIntervalOfDays( + originalEvent: CalendarEvent, + initialDate: LocalDate, + finalDate: LocalDate, + alterationEvent: AlterationEvent, + ): AlterationEvent { + if (initialDate.isAfter(finalDate)) { + throw EventDateException() + } else { + when (originalEvent) { + is DateEvent -> { + if (originalEvent.date !in initialDate..finalDate) { + throw EventDateException() + } else { + return alterationEvent + } + } + + is WeekEvent -> { + if (originalEvent.fromDate.isAfter(initialDate) || originalEvent.toDate.isBefore(finalDate)) { + throw EventDateException() + } else { + return alterationEvent + } + } + + else -> { + throw IllegalArgumentException("Original event must be a DateEvent or WeekEvent") + } + } + } + } + + private fun checkRescheduleEvent( + originalEvent: CalendarEvent, + newEvent: CalendarEvent, + checkCancelOriginalEvent: () -> AlterationEvent, + ): AlterationEvent { + if (originalEvent == newEvent) { + throw IllegalArgumentException("New event must be different from rescheduled event") + } else { + return checkCancelOriginalEvent() + } + } + + /** + * Creates an alteration for a rescheduled event that occurs in a single day. + * + * @param newEvent the new event + * @param dateOriginalEvent the date of the original event + * @param originalEvent the original event + * @return the alteration for the rescheduled event + * @throws IllegalArgumentException if the new event is the same as the original event + * @throws EventDateException if the date of the original event is different from the date of the new event + * @throws IllegalArgumentException if the original event is not a [DateEvent] or [WeekEvent] + */ + fun createRescheduleSingleDayEvent( + newEvent: CalendarEvent, + dateOriginalEvent: LocalDate, + originalEvent: CalendarEvent, + ): AlterationEvent { + val alterationEvent = object : RescheduleEvent, SingleDayAlteration { + override val event: CalendarEvent + get() = newEvent + override val date: LocalDate + get() = dateOriginalEvent + override val originalEvent: CalendarEvent + get() = originalEvent + + override fun wasEventRescheduledOnDate(date: LocalDate): Boolean = this.date == date + + override fun isNewEventOnDate(date: LocalDate): Boolean = isEventOnDate(newEvent, date) + } + return checkRescheduleEvent(originalEvent, newEvent) { + checkCancelOriginalEventSingleDay(originalEvent, dateOriginalEvent, alterationEvent) + } + } + + /** + * Creates an alteration for a rescheduled event that occurs in an interval of days. + * + * @param initialDate the initial date of the interval + * @param finalDate the final date of the interval + * @param originalEvent the original event + * @param newEvent the new event + * @return the alteration for the rescheduled event + * @throws IllegalArgumentException if the new event is the same as the original event + * @throws EventDateException if the interval of the original event is different from the interval of the new event + * @throws IllegalArgumentException if the original event is not a [DateEvent] or [WeekEvent] + */ + fun createRescheduleIntervalOfDaysEvent( + initialDate: LocalDate, + finalDate: LocalDate, + originalEvent: CalendarEvent, + newEvent: CalendarEvent, + ): AlterationEvent { + val alterationEvent = object : RescheduleEvent, IntervalOfDaysAlteration { + override val event: CalendarEvent + get() = newEvent + override val initialDate: LocalDate + get() = initialDate + override val finalDate: LocalDate + get() = finalDate + override val originalEvent: CalendarEvent + get() = originalEvent + + override fun wasEventRescheduledOnDate(date: LocalDate): Boolean = + date in initialDate..finalDate + + override fun isNewEventOnDate(date: LocalDate): Boolean = isEventOnDate(newEvent, date) + } + return checkRescheduleEvent(originalEvent, newEvent) { + checkCancelOriginalEventIntervalOfDays(originalEvent, initialDate, finalDate, alterationEvent) + } + } + + /** + * Creates an alteration for a cancelled event that occurs in a single day. + * + * @param date the date of the cancelled event + * @param cancelledEvent the cancelled event + * @return the alteration for the cancelled event + * @throws EventDateException if the date of the cancelled event is different from the date of the new event + * @throws IllegalArgumentException if the cancelled event is not a [DateEvent] or [WeekEvent] + */ + fun createCancelSingleDayEvent(date: LocalDate, cancelledEvent: CalendarEvent): AlterationEvent { + val alterationEvent = object : CancelEvent, SingleDayAlteration { + override fun isEventCancelledOnDate(date: LocalDate): Boolean = + date == this.date + + override val event: CalendarEvent + get() = cancelledEvent + override val date: LocalDate + get() = date + } + return checkCancelOriginalEventSingleDay(cancelledEvent, date, alterationEvent) + } + + /** + * Creates an alteration for a cancelled event that occurs in an interval of days. + * + * @param initialDate the initial date of the interval + * @param finalDate the final date of the interval + * @param cancelledEvent the cancelled event + * @return the alteration for the cancelled event + * @throws EventDateException if the interval of the cancelled event is different from the interval of the new event + * @throws IllegalArgumentException if the cancelled event is not a [DateEvent] or [WeekEvent] + */ + fun createCancelIntervalOfDaysEvent( + initialDate: LocalDate, + finalDate: LocalDate, + cancelledEvent: CalendarEvent, + ): AlterationEvent { + val alterationEvent = object : CancelEvent, IntervalOfDaysAlteration { + override fun isEventCancelledOnDate(date: LocalDate): Boolean { + return date in initialDate..finalDate + } + + override val event: CalendarEvent + get() = cancelledEvent + override val initialDate: LocalDate + get() = initialDate + override val finalDate: LocalDate + get() = finalDate + } + return checkCancelOriginalEventIntervalOfDays(cancelledEvent, initialDate, finalDate, alterationEvent) + } +} diff --git a/schoolDomain/src/main/kotlin/com/intelligentbackpack/schooldomain/entities/calendar/alteration/AlterationType.kt b/schoolDomain/src/main/kotlin/com/intelligentbackpack/schooldomain/entities/calendar/alteration/AlterationType.kt deleted file mode 100644 index 32964eb6..00000000 --- a/schoolDomain/src/main/kotlin/com/intelligentbackpack/schooldomain/entities/calendar/alteration/AlterationType.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.intelligentbackpack.schooldomain.entities.calendar.alteration - -enum class AlterationType { - CANCELLED, - RESCHEDULED, - CHANGED_PROFESSOR, - CHANGED_SUBJECT, -} diff --git a/schoolDomain/src/main/kotlin/com/intelligentbackpack/schooldomain/entities/calendar/alteration/CancelEvent.kt b/schoolDomain/src/main/kotlin/com/intelligentbackpack/schooldomain/entities/calendar/alteration/CancelEvent.kt new file mode 100644 index 00000000..08cab816 --- /dev/null +++ b/schoolDomain/src/main/kotlin/com/intelligentbackpack/schooldomain/entities/calendar/alteration/CancelEvent.kt @@ -0,0 +1,18 @@ +package com.intelligentbackpack.schooldomain.entities.calendar.alteration + +import java.time.LocalDate + +/** + * Represents an event that cancel an event from the original calendar. + * + * @property event the event that has been cancelled + */ +interface CancelEvent : AlterationEvent { + /** + * Checks if the event is cancelled on the given date. + * + * @param date the date to check + * @return true if the event is cancelled on the given date, false otherwise + */ + fun isEventCancelledOnDate(date: LocalDate): Boolean +} diff --git a/schoolDomain/src/main/kotlin/com/intelligentbackpack/schooldomain/entities/calendar/alteration/IntervalOfDaysAlteration.kt b/schoolDomain/src/main/kotlin/com/intelligentbackpack/schooldomain/entities/calendar/alteration/IntervalOfDaysAlteration.kt new file mode 100644 index 00000000..92a4b150 --- /dev/null +++ b/schoolDomain/src/main/kotlin/com/intelligentbackpack/schooldomain/entities/calendar/alteration/IntervalOfDaysAlteration.kt @@ -0,0 +1,14 @@ +package com.intelligentbackpack.schooldomain.entities.calendar.alteration + +import java.time.LocalDate + +/** + * Represents an alteration event that alters the original calendar for an interval of days + * + * @property initialDate the initial date of the interval + * @property finalDate the final date of the interval + */ +interface IntervalOfDaysAlteration : AlterationEvent { + val initialDate: LocalDate + val finalDate: LocalDate +} diff --git a/schoolDomain/src/main/kotlin/com/intelligentbackpack/schooldomain/entities/calendar/alteration/NewEvent.kt b/schoolDomain/src/main/kotlin/com/intelligentbackpack/schooldomain/entities/calendar/alteration/NewEvent.kt new file mode 100644 index 00000000..ae742991 --- /dev/null +++ b/schoolDomain/src/main/kotlin/com/intelligentbackpack/schooldomain/entities/calendar/alteration/NewEvent.kt @@ -0,0 +1,19 @@ +package com.intelligentbackpack.schooldomain.entities.calendar.alteration + +import java.time.LocalDate + +/** + * Represents a new event that is added to the original calendar. + * + * @property event the new event + */ +interface NewEvent : AlterationEvent { + + /** + * Checks if the new event is on the given date. + * + * @param date the date to check + * @return true if the new event is on the given date, false otherwise + */ + fun isNewEventOnDate(date: LocalDate): Boolean +} diff --git a/schoolDomain/src/main/kotlin/com/intelligentbackpack/schooldomain/entities/calendar/alteration/RescheduleEvent.kt b/schoolDomain/src/main/kotlin/com/intelligentbackpack/schooldomain/entities/calendar/alteration/RescheduleEvent.kt new file mode 100644 index 00000000..72963057 --- /dev/null +++ b/schoolDomain/src/main/kotlin/com/intelligentbackpack/schooldomain/entities/calendar/alteration/RescheduleEvent.kt @@ -0,0 +1,30 @@ +package com.intelligentbackpack.schooldomain.entities.calendar.alteration + +import com.intelligentbackpack.schooldomain.entities.calendar.CalendarEvent +import java.time.LocalDate + +/** + * Represents an event that reschedules an event from the original calendar. + * + * @property originalEvent the event that has been rescheduled + * @property event the new event + */ +interface RescheduleEvent : AlterationEvent { + val originalEvent: CalendarEvent + + /** + * Checks if the event rescheduled was on the given date. + * + * @param date the date to check + * @return true if the event rescheduled was on the given date, false otherwise + */ + fun wasEventRescheduledOnDate(date: LocalDate): Boolean + + /** + * Checks if the new event is on the given date. + * + * @param date the date to check + * @return true if the new event is on the given date, false otherwise + */ + fun isNewEventOnDate(date: LocalDate): Boolean +} diff --git a/schoolDomain/src/main/kotlin/com/intelligentbackpack/schooldomain/entities/calendar/alteration/SingleDayAlteration.kt b/schoolDomain/src/main/kotlin/com/intelligentbackpack/schooldomain/entities/calendar/alteration/SingleDayAlteration.kt new file mode 100644 index 00000000..6651882b --- /dev/null +++ b/schoolDomain/src/main/kotlin/com/intelligentbackpack/schooldomain/entities/calendar/alteration/SingleDayAlteration.kt @@ -0,0 +1,12 @@ +package com.intelligentbackpack.schooldomain.entities.calendar.alteration + +import java.time.LocalDate + +/** + * Represents an alteration event that alters the original calendar for a single day + * + * @property date the date in which the alteration occurs + */ +interface SingleDayAlteration { + val date: LocalDate +}