-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- 기존의 Util Class의 메서드로 존재하던 구조 대신 전략 패턴 적용해서 클래스 단위로 분리 - 이에 따른 테스트 수정 Resolves: #38
- Loading branch information
Showing
12 changed files
with
735 additions
and
1 deletion.
There are no files selected for viewing
16 changes: 16 additions & 0 deletions
16
...l-core/src/main/java/com/wypl/wyplcore/schedule/service/repetition/RepetitionService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package com.wypl.wyplcore.schedule.service.repetition; | ||
|
||
import java.time.LocalDate; | ||
import java.util.List; | ||
|
||
import com.wypl.jpacalendardomain.calendar.domain.Schedule; | ||
import com.wypl.wyplcore.schedule.data.response.ScheduleFindResponse; | ||
import com.wypl.wyplcore.schedule.service.repetition.strategy.RepetitionStrategy; | ||
|
||
public class RepetitionService { | ||
|
||
public static List<ScheduleFindResponse> getScheduleResponses(Schedule schedule, LocalDate searchStartDate, LocalDate searchEndDate) { | ||
RepetitionStrategy repetitionStrategy = RepetitionStrategyFactory.getRepetitionStrategy(schedule.getRepetitionCycle()); | ||
return repetitionStrategy.getScheduleResponses(schedule, searchStartDate, searchEndDate); | ||
} | ||
} |
32 changes: 32 additions & 0 deletions
32
...rc/main/java/com/wypl/wyplcore/schedule/service/repetition/RepetitionStrategyFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package com.wypl.wyplcore.schedule.service.repetition; | ||
|
||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
import com.wypl.jpacalendardomain.calendar.data.RepetitionCycle; | ||
import com.wypl.wyplcore.schedule.service.repetition.strategy.DayRepetitionStrategy; | ||
import com.wypl.wyplcore.schedule.service.repetition.strategy.MonthRepetitionStrategy; | ||
import com.wypl.wyplcore.schedule.service.repetition.strategy.RepetitionStrategy; | ||
import com.wypl.wyplcore.schedule.service.repetition.strategy.WeekRepetitionStrategy; | ||
import com.wypl.wyplcore.schedule.service.repetition.strategy.YearRepetitionStrategy; | ||
|
||
public class RepetitionStrategyFactory { | ||
|
||
private static RepetitionStrategyFactory instance; | ||
|
||
private final Map<RepetitionCycle, RepetitionStrategy> map = new HashMap<>(); | ||
|
||
private RepetitionStrategyFactory() { | ||
map.put(RepetitionCycle.DAY, new DayRepetitionStrategy()); | ||
map.put(RepetitionCycle.WEEK, new WeekRepetitionStrategy()); | ||
map.put(RepetitionCycle.MONTH, new MonthRepetitionStrategy()); | ||
map.put(RepetitionCycle.YEAR, new YearRepetitionStrategy()); | ||
} | ||
|
||
public static RepetitionStrategy getRepetitionStrategy(RepetitionCycle repetitionCycle) { | ||
if (instance == null) { | ||
instance = new RepetitionStrategyFactory(); | ||
} | ||
return instance.map.get(repetitionCycle); | ||
} | ||
} |
29 changes: 29 additions & 0 deletions
29
...in/java/com/wypl/wyplcore/schedule/service/repetition/strategy/DayRepetitionStrategy.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package com.wypl.wyplcore.schedule.service.repetition.strategy; | ||
|
||
import static com.wypl.wyplcore.calendar.CalendarServiceUtil.*; | ||
|
||
import java.time.LocalDate; | ||
import java.time.LocalDateTime; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
import com.wypl.jpacalendardomain.calendar.domain.Schedule; | ||
import com.wypl.wyplcore.schedule.data.response.ScheduleFindResponse; | ||
|
||
public class DayRepetitionStrategy implements RepetitionStrategy{ | ||
@Override | ||
public List<ScheduleFindResponse> getScheduleResponses(Schedule schedule, LocalDate searchStartDate, LocalDate searchEndDate) { | ||
|
||
List<ScheduleFindResponse> responses = new ArrayList<>(); | ||
|
||
searchStartDate = getMaxDate(searchStartDate, schedule.getRepetitionStartDate()); | ||
searchEndDate = getMinDate(searchEndDate, schedule.getRepetitionEndDate()); | ||
|
||
for(; !searchStartDate.isAfter(searchEndDate); searchStartDate = searchStartDate.plusDays(1)) { | ||
LocalDateTime startDateTime = LocalDateTime.of(searchStartDate, schedule.getStartDateTime().toLocalTime()); | ||
LocalDateTime endDateTime = LocalDateTime.of(searchStartDate, schedule.getEndDateTime().toLocalTime()); | ||
responses.add(ScheduleFindResponse.of(schedule, startDateTime, endDateTime)); | ||
} | ||
return responses; | ||
} | ||
} |
38 changes: 38 additions & 0 deletions
38
.../java/com/wypl/wyplcore/schedule/service/repetition/strategy/MonthRepetitionStrategy.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package com.wypl.wyplcore.schedule.service.repetition.strategy; | ||
|
||
import static com.wypl.wyplcore.calendar.CalendarServiceUtil.*; | ||
|
||
import java.time.Duration; | ||
import java.time.LocalDate; | ||
import java.time.LocalDateTime; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
import com.wypl.jpacalendardomain.calendar.domain.Schedule; | ||
import com.wypl.wyplcore.schedule.data.response.ScheduleFindResponse; | ||
|
||
public class MonthRepetitionStrategy implements RepetitionStrategy{ | ||
@Override | ||
public List<ScheduleFindResponse> getScheduleResponses(Schedule schedule, LocalDate searchStartDate, | ||
LocalDate searchEndDate) { | ||
|
||
List<ScheduleFindResponse> responses = new ArrayList<>(); | ||
searchStartDate = getMaxDate(searchStartDate, schedule.getRepetitionStartDate()); | ||
searchEndDate = getMinDate(searchEndDate, schedule.getRepetitionEndDate()); | ||
|
||
// 끝나는 날짜 | ||
int endDayOfMonth = schedule.getEndDateTime().getDayOfMonth(); | ||
|
||
// 탐색할 시작 일시와 끝 일시 설정 | ||
LocalDateTime searchEndDateTime = LocalDateTime.of(searchStartDate.withDayOfMonth(endDayOfMonth), schedule.getEndDateTime().toLocalTime()); | ||
Duration duration = Duration.between(schedule.getStartDateTime(), schedule.getEndDateTime()); | ||
LocalDateTime searchStartDateTime = searchEndDateTime.minus(duration); | ||
|
||
for ( LocalDate date = searchStartDateTime.toLocalDate(); !date.isAfter(searchEndDate); date = date.plusMonths(1)) { | ||
LocalDateTime startDateTime = LocalDateTime.of(date, schedule.getStartDateTime().toLocalTime()); | ||
LocalDateTime endDateTime = startDateTime.plus(duration); | ||
responses.add(ScheduleFindResponse.of(schedule, startDateTime, endDateTime)); | ||
} | ||
return responses; | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
.../main/java/com/wypl/wyplcore/schedule/service/repetition/strategy/RepetitionStrategy.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package com.wypl.wyplcore.schedule.service.repetition.strategy; | ||
|
||
import java.time.LocalDate; | ||
import java.util.List; | ||
|
||
import com.wypl.jpacalendardomain.calendar.domain.Schedule; | ||
import com.wypl.wyplcore.schedule.data.response.ScheduleFindResponse; | ||
|
||
public interface RepetitionStrategy { | ||
|
||
List<ScheduleFindResponse> getScheduleResponses(Schedule schedule, LocalDate searchStartDate, LocalDate searchEndDate); | ||
|
||
} |
116 changes: 116 additions & 0 deletions
116
...n/java/com/wypl/wyplcore/schedule/service/repetition/strategy/WeekRepetitionStrategy.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
package com.wypl.wyplcore.schedule.service.repetition.strategy; | ||
|
||
import static com.wypl.wyplcore.calendar.CalendarServiceUtil.*; | ||
|
||
import java.time.DayOfWeek; | ||
import java.time.Duration; | ||
import java.time.LocalDate; | ||
import java.time.LocalDateTime; | ||
import java.time.LocalTime; | ||
import java.time.temporal.TemporalAdjusters; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
import com.wypl.jpacalendardomain.calendar.domain.Schedule; | ||
import com.wypl.wyplcore.schedule.data.response.ScheduleFindResponse; | ||
|
||
public class WeekRepetitionStrategy implements RepetitionStrategy{ | ||
|
||
@Override | ||
public List<ScheduleFindResponse> getScheduleResponses(Schedule schedule, LocalDate searchStartDate, | ||
LocalDate searchEndDate) { | ||
|
||
List<ScheduleFindResponse> responses = new ArrayList<>(); | ||
|
||
// 검색할 시작일자와 끝일자 설정 | ||
searchEndDate = getMinDate(searchEndDate, schedule.getRepetitionEndDate()); | ||
searchStartDate = getMaxDate(searchStartDate, schedule.getRepetitionStartDate()); | ||
|
||
// 반복 주에 포함되도록 가공 | ||
searchStartDate = getNearestDateUsingWeekInterval(searchStartDate, schedule.getWeekInterval(), schedule); | ||
|
||
if(!schedule.existsDayOfWeek()){ // 반복 요일을 설정하지 않았을 경우 | ||
|
||
searchStartDate = resetForBeforeStarted(searchStartDate, schedule); | ||
Duration duration = Duration.between(schedule.getStartDateTime(), schedule.getEndDateTime()); | ||
|
||
// 설정한 weekInterval 만큼씩 증가하면서 endDate까지 반복 | ||
for( LocalDate date = searchStartDate; !date.isAfter(searchEndDate); date = date.plusWeeks(schedule.getWeekInterval())) { | ||
LocalDateTime startDateTime = LocalDateTime.of(date, schedule.getStartDateTime().toLocalTime()); | ||
LocalDateTime endDateTime = startDateTime.plus(duration); | ||
responses.add(ScheduleFindResponse.of(schedule, startDateTime, endDateTime)); | ||
} | ||
return responses; | ||
} | ||
// 반복 요일을 설정했을 경우 | ||
int repetitionDayOfWeek = schedule.getDayOfWeek(); | ||
|
||
for (int dayOfWeek = 1; dayOfWeek <= 7; dayOfWeek++) { | ||
if( isSelectedDayOfWeek(repetitionDayOfWeek, dayOfWeek) ) { | ||
|
||
// Find nearest day by dayOfWeek and increase weekInterval | ||
LocalDate date = getMaxDate(searchStartDate, schedule.getRepetitionStartDate()).with( | ||
TemporalAdjusters.nextOrSame(DayOfWeek.of(dayOfWeek))); | ||
|
||
for(; !date.isAfter(searchEndDate); date = date.plusWeeks(schedule.getWeekInterval())) { | ||
responses.add(ScheduleFindResponse | ||
.of(schedule, LocalDateTime.of(date, schedule.getStartDateTime().toLocalTime()), LocalDateTime.of(date, schedule.getEndDateTime().toLocalTime()))); | ||
} | ||
} | ||
} | ||
return responses; | ||
} | ||
|
||
/** | ||
* 검색 조건에는 포함되지만, 검색이 시작된 날짜보다 이전에 시작한 Schedule 반영 | ||
* @param searchStartDate | ||
* @param schedule | ||
* @return searchStartDate | ||
* Todo: 일정이 일주일 이상 지속될 경우에는 처리 불가, 생각해 보기 | ||
*/ | ||
private static LocalDate resetForBeforeStarted(LocalDate searchStartDate, Schedule schedule) { | ||
|
||
// 끝나는 요일 찾기 | ||
DayOfWeek endDayOfWeek = schedule.getEndDateTime().getDayOfWeek(); | ||
Duration duration = Duration.between(schedule.getStartDateTime(), schedule.getEndDateTime()); | ||
|
||
// 탐색을 시작할 일자 설정 | ||
LocalDateTime endDateTimeForSearch = searchStartDate.with(TemporalAdjusters.nextOrSame(endDayOfWeek)) | ||
.atTime(schedule.getEndDateTime().toLocalTime()); | ||
|
||
return endDateTimeForSearch.minus(duration).toLocalDate(); | ||
} | ||
|
||
/** | ||
* 검색 시작일자에 WeekInterval을 적용 | ||
* @param searchStartDate | ||
* @param weekInterval | ||
* @param schedule | ||
* @return searchStartDate | ||
*/ | ||
public static LocalDate getNearestDateUsingWeekInterval(LocalDate searchStartDate, Integer weekInterval, | ||
Schedule schedule){ | ||
|
||
// searchStartDate를 해당 주의 월요일로 설정 | ||
LocalDateTime searchStartMonday = LocalDateTime.of(searchStartDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)), LocalTime.of(0, 0)); | ||
LocalDateTime scheduleStartMonday = LocalDateTime.of(schedule.getRepetitionStartDate().with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)), LocalTime.of(0, 0)); | ||
|
||
int gapOfWeek = (int) Duration.between(scheduleStartMonday, searchStartMonday).toDays() / 7; | ||
|
||
if (gapOfWeek % weekInterval == 0) return searchStartDate; | ||
|
||
int addWeek = (gapOfWeek / weekInterval + 1) * weekInterval - gapOfWeek; | ||
|
||
return searchStartDate.plusWeeks(addWeek); | ||
} | ||
|
||
/** | ||
* repetitionDayOfWeek에 해당하는 요일이 선택되었는지 확인 | ||
* @param repetitionDayOfWeek of Schedule | ||
* @param dayOfWeek (1: 월요일, 2: 화요일, 3: 수요일, 4: 목요일, 5: 금요일, 6: 토요일, 7: 일요일) | ||
* @return boolean | ||
*/ | ||
static boolean isSelectedDayOfWeek(int repetitionDayOfWeek, int dayOfWeek) { | ||
return (repetitionDayOfWeek & (1 << dayOfWeek)) != 0; | ||
} | ||
} |
39 changes: 39 additions & 0 deletions
39
...n/java/com/wypl/wyplcore/schedule/service/repetition/strategy/YearRepetitionStrategy.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package com.wypl.wyplcore.schedule.service.repetition.strategy; | ||
|
||
import static com.wypl.wyplcore.calendar.CalendarServiceUtil.*; | ||
|
||
import java.time.Duration; | ||
import java.time.LocalDate; | ||
import java.time.LocalDateTime; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
import org.springframework.stereotype.Service; | ||
|
||
import com.wypl.jpacalendardomain.calendar.domain.Schedule; | ||
import com.wypl.wyplcore.schedule.data.response.ScheduleFindResponse; | ||
|
||
@Service | ||
public class YearRepetitionStrategy implements RepetitionStrategy{ | ||
@Override | ||
public List<ScheduleFindResponse> getScheduleResponses(Schedule schedule, LocalDate searchStartDate, | ||
LocalDate searchEndDate) { | ||
List<ScheduleFindResponse> responses = new ArrayList<>(); | ||
|
||
searchStartDate = getMaxDate(searchStartDate, schedule.getRepetitionStartDate()); | ||
searchEndDate = getMinDate(searchEndDate, schedule.getRepetitionEndDate()); | ||
|
||
// startDate와 같거나 가장 가까운 schedule.endDateTime의 날짜, 시간을 가진 LocalDateTime 생성 | ||
LocalDateTime nearestEndDateTime = LocalDateTime.of(searchStartDate.withDayOfYear(schedule.getEndDateTime().getDayOfYear()), schedule.getEndDateTime().toLocalTime()); | ||
LocalDateTime nearestStartDateTime = nearestEndDateTime.minus( | ||
Duration.between(schedule.getStartDateTime(), schedule.getEndDateTime())); | ||
|
||
for(LocalDate date = nearestStartDateTime.toLocalDate(); !date.isAfter(searchEndDate); date = date.plusYears(1)) { | ||
LocalDateTime startDateTime = LocalDateTime.of(date, schedule.getStartDateTime().toLocalTime()); | ||
LocalDateTime endDateTime = startDateTime.plus(Duration.between(schedule.getStartDateTime(), schedule.getEndDateTime())); | ||
responses.add(ScheduleFindResponse.of(schedule, startDateTime, endDateTime)); | ||
} | ||
|
||
return responses; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.