/** {@inheritDoc} */
  @Override
  public void removeOldJobs(final @NotNull Integer days) {

    final Calendar cal = CalendarUtils.getCalendarWithoutTime();
    cal.add(Calendar.DAY_OF_YEAR, days.intValue() * -1);

    final List<Job> jobs = jobDao.getJobsByUpdateDate(cal);

    LOGGER.info("Found " + jobs.size() + " jobs that are eligible for removal.");

    if (!jobs.isEmpty()) {

      final long jobsCount = jobDao.getJobsCount();

      for (final Job job : jobs) {
        jobDao.remove(job.getId());
      }

      JobCountPerDay jobCountPerDay = jobCountPerDayDao.getByDate(new Date());

      if (jobCountPerDay == null) {
        jobCountPerDay = new JobCountPerDay();
        jobCountPerDay.setJobDate(new Date());
      }

      jobCountPerDay.setNumberOfJobsDeleted(Long.valueOf(jobs.size()));
      jobCountPerDay.setNumberOfJobsPosted(Long.valueOf(0));
      jobCountPerDay.setTotalNumberOfJobs(jobsCount - jobs.size());
      jobCountPerDay.setAutomaticallyCleaned(Boolean.TRUE);
      jobCountPerDayDao.save(jobCountPerDay);
    }
  }
  /** {@inheritDoc} */
  @Override
  public void updateJobCountPerDays(final Calendar asOfDay) {

    final Calendar today = CalendarUtils.getCalendarWithoutTime();
    today.setTime(asOfDay.getTime());
    final Calendar yesterday = CalendarUtils.getCalendarWithoutTime();
    yesterday.add(Calendar.DAY_OF_YEAR, -1);

    final List<JobCountPerDay> latestTwoJobCountPerDays = jobCountPerDayDao.getLatestTwoJobCounts();

    // If nothing exists yet, create an entry with zero jobs.
    if (latestTwoJobCountPerDays.isEmpty()) {
      jobCountPerDayDao.save(new JobCountPerDay(yesterday.getTime(), 0L, 0L, 0L));
    }

    boolean containsToday = false;

    // Let's make sure we have a value for today
    for (JobCountPerDay jobCountPerDay : latestTwoJobCountPerDays) {
      if (today.getTime().equals(jobCountPerDay.getJobDate())) {
        containsToday = true;
        break;
      }
    }

    if (!containsToday) {
      // We need to create a value for today
      final Long totalNumberOfJobs = this.getJobsCount();
      jobCountPerDayDao.save(new JobCountPerDay(today.getTime(), 0L, 0L, totalNumberOfJobs));
    }
  }
  /** {@inheritDoc} */
  @Override
  public void deleteJobForId(final Long jobId) {
    jobDao.remove(jobId);

    JobCountPerDay jobCountPerDay = jobCountPerDayDao.getByDate(new Date());

    if (jobCountPerDay == null) {
      jobCountPerDay = new JobCountPerDay();
      jobCountPerDay.setJobDate(new Date());
    }

    jobCountPerDay.setNumberOfJobsDeleted(Long.valueOf(1));
    jobCountPerDay.setNumberOfJobsPosted(Long.valueOf(0));
    jobCountPerDay.setTotalNumberOfJobs(jobDao.getJobsCount());
    jobCountPerDayDao.save(jobCountPerDay);
  }
  /** {@inheritDoc} */
  @Override
  @Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
  public List<JobCountPerDay> getJobCountPerDayAndPeriod(final Date fromDate, final Date toDate) {

    // Make sure we have values at least for today and the previous day.
    this.updateJobCountPerDays();

    final List<JobCountPerDay> jobCountPerDays =
        jobCountPerDayDao.getJobCountPerDayAndPeriod(fromDate, toDate);
    return jobCountPerDays;
  }
  /** {@inheritDoc} */
  public void saveJobStatistics(Job job) {

    if (job.getId() == null) {

      JobCountPerDay jobCountPerDay = jobCountPerDayDao.getByDate(job.getRegistrationDate());

      if (jobCountPerDay == null) {
        jobCountPerDay = new JobCountPerDay();
        jobCountPerDay.setJobDate(job.getRegistrationDate());
        jobCountPerDay.setNumberOfJobsDeleted(Long.valueOf(0));
        jobCountPerDay.setNumberOfJobsPosted(Long.valueOf(1));
        jobCountPerDay.setTotalNumberOfJobs(jobDao.getJobsCount());
        jobCountPerDayDao.save(jobCountPerDay);
      } else {
        jobCountPerDay.setNumberOfJobsPosted(jobCountPerDay.getNumberOfJobsPosted() + 1);
        jobCountPerDay.setTotalNumberOfJobs(jobDao.getJobsCount() + 1);
        jobCountPerDayDao.save(jobCountPerDay);
      }
    }
  }