/**
   * Gets the current and most recent periods to search, based on the period types from the rules to
   * run.
   *
   * <p>For each period type, return the period containing the current date (if any), and the most
   * recent previous period. Add whichever of these periods actually exist in the database.
   *
   * <p>TODO If the last successful daily run was more than one day ago, we might add some
   * additional periods of type DailyPeriodType not to miss any alerts.
   *
   * @param rules the ValidationRules to be evaluated on this run
   * @return periods to search for new alerts
   */
  private Set<Period> getAlertPeriodsFromRules(Set<ValidationRule> rules) {
    Set<Period> periods = new HashSet<>();

    Set<PeriodType> rulePeriodTypes = getPeriodTypesFromRules(rules);

    for (PeriodType periodType : rulePeriodTypes) {
      CalendarPeriodType calendarPeriodType = (CalendarPeriodType) periodType;
      Period currentPeriod = calendarPeriodType.createPeriod();
      Period previousPeriod = calendarPeriodType.getPreviousPeriod(currentPeriod);
      periods.addAll(
          periodService.getIntersectingPeriodsByPeriodType(
              periodType, previousPeriod.getStartDate(), currentPeriod.getEndDate()));
    }

    return periods;
  }
  public List<Period> getPeriods(Period lastPeriod, int historyLength) {
    List<Period> periods = new ArrayList<Period>(historyLength);

    lastPeriod = periodStore.reloadForceAddPeriod(lastPeriod);

    CalendarPeriodType periodType = (CalendarPeriodType) lastPeriod.getPeriodType();

    Period p = new Period();

    for (int i = 0; i < historyLength; ++i) {
      p = getPeriodFromDates(lastPeriod.getStartDate(), lastPeriod.getEndDate(), periodType);

      periods.add(p != null ? p : lastPeriod);

      lastPeriod = periodType.getPreviousPeriod(lastPeriod);
    }

    Collections.reverse(periods);

    return periods;
  }