/** {@inheritDoc} */
  @Transactional(rollbackFor = {Throwable.class})
  public void updateSavedSearch(Long savedSearchId, boolean weekly, boolean monthly) {
    SavedSearch savedSearch = hibernateTemplate.get(SavedSearch.class, savedSearchId);

    savedSearch.setMonthly(monthly);
    savedSearch.setWeekly(weekly);

    hibernateTemplate.update(savedSearch);
  }
  @SuppressWarnings("unchecked")
  protected void markSearchRun(Long savedSearchID, String frequency, Date endDate) {
    SavedSearch savedSearch = hibernateTemplate.get(SavedSearch.class, savedSearchID);

    if (savedSearch == null) {
      throw new RuntimeException("Could not find savedSearch: " + savedSearchID);
    }

    if (frequency.equals(WEEKLY_FREQUENCY)) {
      savedSearch.setLastWeeklySearchTime(endDate);
    } else {
      savedSearch.setLastMonthlySearchTime(endDate);
    }

    hibernateTemplate.update(savedSearch);

    log.debug(
        "Updated Last {} saved Search time for Saved Search ID: {}", frequency, savedSearchID);
  }
  /** {@inheritDoc} */
  @Transactional(rollbackFor = {Throwable.class})
  public void deleteSavedSearch(Long userProfileId, Long savedSearchId) {

    UserProfile userProfile =
        (UserProfile)
            DataAccessUtils.uniqueResult(
                hibernateTemplate.findByCriteria(
                    DetachedCriteria.forClass(UserProfile.class)
                        .add(Restrictions.eq("ID", userProfileId))
                        .setFetchMode("savedSearches", FetchMode.JOIN)
                        .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)));
    List<SavedSearch> savedSearches = userProfile.getSavedSearches();
    for (Iterator<SavedSearch> it = savedSearches.iterator(); it.hasNext(); ) {
      SavedSearch savedSearch = it.next();
      if (savedSearch.getID().equals(savedSearchId)) {
        it.remove();
      }
    }
    hibernateTemplate.update(userProfile);
  }
  /** {@inheritDoc} */
  @Transactional(rollbackFor = {Throwable.class})
  @SuppressWarnings("unchecked")
  public void saveSearch(
      Long userProfileId,
      SearchParameters searchParameters,
      String name,
      boolean weekly,
      boolean monthly) {

    UserProfile user = hibernateTemplate.get(UserProfile.class, userProfileId);

    SavedSearchQuery query = saveSearchQuery(searchParameters);

    SavedSearch savedSearch = new SavedSearch(name, query);
    savedSearch.setSearchType(SavedSearchType.USER_DEFINED);
    savedSearch.setWeekly(weekly);
    savedSearch.setMonthly(monthly);

    user.getSavedSearches().add(savedSearch);

    hibernateTemplate.save(user);
  }
  /** {@inheritDoc} */
  @Transactional(rollbackFor = {Throwable.class})
  public UserProfile removedFilteredWeeklySearchAlert(Long userProfileId, String journal) {
    UserProfile user = getUser(userProfileId);

    SavedSearch oldSearch = null;

    // We key off of the title as it is not user facing
    for (SavedSearch savedSearch : user.getSavedSearches()) {
      if (savedSearch.getSearchType() == SavedSearchType.JOURNAL_ALERT
          && savedSearch.getWeekly()
          && savedSearch.getSearchName().equals(journal)) {

        oldSearch = savedSearch;
      }
    }

    if (oldSearch != null) {
      user.getSavedSearches().remove(oldSearch);
    }

    hibernateTemplate.save(user);

    return user;
  }
  /** {@inheritDoc} */
  @Transactional(rollbackFor = {Throwable.class})
  public UserProfile setFilteredWeeklySearchAlert(
      Long userProfileId, String[] subjects, String journal) {
    SearchParameters searchParameters = new SearchParameters();

    searchParameters.setQuery("*:*");
    searchParameters.setFilterJournals(new String[] {journal});
    searchParameters.setFilterSubjectsDisjunction(subjects);

    // We store the saved search here as JSON instead of serializing the object cuz JSON rocks
    SavedSearchQuery query = saveSearchQuery(searchParameters);

    UserProfile user = getUser(userProfileId);
    SavedSearch newSearch = null;

    // See if a record exists already, we only allow one weekly alert of type JOURNAL_ALERT per
    // journal
    // We key off of the title as it is not user facing
    for (SavedSearch savedSearch : user.getSavedSearches()) {
      if (savedSearch.getSearchType() == SavedSearchType.JOURNAL_ALERT
          && savedSearch.getWeekly()
          && savedSearch.getSearchName().equals(journal)) {
        newSearch = savedSearch;
      }
    }

    if (newSearch == null) {
      newSearch = new SavedSearch(journal, query);
      newSearch.setSearchType(SavedSearchType.JOURNAL_ALERT);
      newSearch.setWeekly(true);
      newSearch.setMonthly(false);
      user.getSavedSearches().add(newSearch);
    } else {
      newSearch.setSearchQuery(query);
    }

    hibernateTemplate.save(user);

    return user;
  }