/** @inheritDoc */
  public void saveWeblogCategory(WeblogCategory cat) throws WebloggerException {
    boolean exists = getWeblogCategory(cat.getId()) != null;
    if (!exists && isDuplicateWeblogCategoryName(cat)) {
      throw new WebloggerException("Duplicate category name, cannot save category");
    }

    // update weblog last modified date.  date updated by saveWebsite()
    roller.getWeblogManager().saveWeblog(cat.getWeblog());
    this.strategy.store(cat);
  }
  /** @inheritDoc */
  public void removeWeblogCategory(WeblogCategory cat) throws WebloggerException {
    if (cat.retrieveWeblogEntries(false).size() > 0) {
      throw new WebloggerException("Cannot remove category with entries");
    }

    cat.getWeblog().getWeblogCategories().remove(cat);

    // remove cat
    this.strategy.remove(cat);

    if (cat.equals(cat.getWeblog().getBloggerCategory())) {
      cat.getWeblog().setBloggerCategory(null);
      this.strategy.store(cat.getWeblog());
    }

    // update weblog last modified date.  date updated by saveWebsite()
    roller.getWeblogManager().saveWeblog(cat.getWeblog());
  }
  /** @inheritDoc */
  public void removeWeblogEntry(WeblogEntry entry) throws WebloggerException {
    Weblog weblog = entry.getWebsite();

    CommentSearchCriteria csc = new CommentSearchCriteria();
    csc.setEntry(entry);

    // remove comments
    List<WeblogEntryComment> comments = getComments(csc);
    for (WeblogEntryComment comment : comments) {
      this.strategy.remove(comment);
    }

    // remove tag & tag aggregates
    if (entry.getTags() != null) {
      for (WeblogEntryTag tag : entry.getTags()) {
        removeWeblogEntryTag(tag);
      }
    }

    // remove attributes
    if (entry.getEntryAttributes() != null) {
      for (Iterator it = entry.getEntryAttributes().iterator(); it.hasNext(); ) {
        WeblogEntryAttribute att = (WeblogEntryAttribute) it.next();
        it.remove();
        this.strategy.remove(att);
      }
    }

    // remove entry
    this.strategy.remove(entry);

    // update weblog last modified date.  date updated by saveWebsite()
    if (entry.isPublished()) {
      roller.getWeblogManager().saveWeblog(weblog);
    }

    // remove entry from cache mapping
    this.entryAnchorToIdMap.remove(entry.getWebsite().getHandle() + ":" + entry.getAnchor());
  }
  // TODO: perhaps the createAnchor() and queuePings() items should go outside this method?
  public void saveWeblogEntry(WeblogEntry entry) throws WebloggerException {

    if (entry.getCategory() == null) {
      // Entry is invalid without category, so use weblog client cat
      WeblogCategory cat = entry.getWebsite().getBloggerCategory();
      if (cat == null) {
        // Still no category, so use first one found
        cat = entry.getWebsite().getWeblogCategories().iterator().next();
      }
      entry.setCategory(cat);
    }

    // Entry is invalid without local. if missing use weblog default
    if (entry.getLocale() == null) {
      entry.setLocale(entry.getWebsite().getLocale());
    }

    if (entry.getAnchor() == null || entry.getAnchor().trim().equals("")) {
      entry.setAnchor(this.createAnchor(entry));
    }

    if (entry.isPublished()) {
      // tag aggregates are updated only when entry published in order for
      // tag cloud counts to match published articles
      if (entry.getRefreshAggregates()) {
        // blog entry wasn't published before, so all tags need to be incremented
        for (WeblogEntryTag tag : entry.getTags()) {
          updateTagCount(tag.getName(), entry.getWebsite(), 1);
        }
      } else {
        // only new tags need to be incremented
        for (WeblogEntryTag tag : entry.getAddedTags()) {
          updateTagCount(tag.getName(), entry.getWebsite(), 1);
        }
      }
    } else {
      if (entry.getRefreshAggregates()) {
        // blog entry no longer published so need to reduce aggregate count
        for (WeblogEntryTag tag : entry.getTags()) {
          updateTagCount(tag.getName(), entry.getWebsite(), -1);
        }
      }
    }

    for (WeblogEntryTag tag : entry.getRemovedTags()) {
      removeWeblogEntryTag(tag);
    }

    // if the entry was published to future, set status as SCHEDULED
    // we only consider an entry future published if it is scheduled
    // more than 1 minute into the future
    if (PubStatus.PUBLISHED.equals(entry.getStatus())
        && entry
            .getPubTime()
            .after(new Date(System.currentTimeMillis() + RollerConstants.MIN_IN_MS))) {
      entry.setStatus(PubStatus.SCHEDULED);
    }

    // Store value object (creates new or updates existing)
    entry.setUpdateTime(new Timestamp(new Date().getTime()));

    this.strategy.store(entry);

    // update weblog last modified date.  date updated by saveWebsite()
    if (entry.isPublished()) {
      roller.getWeblogManager().saveWeblog(entry.getWebsite());
    }

    if (entry.isPublished()) {
      // Queue applicable pings for this update.
      roller.getAutopingManager().queueApplicableAutoPings(entry);
    }
  }
  /** @inheritDoc */
  public void removeComment(WeblogEntryComment comment) throws WebloggerException {
    this.strategy.remove(comment);

    // update weblog last modified date.  date updated by saveWebsite()
    roller.getWeblogManager().saveWeblog(comment.getWeblogEntry().getWebsite());
  }