public String createAnchor(WeblogEntryData entry) throws RollerException {
    try {
      // Check for uniqueness of anchor
      String base = entry.createAnchorBase();
      String name = base;
      int count = 0;

      while (true) {
        if (count > 0) {
          name = base + count;
        }

        Session session = ((HibernatePersistenceStrategy) this.strategy).getSession();
        Criteria criteria = session.createCriteria(WeblogEntryData.class);
        criteria.add(Expression.eq("website", entry.getWebsite()));
        criteria.add(Expression.eq("anchor", name));

        List results = criteria.list();

        if (results.size() < 1) {
          break;
        } else {
          count++;
        }
      }
      return name;
    } catch (HibernateException e) {
      throw new RollerException(e);
    }
  }
  public WeblogEntryData getWeblogEntryByAnchor(WebsiteData website, String anchor)
      throws RollerException {

    if (website == null) throw new RollerException("Website is null");

    if (anchor == null) throw new RollerException("Anchor is null");

    // mapping key is combo of weblog + anchor
    String mappingKey = website.getHandle() + ":" + anchor;

    // check cache first
    // NOTE: if we ever allow changing anchors then this needs updating
    if (this.entryAnchorToIdMap.containsKey(mappingKey)) {

      WeblogEntryData entry = this.getWeblogEntry((String) this.entryAnchorToIdMap.get(mappingKey));
      if (entry != null) {
        log.debug("entryAnchorToIdMap CACHE HIT - " + mappingKey);
        return entry;
      } else {
        // mapping hit with lookup miss?  mapping must be old, remove it
        this.entryAnchorToIdMap.remove(mappingKey);
      }
    }

    // cache failed, do lookup
    try {
      Session session = ((HibernatePersistenceStrategy) this.strategy).getSession();
      Criteria criteria = session.createCriteria(WeblogEntryData.class);
      criteria.add(
          Expression.conjunction()
              .add(Expression.eq("website", website))
              .add(Expression.eq("anchor", anchor)));
      criteria.addOrder(Order.desc("pubTime"));
      criteria.setMaxResults(1);

      List list = criteria.list();

      WeblogEntryData entry = null;
      if (list.size() != 0) {
        entry = (WeblogEntryData) criteria.uniqueResult();
      }

      // add mapping to cache
      if (entry != null) {
        log.debug("entryAnchorToIdMap CACHE MISS - " + mappingKey);
        this.entryAnchorToIdMap.put(mappingKey, entry.getId());
      }

      return entry;
    } catch (HibernateException e) {
      throw new RollerException(e);
    }
  }
  public void removeWeblogEntry(WeblogEntryData entry) throws RollerException {

    Session session = ((HibernatePersistenceStrategy) this.strategy).getSession();

    // remove referers
    Criteria refererQuery = session.createCriteria(RefererData.class);
    refererQuery.add(Expression.eq("weblogEntry", entry));
    List referers = refererQuery.list();
    for (Iterator iter = referers.iterator(); iter.hasNext(); ) {
      RefererData referer = (RefererData) iter.next();
      this.strategy.remove(referer);
    }

    // remove comments
    List comments =
        getComments(
            null, // website
            entry, null, // search String
            null, // startDate
            null, // endDate
            null, // pending
            null, // approved
            null, // spam
            true, // reverse chrono order (not that it matters)
            0, // offset
            -1); // no limit
    Iterator commentsIT = comments.iterator();
    while (commentsIT.hasNext()) {
      this.strategy.remove((CommentData) commentsIT.next());
    }

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

    // update weblog last modified date.  date updated by saveWebsite()
    if (entry.isPublished()) {
      RollerFactory.getRoller().getUserManager().saveWebsite(entry.getWebsite());
    }

    // remove entry from cache mapping
    this.entryAnchorToIdMap.remove(entry.getWebsite().getHandle() + ":" + entry.getAnchor());
  }
  private Map getWeblogEntryMap(
      WebsiteData website,
      Date startDate,
      Date endDate,
      String catName,
      String status,
      boolean stringsOnly,
      String locale,
      int offset,
      int length)
      throws RollerException {

    TreeMap map = new TreeMap(reverseComparator);

    List entries =
        getWeblogEntries(
            website, null, startDate, endDate, catName, status, null, locale, offset, length);

    Calendar cal = Calendar.getInstance();
    if (website != null) {
      cal.setTimeZone(website.getTimeZoneInstance());
    }

    SimpleDateFormat formatter = DateUtil.get8charDateFormat();
    for (Iterator wbItr = entries.iterator(); wbItr.hasNext(); ) {
      WeblogEntryData entry = (WeblogEntryData) wbItr.next();
      Date sDate = DateUtil.getNoonOfDay(entry.getPubTime(), cal);
      if (stringsOnly) {
        if (map.get(sDate) == null) map.put(sDate, formatter.format(sDate));
      } else {
        List dayEntries = (List) map.get(sDate);
        if (dayEntries == null) {
          dayEntries = new ArrayList();
          map.put(sDate, dayEntries);
        }
        dayEntries.add(entry);
      }
    }
    return map;
  }
  public List getNextPrevEntries(
      WeblogEntryData current, String catName, String locale, int maxEntries, boolean next)
      throws RollerException {

    Junction conjunction = Expression.conjunction();
    conjunction.add(Expression.eq("website", current.getWebsite()));
    conjunction.add(Expression.eq("status", WeblogEntryData.PUBLISHED));

    if (next) {
      conjunction.add(Expression.gt("pubTime", current.getPubTime()));
    } else {
      conjunction.add(Expression.lt("pubTime", current.getPubTime()));
    }

    if (catName != null && !catName.trim().equals("/")) {
      WeblogCategoryData category = getWeblogCategoryByPath(current.getWebsite(), null, catName);
      if (category != null) {
        conjunction.add(Expression.eq("category", category));
      } else {
        throw new RollerException("Cannot find category: " + catName);
      }
    }

    if (locale != null) {
      conjunction.add(Expression.ilike("locale", locale, MatchMode.START));
    }

    try {
      Session session = ((HibernatePersistenceStrategy) this.strategy).getSession();
      Criteria criteria = session.createCriteria(WeblogEntryData.class);
      criteria.addOrder(next ? Order.asc("pubTime") : Order.desc("pubTime"));
      criteria.add(conjunction);
      criteria.setMaxResults(maxEntries);
      List results = criteria.list();
      return results;
    } catch (HibernateException e) {
      throw new RollerException(e);
    }
  }
  public void moveWeblogCategoryContents(WeblogCategoryData srcCat, WeblogCategoryData destCat)
      throws RollerException {

    // TODO: this check should be made before calling this method?
    if (destCat.descendentOf(srcCat)) {
      throw new RollerException("ERROR cannot move parent category into it's own child");
    }

    // get all entries in category and subcats
    List results = srcCat.retrieveWeblogEntries(true);

    // Loop through entries in src cat, assign them to dest cat
    Iterator iter = results.iterator();
    WebsiteData website = destCat.getWebsite();
    while (iter.hasNext()) {
      WeblogEntryData entry = (WeblogEntryData) iter.next();
      entry.setCategory(destCat);
      entry.setWebsite(website);
      this.strategy.store(entry);
    }

    // Make sure website's default and bloggerapi categories
    // are valid after the move

    if (srcCat.getWebsite().getDefaultCategory().getId().equals(srcCat.getId())
        || srcCat.getWebsite().getDefaultCategory().descendentOf(srcCat)) {
      srcCat.getWebsite().setDefaultCategory(destCat);
      this.strategy.store(srcCat.getWebsite());
    }

    if (srcCat.getWebsite().getBloggerCategory().getId().equals(srcCat.getId())
        || srcCat.getWebsite().getBloggerCategory().descendentOf(srcCat)) {
      srcCat.getWebsite().setBloggerCategory(destCat);
      this.strategy.store(srcCat.getWebsite());
    }
  }
  // TODO: perhaps the createAnchor() and queuePings() items should go outside this method?
  public void saveWeblogEntry(WeblogEntryData entry) throws RollerException {

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

    this.strategy.store(entry);

    // update weblog last modified date.  date updated by saveWebsite()
    if (entry.isPublished()) {
      RollerFactory.getRoller().getUserManager().saveWebsite(entry.getWebsite());
    }

    if (entry.isPublished()) {
      // Queue applicable pings for this update.
      RollerFactory.getRoller().getAutopingManager().queueApplicableAutoPings(entry);
    }
  }