/** @inheritDoc */
  public void incrementHitCount(Weblog weblog, int amount) throws WebloggerException {

    if (amount == 0) {
      throw new WebloggerException("Tag increment amount cannot be zero.");
    }

    if (weblog == null) {
      throw new WebloggerException("Website cannot be NULL.");
    }

    TypedQuery<WeblogHitCount> q =
        strategy.getNamedQuery("WeblogHitCount.getByWeblog", WeblogHitCount.class);
    q.setParameter(1, weblog);
    WeblogHitCount hitCount;
    try {
      hitCount = q.getSingleResult();
    } catch (NoResultException e) {
      hitCount = null;
    }

    // create it if it doesn't exist
    if (hitCount == null && amount > 0) {
      hitCount = new WeblogHitCount();
      hitCount.setWeblog(weblog);
      hitCount.setDailyHits(amount);
      strategy.store(hitCount);
    } else if (hitCount != null) {
      hitCount.setDailyHits(hitCount.getDailyHits() + amount);
      strategy.store(hitCount);
    }
  }
  /** Save all properties. */
  public void saveProperties(Map properties) throws PlanetException {

    // just go through the list and saveProperties each property
    Iterator props = properties.values().iterator();
    while (props.hasNext()) {
      strategy.store((RuntimeConfigProperty) props.next());
    }
  }
 /** @inheritDoc */
 public void resetHitCount(Weblog weblog) throws WebloggerException {
   TypedQuery<WeblogHitCount> q =
       strategy.getNamedQuery("WeblogHitCount.getByWeblog", WeblogHitCount.class);
   q.setParameter(1, weblog);
   WeblogHitCount hitCount;
   try {
     hitCount = q.getSingleResult();
     hitCount.setDailyHits(0);
     strategy.store(hitCount);
   } catch (NoResultException e) {
     // ignore: no hit count for weblog
   }
 }
  /**
   * This method maintains the tag aggregate table up-to-date with total counts. More specifically
   * every time this method is called it will act upon exactly two rows in the database
   * (tag,website,count), one with website matching the argument passed and one where website is
   * null. If the count ever reaches zero, the row must be deleted.
   *
   * @param name The tag name
   * @param website The website to used when updating the stats.
   * @param amount The amount to increment the tag count (it can be positive or negative).
   * @throws WebloggerException
   */
  private void updateTagCount(String name, Weblog website, int amount) throws WebloggerException {
    if (amount == 0) {
      throw new WebloggerException("Tag increment amount cannot be zero.");
    }

    if (website == null) {
      throw new WebloggerException("Website cannot be NULL.");
    }

    // The reason why add order lastUsed desc is to make sure we keep picking the most recent
    // one in the case where we have multiple rows (clustered environment)
    // eventually that second entry will have a very low total (most likely 1) and
    // won't matter
    TypedQuery<WeblogEntryTagAggregate> weblogQuery =
        strategy.getNamedQuery(
            "WeblogEntryTagAggregate.getByName&WebsiteOrderByLastUsedDesc",
            WeblogEntryTagAggregate.class);
    weblogQuery.setParameter(1, name);
    weblogQuery.setParameter(2, website);
    WeblogEntryTagAggregate weblogTagData;
    try {
      weblogTagData = weblogQuery.getSingleResult();
    } catch (NoResultException e) {
      weblogTagData = null;
    }

    TypedQuery<WeblogEntryTagAggregate> siteQuery =
        strategy.getNamedQuery(
            "WeblogEntryTagAggregate.getByName&WebsiteNullOrderByLastUsedDesc",
            WeblogEntryTagAggregate.class);
    siteQuery.setParameter(1, name);
    WeblogEntryTagAggregate siteTagData;
    try {
      siteTagData = siteQuery.getSingleResult();
    } catch (NoResultException e) {
      siteTagData = null;
    }
    Timestamp lastUsed = new Timestamp((new Date()).getTime());

    // create it only if we are going to need it.
    if (weblogTagData == null && amount > 0) {
      weblogTagData = new WeblogEntryTagAggregate(null, website, name, amount);
      weblogTagData.setLastUsed(lastUsed);
      strategy.store(weblogTagData);

    } else if (weblogTagData != null) {
      weblogTagData.setTotal(weblogTagData.getTotal() + amount);
      weblogTagData.setLastUsed(lastUsed);
      strategy.store(weblogTagData);
    }

    // create it only if we are going to need it.
    if (siteTagData == null && amount > 0) {
      siteTagData = new WeblogEntryTagAggregate(null, null, name, amount);
      siteTagData.setLastUsed(lastUsed);
      strategy.store(siteTagData);

    } else if (siteTagData != null) {
      siteTagData.setTotal(siteTagData.getTotal() + amount);
      siteTagData.setLastUsed(lastUsed);
      strategy.store(siteTagData);
    }

    // delete all bad counts
    Query removeq = strategy.getNamedUpdate("WeblogEntryTagAggregate.removeByTotalLessEqual");
    removeq.setParameter(1, 0);
    removeq.executeUpdate();
  }
  /** Save a single property. */
  public void saveProperty(RuntimeConfigProperty property) throws PlanetException {

    strategy.store(property);
  }