/** @inheritDoc */
  public int removeMatchingComments(
      Weblog weblog,
      WeblogEntry entry,
      String searchString,
      Date startDate,
      Date endDate,
      ApprovalStatus status)
      throws WebloggerException {

    // TODO dynamic bulk delete query: I'd MUCH rather use a bulk delete,
    // but MySQL says "General error, message from server: "You can't
    // specify target table 'roller_comment' for update in FROM clause"

    CommentSearchCriteria csc = new CommentSearchCriteria();
    csc.setWeblog(weblog);
    csc.setEntry(entry);
    csc.setSearchText(searchString);
    csc.setStartDate(startDate);
    csc.setEndDate(endDate);
    csc.setStatus(status);

    List<WeblogEntryComment> comments = getComments(csc);
    int count = 0;
    for (WeblogEntryComment comment : comments) {
      removeComment(comment);
      count++;
    }
    return count;
  }
  /** @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());
  }
  /** @inheritDoc */
  public List<WeblogEntryComment> getComments(CommentSearchCriteria csc) throws WebloggerException {

    List<Object> params = new ArrayList<Object>();
    int size = 0;
    StringBuilder queryString = new StringBuilder();
    queryString.append("SELECT c FROM WeblogEntryComment c ");

    StringBuilder whereClause = new StringBuilder();
    if (csc.getEntry() != null) {
      params.add(size++, csc.getEntry());
      whereClause.append("c.weblogEntry = ?").append(size);
    } else if (csc.getWeblog() != null) {
      params.add(size++, csc.getWeblog());
      whereClause.append("c.weblogEntry.website = ?").append(size);
    }

    if (csc.getSearchText() != null) {
      params.add(size++, "%" + csc.getSearchText().toUpperCase() + "%");
      appendConjuctionToWhereclause(whereClause, "upper(c.content) LIKE ?").append(size);
    }

    if (csc.getStartDate() != null) {
      Timestamp start = new Timestamp(csc.getStartDate().getTime());
      params.add(size++, start);
      appendConjuctionToWhereclause(whereClause, "c.postTime >= ?").append(size);
    }

    if (csc.getEndDate() != null) {
      Timestamp end = new Timestamp(csc.getEndDate().getTime());
      params.add(size++, end);
      appendConjuctionToWhereclause(whereClause, "c.postTime <= ?").append(size);
    }

    if (csc.getStatus() != null) {
      params.add(size++, csc.getStatus());
      appendConjuctionToWhereclause(whereClause, "c.status = ?").append(size);
    }

    if (whereClause.length() != 0) {
      queryString.append(" WHERE ").append(whereClause);
    }
    if (csc.isReverseChrono()) {
      queryString.append(" ORDER BY c.postTime DESC");
    } else {
      queryString.append(" ORDER BY c.postTime ASC");
    }

    TypedQuery<WeblogEntryComment> query =
        strategy.getDynamicQuery(queryString.toString(), WeblogEntryComment.class);
    if (csc.getOffset() != 0) {
      query.setFirstResult(csc.getOffset());
    }
    if (csc.getMaxResults() != -1) {
      query.setMaxResults(csc.getMaxResults());
    }
    for (int i = 0; i < params.size(); i++) {
      query.setParameter(i + 1, params.get(i));
    }
    return query.getResultList();
  }