/** * Given that the date is in a non-moratorium holiday, shift it past the holiday until either it * is no longer in a holiday or moratorium, or until it no longer moves (e.g., lands in a same-day * holiday). * * <p>If the date shifts into a moratorium period, then shift it out using the RepaymentRuleType * of the most recent non-moratorium holiday that the date was shifted out of. For example, if * shifting the date out of a next-working-day holiday lands it in a moratorium period, then use * the next-working-day repayment rule to shift it past the moratorium period. * * @param date the DateTime to be shifted * @return the shifted date */ private DateTime shiftDatePastNonMoratoriumHoliday(DateTime date) { assert date != null; assert isEnclosedByAHoliday(date); assert !isEnclosedByAHolidayWithRepaymentRule(date, RepaymentRuleTypes.REPAYMENT_MORATORIUM); Holiday currentlyEnclosingHoliday = getHolidayEnclosing(date); RepaymentRuleTypes mostRecentNonMoratoriumRepaymentRule = currentlyEnclosingHoliday.getRepaymentRuleType(); // never REPAYMENT_MORATORIUM DateTime previousDate = null; DateTime adjustedDate = date; do { previousDate = adjustedDate; if (currentlyEnclosingHoliday.getRepaymentRuleType() == RepaymentRuleTypes.REPAYMENT_MORATORIUM) { adjustedDate = buildHolidayFromCurrentHolidayWithRepaymentRule( currentlyEnclosingHoliday, mostRecentNonMoratoriumRepaymentRule) .adjust(previousDate, workingDays, scheduledEvent); } else { adjustedDate = currentlyEnclosingHoliday.adjust(previousDate, workingDays, scheduledEvent); mostRecentNonMoratoriumRepaymentRule = currentlyEnclosingHoliday.getRepaymentRuleType(); } if (isEnclosedByAHoliday(adjustedDate)) { currentlyEnclosingHoliday = getHolidayEnclosing(adjustedDate); } } while (isEnclosedByAHoliday(adjustedDate) && (!adjustedDate.equals(previousDate))); return adjustedDate; }
private boolean isEnclosedByAHolidayWithRepaymentRule(DateTime date, RepaymentRuleTypes rule) { for (Holiday holiday : this.upcomingHolidays) { if (holiday.encloses(date.toDate()) && (holiday.getRepaymentRuleType() == rule)) { return true; } } return false; }
private List<Holiday> getNonMoratoriumHolidays() { List<Holiday> nonMoratoriumHolidays = new ArrayList<Holiday>(); for (Holiday holiday : this.upcomingHolidays) { if (!(holiday.getRepaymentRuleType() == RepaymentRuleTypes.REPAYMENT_MORATORIUM)) { nonMoratoriumHolidays.add(holiday); } } return nonMoratoriumHolidays; }