Package org.apache.roller.weblogger.business.jpa

Source Code of org.apache.roller.weblogger.business.jpa.JPAWeblogEntryManagerImpl

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
*  contributor license agreements.  The ASF licenses this file to You
* under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.  For additional information regarding
* copyright in this work, please see the NOTICE file in the top level
* directory of this distribution.
*/

package org.apache.roller.weblogger.business.jpa;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.text.SimpleDateFormat;
import java.util.TreeMap;
import java.sql.Timestamp;
import javax.persistence.NoResultException;
import javax.persistence.Query;

import org.apache.commons.collections.comparators.ReverseComparator;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.roller.weblogger.WebloggerException;
import org.apache.roller.weblogger.business.Weblogger;
import org.apache.roller.weblogger.pojos.WeblogEntryComment;
import org.apache.roller.weblogger.pojos.WeblogHitCount;
import org.apache.roller.weblogger.pojos.WeblogReferrer;
import org.apache.roller.weblogger.pojos.StatCount;
import org.apache.roller.weblogger.pojos.TagStat;
import org.apache.roller.weblogger.pojos.TagStatComparator;
import org.apache.roller.weblogger.pojos.TagStatCountComparator;
import org.apache.roller.weblogger.pojos.WeblogCategory;
import org.apache.roller.weblogger.pojos.WeblogEntry;
import org.apache.roller.weblogger.pojos.WeblogEntryTagAggregate;
import org.apache.roller.weblogger.pojos.WeblogEntryTag;
import org.apache.roller.weblogger.pojos.Weblog;
import org.apache.roller.weblogger.pojos.WeblogEntryAttribute;
import org.apache.roller.weblogger.pojos.StatCountCountComparator;
import org.apache.roller.weblogger.pojos.User;
import org.apache.roller.util.DateUtil;
import org.apache.roller.weblogger.business.WeblogEntryManager;


/**
* JPAWeblogManagerImpl.java
*
* Created on May 31, 2006, 4:08 PM
*
*/
@com.google.inject.Singleton
public class JPAWeblogEntryManagerImpl implements WeblogEntryManager {
   
    protected static Log log = LogFactory.getLog(
            JPAWeblogEntryManagerImpl.class);
   
    private final Weblogger roller;
    private final JPAPersistenceStrategy strategy;
   
    // cached mapping of entryAnchors -> entryIds
    private Hashtable entryAnchorToIdMap = new Hashtable();
   
    /* inline creation of reverse comparator, anonymous inner class */
    private static final Comparator reverseComparator = new ReverseComparator();
   
    private static final Comparator tagStatNameComparator = new TagStatComparator();
   
    private static final Comparator tagStatCountReverseComparator =
            Collections.reverseOrder(TagStatCountComparator.getInstance());
   
    private static final Comparator statCountCountReverseComparator =
            Collections.reverseOrder(StatCountCountComparator.getInstance());
   
   
    @com.google.inject.Inject
    protected JPAWeblogEntryManagerImpl(Weblogger roller, JPAPersistenceStrategy strategy) {
        log.debug("Instantiating JPA Weblog Manager");
        this.roller = roller;
        this.strategy = strategy;
    }
   
    /**
     * @inheritDoc
     */
    public void saveWeblogCategory(WeblogCategory cat) throws WebloggerException {
        boolean exists = getWeblogCategory(cat.getId()) != null;
        if (!exists) {
            if (isDuplicateWeblogCategoryName(cat)) {
                throw new WebloggerException("Duplicate category name, cannot save category");
            }
            // Newly added object. If it has a parent,
            // maintain relationship from both sides
            WeblogCategory parent = cat.getParent();
            if(parent != null) {
                parent.getWeblogCategories().add(cat);
            }
        }
       
        // update weblog last modified date.  date updated by saveWebsite()
        roller.getWeblogManager().saveWeblog(cat.getWebsite());       
        this.strategy.store(cat);
    }
   
    /**
     * @inheritDoc
     */
    public void removeWeblogCategory(WeblogCategory cat)
    throws WebloggerException {
        if(cat.retrieveWeblogEntries(true).size() > 0) {
            throw new WebloggerException("Cannot remove category with entries");
        }
       
        // remove cat
        this.strategy.remove(cat);
        //relationship management for the other side
        WeblogCategory parent = cat.getParent();
        if(parent != null) {
            parent.getWeblogCategories().remove(cat);
        }
       
        // update website default cats if needed
        if(cat.getWebsite().getBloggerCategory().equals(cat)) {
            WeblogCategory rootCat = this.getRootWeblogCategory(cat.getWebsite());
            cat.getWebsite().setBloggerCategory(rootCat);
            this.strategy.store(cat.getWebsite());
        }
       
        if(cat.getWebsite().getDefaultCategory().equals(cat)) {
            WeblogCategory rootCat = this.getRootWeblogCategory(cat.getWebsite());
            cat.getWebsite().setDefaultCategory(rootCat);
            this.strategy.store(cat.getWebsite());
        }
       
        // update weblog last modified date.  date updated by saveWebsite()
        roller.getWeblogManager().saveWeblog(
                cat.getWebsite());
    }
   
    /**
     * @inheritDoc
     */
    public void moveWeblogCategory(WeblogCategory srcCat, WeblogCategory destCat)
    throws WebloggerException {
       
        // TODO: this check should be made before calling this method?
        if (destCat.descendentOf(srcCat)) {
            throw new WebloggerException(
                    "ERROR cannot move parent category into it's own child");
        }
       
        log.debug("Moving category "+srcCat.getPath() +
                " under "+destCat.getPath());
       
       
        WeblogCategory oldParent = srcCat.getParent();
        if(oldParent != null) {
            oldParent.getWeblogCategories().remove(srcCat);
        }
        srcCat.setParent(destCat);
        destCat.getWeblogCategories().add(srcCat);
       
        if("/".equals(destCat.getPath())) {
            srcCat.setPath("/"+srcCat.getName());
        } else {
            srcCat.setPath(destCat.getPath() + "/" + srcCat.getName());
        }
        saveWeblogCategory(srcCat);
       
        // the main work to be done for a category move is to update the
        // path attribute of the category and all descendent categories
        updatePathTree(srcCat);
    }
   
   
    // updates the paths of all descendents of the given category
    private void updatePathTree(WeblogCategory cat)
    throws WebloggerException {
       
        log.debug("Updating path tree for category "+cat.getPath());
       
        WeblogCategory childCat = null;
        Iterator childCats = cat.getWeblogCategories().iterator();
        while(childCats.hasNext()) {
            childCat = (WeblogCategory) childCats.next();
           
            log.debug("OLD child category path was "+childCat.getPath());
           
            // update path and save
            if("/".equals(cat.getPath())) {
                childCat.setPath("/" + childCat.getName());
            } else {
                childCat.setPath(cat.getPath() + "/" + childCat.getName());
            }
            saveWeblogCategory(childCat);
           
            log.debug("NEW child category path is "+ childCat.getPath());
           
            // then make recursive call to update this cats children
            updatePathTree(childCat);
        }
    }
   
    /**
     * @inheritDoc
     */
    public void moveWeblogCategoryContents(WeblogCategory srcCat,
            WeblogCategory destCat)
            throws WebloggerException {
       
        // TODO: this check should be made before calling this method?
        if (destCat.descendentOf(srcCat)) {
            throw new WebloggerException(
                    "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();
        Weblog website = destCat.getWebsite();
        while (iter.hasNext()) {
            WeblogEntry entry = (WeblogEntry) 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());
        }
    }
   
    /**
     * @inheritDoc
     */
    public void saveComment(WeblogEntryComment comment) throws WebloggerException {
        this.strategy.store(comment);
       
        // update weblog last modified date.  date updated by saveWebsite()
        roller.getWeblogManager().saveWeblog(comment.getWeblogEntry().getWebsite());
    }
   
    /**
     * @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());
    }
   
    /**
     * @inheritDoc
     */
    // 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) {
                // Sill no category, so use first one found
                cat = (WeblogCategory)
                    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));
        }
       
        for(Iterator it = entry.getAddedTags().iterator(); it.hasNext();) {
            String name = (String) it.next();
            updateTagCount(name, entry.getWebsite(), 1);
        }
       
        for(Iterator it = entry.getRemovedTags().iterator(); it.hasNext();) {
            String name = (String) it.next();
            updateTagCount(name, entry.getWebsite(), -1);
        }
       
        // 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 ("PUBLISHED".equals(entry.getStatus()) &&
                entry.getPubTime().after(new Date(System.currentTimeMillis() + 60000))) {
            entry.setStatus(WeblogEntry.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 removeWeblogEntry(WeblogEntry entry) throws WebloggerException {
        Weblog weblog = entry.getWebsite();
       
        Query q = strategy.getNamedQuery("WeblogReferrer.getByWeblogEntry");
        q.setParameter(1, entry);
        List referers = q.getResultList();
        for (Iterator iter = referers.iterator(); iter.hasNext();) {
            WeblogReferrer referer = (WeblogReferrer) iter.next();
            this.strategy.remove(referer);
        }
       
        // remove comments
        List comments = getComments(
                null,  // website
                entry,
                null,  // search String
                null,  // startDate
                null,  // endDate
                null,  // status
                true,  // reverse chrono order (not that it matters)
                0,     // offset
                -1);   // no limit
        Iterator commentsIT = comments.iterator();
        while (commentsIT.hasNext()) {
            this.strategy.remove((WeblogEntryComment) commentsIT.next());
        }
       
        // remove tags aggregates
        if (entry.getTags() != null) {
            for(Iterator it = entry.getTags().iterator(); it.hasNext(); ) {
                WeblogEntryTag tag = (WeblogEntryTag) it.next();
                updateTagCount(tag.getName(), entry.getWebsite(), -1);
                it.remove();
                this.strategy.remove(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);
            }
        }
        // TODO: can we eliminate this unnecessary flush with OpenJPA 1.0
        this.strategy.flush();
       
        // 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());
    }
   
    public List getNextPrevEntries(WeblogEntry current, String catName,
            String locale, int maxEntries, boolean next)
            throws WebloggerException {

    if (current == null) {
      log.debug("WeblogEntry current cannot be null");     
      return Collections.emptyList();
    }

        Query query = null;
        List results = null;
        WeblogCategory category = null;
       
        if (catName != null && !catName.trim().equals("/")) {
            category = getWeblogCategoryByPath(current.getWebsite(), null,
                    catName);
        }
               
        List params = new ArrayList();
        int size = 0;
        StringBuffer queryString = new StringBuffer();
        StringBuffer whereClause = new StringBuffer();
        queryString.append("SELECT e FROM WeblogEntry e WHERE ");
                    
        params.add(size++, current.getWebsite());
        whereClause.append("e.website = ?" + size);
       
        params.add(size++, WeblogEntry.PUBLISHED);
        whereClause.append(" AND e.status = ?" + size);
               
        if (next) {
            params.add(size++, current.getPubTime());
            whereClause.append(" AND e.pubTime > ?" + size);
        } else {
            params.add(size++, current.getPubTime());
            whereClause.append(" AND e.pubTime < ?" + size);
        }
       
        if (catName != null && !catName.trim().equals("/")) {
            category = getWeblogCategoryByPath(current.getWebsite(), catName);
            if (category != null) {
                params.add(size++, category);
                whereClause.append(" AND e.category = ?" + size);
            } else {
                throw new WebloggerException("Cannot find category: " + catName);
            }
        }
       
        if(locale != null) {
            params.add(size++, locale + '%');
            whereClause.append(" AND e.locale like ?" + size);
        }
       
        if (next) {
            whereClause.append(" ORDER BY e.pubTime ASC");
        } else {
            whereClause.append(" ORDER BY e.pubTime DESC");
        }
        query = strategy.getDynamicQuery(queryString.toString() + whereClause.toString());
        for (int i=0; i<params.size(); i++) {
            query.setParameter(i+1, params.get(i));
        }
        query.setMaxResults(maxEntries);
       
        return query.getResultList();
    }
   
    /**
     * @inheritDoc
     */
    public WeblogCategory getRootWeblogCategory(Weblog website)
    throws WebloggerException {
        if (website == null)
            throw new WebloggerException("website is null");
       
        Query q = strategy.getNamedQuery(
                "WeblogCategory.getByWebsite&ParentNull");
        q.setParameter(1, website);
        try {
            return (WeblogCategory)q.getSingleResult();
        } catch (NoResultException e) {
            return null;
        }
    }
   
    /**
     * @inheritDoc
     */
    public List getWeblogCategories(Weblog website, boolean includeRoot)
    throws WebloggerException {
        if (website == null)
            throw new WebloggerException("website is null");
       
        if (includeRoot) return getWeblogCategories(website);
       
        Query q = strategy.getNamedQuery(
                "WeblogCategory.getByWebsite&ParentNotNull");
        q.setParameter(1, website);
        return q.getResultList();
    }
   
    /**
     * @inheritDoc
     */
    public List getWeblogCategories(Weblog website)
    throws WebloggerException {
        if (website == null)
            throw new WebloggerException("website is null");
       
        Query q = strategy.getNamedQuery(
                "WeblogCategory.getByWebsite");
        q.setParameter(1, website);
        return q.getResultList();
    }
   
    /**
     * @inheritDoc
     */
    public List getWeblogEntries(
            Weblog website,
            User    user,
            Date        startDate,
            Date        endDate,
            String      catName,
            List        tags,
            String      status,
            String      text,
            String      sortby,
            String      sortOrder,
            String      locale,
            int         offset,
            int         length) throws WebloggerException {
       
        WeblogCategory cat = null;
        if (StringUtils.isNotEmpty(catName) && website != null) {
            cat = getWeblogCategoryByPath(website, catName);
            if (cat == null) catName = null;
        }
        if (catName != null && catName.trim().equals("/")) {
            catName = null;
        }
       
        List params = new ArrayList();
        int size = 0;
        StringBuffer queryString = new StringBuffer();
       
        //queryString.append("SELECT e FROM WeblogEntry e WHERE ");
        if (tags == null || tags.size()==0) {
            queryString.append("SELECT e FROM WeblogEntry e WHERE ");
        } else {
            queryString.append("SELECT e FROM WeblogEntry e JOIN e.tags t WHERE ");
            queryString.append("(");
            for(int i = 0; i < tags.size(); i++) {
                if (i != 0) queryString.append(" OR ");
                params.add(size++, tags.get(i));
                queryString.append(" t.name = ?").append(size);               
            }
            queryString.append(") AND ");
        }
       
        if (website != null) {
            params.add(size++, website.getId());
            queryString.append("e.website.id = ?").append(size);
        } else {
            params.add(size++, Boolean.TRUE);
            queryString.append("e.website.enabled = ?").append(size);
        }
       
        /*if (tags != null && tags.size() > 0) {
            // A JOIN with WeblogEntryTag in parent quert will cause a DISTINCT in SELECT clause
            // WeblogEntry has a clob field and many databases do not link DISTINCT for CLOB fields
            // Hence as a workaround using corelated EXISTS query.
            queryString.append(" AND EXISTS (SELECT t FROM WeblogEntryTag t WHERE "
                    + " t.weblogEntry = e AND t.name IN (");
            final String PARAM_SEPERATOR = ", ";
            for(int i = 0; i < tags.size(); i++) {
                params.add(size++, tags.get(i));
                queryString.append("?").append(size).append(PARAM_SEPERATOR);
            }
            // Remove the trailing PARAM_SEPERATOR
            queryString.delete(queryString.length() - PARAM_SEPERATOR.length(),
                    queryString.length());

            // Close the brace FOR IN clause and EXIST clause
            queryString.append(" ) )");
        }*/

        if (user != null) {
            params.add(size++, user.getUserName());
            queryString.append(" AND e.creatorUserName = ?").append(size);
        }
       
        if (startDate != null) {
            Timestamp start = new Timestamp(startDate.getTime());
            params.add(size++, start);
            queryString.append(" AND e.pubTime >= ?").append(size);
        }
       
        if (endDate != null) {
            Timestamp end = new Timestamp(endDate.getTime());
            params.add(size++, end);
            queryString.append(" AND e.pubTime <= ?").append(size);
        }
       
        if (cat != null && website != null) {
            params.add(size++, cat.getId());
            queryString.append(" AND e.category.id = ?").append(size);
        }
               
        if (status != null) {
            params.add(size++, status);
            queryString.append(" AND e.status = ?").append(size);
        }
       
        if (locale != null) {
            params.add(size++, locale + '%');
            queryString.append(" AND e.locale like ?").append(size);
        }
       
        if (text != null) {
            params.add(size++, '%' + text + '%');
            queryString.append(" AND ( e.text LIKE ?").append(size);
            queryString.append("    OR e.summary LIKE ? ").append(size);
            queryString.append("    OR e.title LIKE ?").append(size);
            queryString.append(") ");
        }
       
        if (sortby != null && sortby.equals("updateTime")) {
            queryString.append(" ORDER BY e.updateTime ");
        } else {
            queryString.append(" ORDER BY e.pubTime ");
        }
       
        if (sortOrder != null && sortOrder.equals(ASCENDING)) {
            queryString.append("ASC ");
        } else {
            queryString.append("DESC ");
        }
       
       
        Query query = strategy.getDynamicQuery(queryString.toString());
        for (int i=0; i<params.size(); i++) {
            query.setParameter(i+1, params.get(i));
        }
       
        if (offset != 0) {
            query.setFirstResult(offset);
        }
        if (length != -1) {
            query.setMaxResults(length);
        }
       
        return query.getResultList();
    }
   
    /**
     * @inheritDoc
     */
    public List getWeblogEntriesPinnedToMain(Integer max)
    throws WebloggerException {
        Query query = strategy.getNamedQuery(
                "WeblogEntry.getByPinnedToMain&statusOrderByPubTimeDesc");
        query.setParameter(1, Boolean.TRUE);
        query.setParameter(2, WeblogEntry.PUBLISHED);
        if (max != null) {
            query.setMaxResults(max.intValue());
        }
        return query.getResultList();
    }
   
    public void removeWeblogEntryAttribute(String name, WeblogEntry entry)
    throws WebloggerException {

        // seems silly, why is this not done in WeblogEntry?

        for (Iterator it = entry.getEntryAttributes().iterator(); it.hasNext();) {
            WeblogEntryAttribute entryAttribute = (WeblogEntryAttribute) it.next();
            if (entryAttribute.getName().equals(name)) {

                //Remove it from database
                this.strategy.remove(entryAttribute);

                //Remove it from the collection
                it.remove();
            }
        }
    }
   
    public void removeWeblogEntryTag(String name, WeblogEntry entry)
    throws WebloggerException {

        // seems silly, why is this not done in WeblogEntry?

        for (Iterator it = entry.getTags().iterator(); it.hasNext();) {
            WeblogEntryTag tag = (WeblogEntryTag) it.next();
            if (tag.getName().equals(name)) {

                //Call back the entity to adjust its internal state
                entry.onRemoveTag(name);

                //Remove it from database
                this.strategy.remove(tag);
               
                //Remove it from the collection
                it.remove();
            }
        }
    }
   
    /**
     * @inheritDoc
     */
    public WeblogEntry getWeblogEntryByAnchor(Weblog website,
            String anchor) throws WebloggerException {
       
        if (website == null)
            throw new WebloggerException("Website is null");
       
        if (anchor == null)
            throw new WebloggerException("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)) {
           
            WeblogEntry 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
        Query q = strategy.getNamedQuery(
                "WeblogEntry.getByWebsite&AnchorOrderByPubTimeDesc");
        q.setParameter(1, website);
        q.setParameter(2, anchor);
        WeblogEntry entry = null;
        try {
            entry = (WeblogEntry)q.getSingleResult();
        } catch (NoResultException e) {
            entry = null;
        }
       
        // add mapping to cache
        if(entry != null) {
            log.debug("entryAnchorToIdMap CACHE MISS - "+mappingKey);
            this.entryAnchorToIdMap.put(mappingKey, entry.getId());
        }
        return entry;
    }
   
    /**
     * @inheritDoc
     */
    // TODO: this method should be removed and it's functionality moved to getWeblogEntries()
    public List getWeblogEntries(WeblogCategory cat, boolean subcats)
    throws WebloggerException {
        List results = null;
       
        if (!subcats) {
            Query q = strategy.getNamedQuery(
                    "WeblogEntry.getByStatus&Category");
            q.setParameter(1, WeblogEntry.PUBLISHED);
            q.setParameter(2, cat);
            results = q.getResultList();
        } else {
            Query q = strategy.getNamedQuery(
                    "WeblogEntry.getByStatus&Category.pathLike&Website");
            q.setParameter(1, WeblogEntry.PUBLISHED);
            q.setParameter(2, cat.getPath() + '%');
            q.setParameter(3, cat.getWebsite());
            results = q.getResultList();
        }
       
        return results;
    }
   
    /**
     * @inheritDoc
     */
    public String createAnchor(WeblogEntry entry) throws WebloggerException {
        // Check for uniqueness of anchor
        String base = entry.createAnchorBase();
        String name = base;
        int count = 0;
       
        while (true) {
            if (count > 0) {
                name = base + count;
            }
           
            Query q = strategy.getNamedQuery(
                    "WeblogEntry.getByWebsite&Anchor");
            q.setParameter(1, entry.getWebsite());
            q.setParameter(2, name);
            List results = q.getResultList();
           
            if (results.size() < 1) {
                break;
            } else {
                count++;
            }
        }
        return name;
    }
   
    /**
     * @inheritDoc
     */
    public boolean isDuplicateWeblogCategoryName(WeblogCategory cat)
    throws WebloggerException {
       
        // ensure that no sibling categories share the same name
        WeblogCategory parent = cat.getParent();
        if (null != parent) {
            return (getWeblogCategoryByPath(
                    cat.getWebsite(), cat.getPath()) != null);
        }
       
        return false;
    }
   
    /**
     * @inheritDoc
     */
    public boolean isWeblogCategoryInUse(WeblogCategory cat)
    throws WebloggerException {
       
        Query q = strategy.getNamedQuery("WeblogEntry.getByCategory");
        q.setParameter(1, cat);
        int entryCount = q.getResultList().size();
       
        if (entryCount > 0) {
            return true;
        }
       
        Iterator cats = cat.getWeblogCategories().iterator();
        while (cats.hasNext()) {
            WeblogCategory childCat = (WeblogCategory)cats.next();
            if (childCat.isInUse()) {
                return true;
            }
        }
       
        if (cat.getWebsite().getBloggerCategory().equals(cat)) {
            return true;
        }
       
        if (cat.getWebsite().getDefaultCategory().equals(cat)) {
            return true;
        }
       
        return false;
    }
   
    /**
     * @inheritDoc
     */
    public List getComments(
            Weblog     website,
            WeblogEntry entry,
            String          searchString,
            Date            startDate,
            Date            endDate,
            String          status,
            boolean         reverseChrono,
            int             offset,
            int             length) throws WebloggerException {
       
        List params = new ArrayList();
        int size = 0;
        StringBuffer queryString = new StringBuffer();
        queryString.append("SELECT c FROM WeblogEntryComment c ");
       
        StringBuffer whereClause = new StringBuffer();
        if (entry != null) {
            params.add(size++, entry);
            whereClause.append("c.weblogEntry = ?").append(size);
        } else if (website != null) {
            params.add(size++, website);
            whereClause.append("c.weblogEntry.website = ?").append(size);
        }
       
        if (searchString != null) {
            params.add(size++, "%" + searchString + "%");
            appendConjuctionToWhereclause(whereClause, "(c.url LIKE ?")
                .append(size).append(" OR c.content LIKE ?").append(size).append(")");
        }
       
        if (startDate != null) {
            Timestamp start = new Timestamp(startDate.getTime());
            params.add(size++, start);
            appendConjuctionToWhereclause(whereClause, "c.postTime >= ?").append(size);
        }
       
        if (endDate != null) {
            Timestamp end = new Timestamp(endDate.getTime());
            params.add(size++, end);
            appendConjuctionToWhereclause(whereClause, "c.postTime <= ?").append(size);
        }
       
        if (status != null) {
            String comparisionOperator;
            if("ALL_IGNORE_SPAM".equals(status)) {
                // we want all comments, except spam
                // so that means where status != SPAM
                status = WeblogEntryComment.SPAM;
                comparisionOperator = " <> ";
            } else {
                comparisionOperator = " = ";
            }
            params.add(size++, status);
            appendConjuctionToWhereclause(whereClause, "c.status ")
                .append(comparisionOperator).append('?').append(size);
        }
       
        if(whereClause.length() != 0) {
            queryString.append(" WHERE ").append(whereClause);
        }
        if (reverseChrono) {
            queryString.append(" ORDER BY c.postTime DESC");
        } else {
            queryString.append(" ORDER BY c.postTime ASC");
        }
       
        Query query = strategy.getDynamicQuery(queryString.toString());
        if (offset != 0) {
            query.setFirstResult(offset);
        }
        if (length != -1) {
            query.setMaxResults(length);
        }
        for (int i=0; i<params.size(); i++) {
            query.setParameter(i+1, params.get(i));
        }
        return query.getResultList();
       
    }
   
   
    /**
     * @inheritDoc
     */
    public int removeMatchingComments(
            Weblog     website,
            WeblogEntry entry,
            String  searchString,
            Date    startDate,
            Date    endDate,
            String 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"
       
        List comments = getComments(
                website, entry, searchString, startDate, endDate,
                status, true, 0, -1);
        int count = 0;
        for (Iterator it = comments.iterator(); it.hasNext();) {
            WeblogEntryComment comment = (WeblogEntryComment) it.next();
            removeComment(comment);
            count++;
        }
        return count;
    }
   
   
    /**
     * @inheritDoc
     */
    public WeblogCategory getWeblogCategory(String id)
    throws WebloggerException {
        return (WeblogCategory) this.strategy.load(
                WeblogCategory.class, id);
    }
   
    //--------------------------------------------- WeblogCategory Queries
   
    /**
     * @inheritDoc
     */
    public WeblogCategory getWeblogCategoryByPath(Weblog website,
            String categoryPath) throws WebloggerException {
        return getWeblogCategoryByPath(website, null, categoryPath);
    }
   
    /**
     * @inheritDoc
     */
    // TODO: ditch this method in favor of getWeblogCategoryByPath(weblog, path)
    public WeblogCategory getWeblogCategoryByPath(Weblog website,
            WeblogCategory category, String path) throws WebloggerException {
       
        if (path == null || path.trim().equals("/")) {
            return getRootWeblogCategory(website);
        } else {
            String catPath = path;
           
            // all cat paths must begin with a '/'
            if(!catPath.startsWith("/")) {
                catPath = "/"+catPath;
            }
           
            // now just do simple lookup by path
            Query q = strategy.getNamedQuery(
                    "WeblogCategory.getByPath&Website");
            q.setParameter(1, catPath);
            q.setParameter(2, website);
            try {
                return (WeblogCategory)q.getSingleResult();
            } catch (NoResultException e) {
                return null;
            }
        }
    }
   
    /**
     * @inheritDoc
     */
    public WeblogEntryComment getComment(String id) throws WebloggerException {
        return (WeblogEntryComment) this.strategy.load(WeblogEntryComment.class, id);
    }
   
    /**
     * @inheritDoc
     */
    public WeblogEntry getWeblogEntry(String id) throws WebloggerException {
        return (WeblogEntry)strategy.load(WeblogEntry.class, id);
    }
   
    /**
     * @inheritDoc
     */
    public Map getWeblogEntryObjectMap(
            Weblog website,
            Date    startDate,
            Date    endDate,
            String  catName,
            List    tags,
            String  status,
            String  locale,
            int     offset,
            int     length) throws WebloggerException {
        return getWeblogEntryMap(
                website,
                startDate,
                endDate,
                catName,
                tags,
                status,
                false,
                locale,
                offset,
                length);
    }
   
    /**
     * @inheritDoc
     */
    public Map getWeblogEntryStringMap(
            Weblog website,
            Date    startDate,
            Date    endDate,
            String  catName,
            List    tags,
            String  status,
            String  locale,
            int     offset,
            int     length
            ) throws WebloggerException {
        return getWeblogEntryMap(
                website,
                startDate,
                endDate,
                catName,
                tags,
                status,
                true,
                locale,
                offset,
                length);
    }
   
    private Map getWeblogEntryMap(
            Weblog website,
            Date    startDate,
            Date    endDate,
            String  catName,
            List    tags,
            String  status,
            boolean stringsOnly,
            String  locale,
            int     offset,
            int     length) throws WebloggerException {
       
        TreeMap map = new TreeMap(reverseComparator);
       
        List entries = getWeblogEntries(
                website,
                null, // user
                startDate,
                endDate,
                catName,
                tags,
                status,
                null, // text
                null, // sortBy
                null, // sortOrder
                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();) {
            WeblogEntry entry = (WeblogEntry) 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;
    }
   
    /**
     * @inheritDoc
     */
    public List getMostCommentedWeblogEntries(Weblog website,
            Date startDate, Date endDate, int offset,
            int length) throws WebloggerException {
        Query query = null;
        List queryResults = null;       
        if (endDate == null) endDate = new Date();
       
        if (website != null) {
            if (startDate != null) {
                Timestamp start = new Timestamp(startDate.getTime());
                Timestamp end = new Timestamp(endDate.getTime());
                query = strategy.getNamedQuery(
                        "WeblogEntryComment.getMostCommentedWeblogEntryByWebsite&EndDate&StartDate");
                query.setParameter(1, website);
                query.setParameter(2, end);
                query.setParameter(3, start);
            } else {
                Timestamp end = new Timestamp(endDate.getTime());
                query = strategy.getNamedQuery(
                        "WeblogEntryComment.getMostCommentedWeblogEntryByWebsite&EndDate");
                query.setParameter(1, website);
                query.setParameter(2, end);
            }
        } else {
            if (startDate != null) {
                Timestamp start = new Timestamp(startDate.getTime());
                Timestamp end = new Timestamp(endDate.getTime());
                query = strategy.getNamedQuery(
                        "WeblogEntryComment.getMostCommentedWeblogEntryByEndDate&StartDate");
                query.setParameter(1, end);
                query.setParameter(2, start);
            } else {
                Timestamp end = new Timestamp(endDate.getTime());
                query = strategy.getNamedQuery(
                        "WeblogEntryComment.getMostCommentedWeblogEntryByEndDate");
                query.setParameter(1, end);
            }
        }
        if (offset != 0) {
            query.setFirstResult(offset);
        }
        if (length != -1) {
            query.setMaxResults(length);
        }
        queryResults = query.getResultList();
        List results = new ArrayList();
        for (Iterator iter = queryResults.iterator(); iter.hasNext();) {
            Object[] row = (Object[]) iter.next();
            StatCount sc = new StatCount(
                    (String)row[1],                             // weblog handle
                    (String)row[2],                             // entry anchor
                    (String)row[3],                             // entry title
                    "statCount.weblogEntryCommentCountType",    // stat desc
                    ((Long)row[0]).longValue());                // count
            sc.setWeblogHandle((String)row[1]);
            results.add(sc);
        }
        // Original query ordered by desc count.
        // JPA QL doesn't allow queries to be ordered by agregates; do it in memory
        Collections.sort(results, statCountCountReverseComparator);
       
        return results;
    }
   
    /**
     * @inheritDoc
     */
    public WeblogEntry getNextEntry(WeblogEntry current,
            String catName, String locale) throws WebloggerException {
        WeblogEntry entry = null;
        List entryList = getNextPrevEntries(current, catName, locale, 1, true);
        if (entryList != null && entryList.size() > 0) {
            entry = (WeblogEntry)entryList.get(0);
        }
        return entry;
    }
   
    /**
     * @inheritDoc
     */
    public WeblogEntry getPreviousEntry(WeblogEntry current,
            String catName, String locale) throws WebloggerException {
        WeblogEntry entry = null;
        List entryList = getNextPrevEntries(current, catName, locale, 1, false);
        if (entryList != null && entryList.size() > 0) {
            entry = (WeblogEntry)entryList.get(0);
        }
        return entry;
    }
   
    /**
     * @inheritDoc
     */
    public void release() {}
   
    /**
     * @inheritDoc
     */
    public void applyCommentDefaultsToEntries(Weblog website)
    throws WebloggerException {
        if (log.isDebugEnabled()) {
            log.debug("applyCommentDefaults");
        }
       
        // TODO: Non-standard JPA bulk update, using parameter values in set clause
        Query q = strategy.getNamedUpdate(
                "WeblogEntry.updateAllowComments&CommentDaysByWebsite");
        q.setParameter(1, website.getDefaultAllowComments());
        q.setParameter(2, new Integer(website.getDefaultCommentDays()));
        q.setParameter(3, website);
        q.executeUpdate();
    }
   
    /**
     * @inheritDoc
     */
    public List getPopularTags(Weblog website, Date startDate, int offset, int limit)
    throws WebloggerException {
        Query query = null;
        List queryResults = null;
       
        if (website != null) {
            if (startDate != null) {
                Timestamp start = new Timestamp(startDate.getTime());
                query = strategy.getNamedQuery(
                        "WeblogEntryTagAggregate.getPopularTagsByWebsite&StartDate");
                query.setParameter(1, website);
                query.setParameter(2, start);
            } else {
                query = strategy.getNamedQuery(
                        "WeblogEntryTagAggregate.getPopularTagsByWebsite");
                query.setParameter(1, website);
            }
        } else {
            if (startDate != null) {
                Timestamp start = new Timestamp(startDate.getTime());
                query = strategy.getNamedQuery(
                        "WeblogEntryTagAggregate.getPopularTagsByWebsiteNull&StartDate");
                query.setParameter(1, start);
            } else {
                query = strategy.getNamedQuery(
                        "WeblogEntryTagAggregate.getPopularTagsByWebsiteNull");
            }
        }
        if (offset != 0) {
            query.setFirstResult(offset);
        }
        if (limit != -1) {
            query.setMaxResults(limit);
        }
        queryResults = query.getResultList();
       
        double min = Integer.MAX_VALUE;
        double max = Integer.MIN_VALUE;
       
        List results = new ArrayList(limit);
       
        for (Iterator iter = queryResults.iterator(); iter.hasNext();) {
            Object[] row = (Object[]) iter.next();
            TagStat t = new TagStat();
            t.setName((String) row[0]);
            t.setCount(((Number) row[1]).intValue());
           
            min = Math.min(min, t.getCount());
            max = Math.max(max, t.getCount());
            results.add(t);
        }
       
        min = Math.log(1+min);
        max = Math.log(1+max);
       
        double range = Math.max(.01, max - min) * 1.0001;
       
        for (Iterator iter = results.iterator(); iter.hasNext(); ) {
            TagStat t = (TagStat) iter.next();
            t.setIntensity((int) (1 + Math.floor(5 * (Math.log(1+t.getCount()) - min) / range)));
        }
       
        // sort results by name, because query had to sort by total
        Collections.sort(results, tagStatNameComparator);
       
        return results;
    }
   
    /**
     * @inheritDoc
     */
    public List getTags(Weblog website, String sortBy,
            String startsWith, int offset, int limit) throws WebloggerException {
        Query query = null;
        List queryResults = null;
        boolean sortByName = sortBy == null || !sortBy.equals("count");
               
        List params = new ArrayList();
        int size = 0;
        StringBuffer queryString = new StringBuffer();           
        queryString.append("SELECT w.name, SUM(w.total) FROM WeblogEntryTagAggregate w WHERE ");
               
        if (website != null) {
            params.add(size++, website.getId());
            queryString.append(" w.weblog.id = ?").append(size);
        } else {
            queryString.append(" w.weblog IS NULL");
        }
                      
        if (startsWith != null && startsWith.length() > 0) {
            params.add(size++, startsWith + '%');
            queryString.append(" AND w.name LIKE ?" + size);
        }
                   
        if (sortBy != null && sortBy.equals("count")) {
            sortBy = "w.total DESC";
        } else {
            sortBy = "w.name";
        }
        queryString.append(" GROUP BY w.name, w.total ORDER BY " + sortBy);

        query = strategy.getDynamicQuery(queryString.toString());
        for (int i=0; i<params.size(); i++) {
            query.setParameter(i+1, params.get(i));
        }
        if (offset != 0) {
            query.setFirstResult(offset);
        }
        if (limit != -1) {
            query.setMaxResults(limit);
        }
        queryResults = query.getResultList();
       
        List results = new ArrayList();
        for (Iterator iter = queryResults.iterator(); iter.hasNext();) {
            Object[] row = (Object[]) iter.next();
            TagStat ce = new TagStat();
            ce.setName((String) row[0]);
            // The JPA query retrieves SUM(w.total) always as long
            ce.setCount(((Long) row[1]).intValue());
            results.add(ce);
        }
       
        if (sortByName) {
            Collections.sort(results, tagStatNameComparator);
        } else {
            Collections.sort(results, tagStatCountReverseComparator);
        }
       
        return results;
    }
   
   
    /**
     * @inheritDoc
     */
    public boolean getTagComboExists(List tags, Weblog weblog) throws WebloggerException{
       
        if(tags == null || tags.size() == 0) {
            return false;
        }
       
        StringBuffer queryString = new StringBuffer();
        queryString.append("SELECT DISTINCT w.name ");
        queryString.append("FROM WeblogEntryTagAggregate w WHERE w.name IN (");
        //?1) AND w.weblog = ?2");
        //Append tags as parameter markers to avoid potential escaping issues
        //The IN clause would be of form (?1, ?2, ?3, ..)
        ArrayList params = new ArrayList(tags.size() + 1);
        final String PARAM_SEPERATOR = ", ";
        int i;
        for (i=0; i < tags.size(); i++) {
            queryString.append('?').append(i+1).append(PARAM_SEPERATOR);
            params.add(tags.get(i));
        }
       
        // Remove the trailing PARAM_SEPERATOR
        queryString.delete(queryString.length() - PARAM_SEPERATOR.length(),
                queryString.length());
        // Close the brace of IN clause
        queryString.append(')');
       
        if(weblog != null) {
            queryString.append(" AND w.weblog = ?").append(i+1);
            params.add(weblog);
        } else {
            queryString.append(" AND w.weblog IS NULL");
        }
       
        Query q = strategy.getDynamicQuery(queryString.toString());
        for (int j=0; j<params.size(); j++) {
            q.setParameter(j+1, params.get(j));
        }
        List results = q.getResultList();
       
        //TODO: DatamapperPort: Since we are only interested in knowing whether
        //results.size() == tags.size(). This query can be optimized to just fetch COUNT
        //instead of objects as done currently
        return (results != null && results.size() == tags.size());
    }
   
    /**
     * @inheritDoc
     */
    public 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
        Query weblogQuery = strategy.getNamedQuery(
                "WeblogEntryTagAggregate.getByName&WebsiteOrderByLastUsedDesc");
        weblogQuery.setParameter(1, name);
        weblogQuery.setParameter(2, website);
        WeblogEntryTagAggregate weblogTagData;
        try {
            weblogTagData = (WeblogEntryTagAggregate)weblogQuery.getSingleResult();
        } catch (NoResultException e) {
            weblogTagData = null;
        }
       
        Query siteQuery = strategy.getNamedQuery(
                "WeblogEntryTagAggregate.getByName&WebsiteNullOrderByLastUsedDesc");
        siteQuery.setParameter(1, name);
        WeblogEntryTagAggregate siteTagData;
        try {
            siteTagData = (WeblogEntryTagAggregate)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);
            // Why use update query when only one object needs update?
//            Query update = strategy.getNamedUpdate(
//                    "WeblogEntryTagAggregate.updateAddToTotalByName&Weblog");
//            update.setParameter(1, new Long(amount));
//            update.setParameter(2, lastUsed);
//            update.setParameter(3, weblogTagData.getName());
//            update.setParameter(4, website);
//            update.executeUpdate();
        }
       
        // 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);
            // Why use update query when only one object needs update?
//            Query update = strategy.getNamedUpdate(
//                    "WeblogEntryTagAggregate.updateAddToTotalByName&WeblogNull");
//            update.setParameter(1, new Long(amount));
//            update.setParameter(2, siteTagData.getName());
//            update.executeUpdate();
        }
       
        // delete all bad counts
        Query removeq = strategy.getNamedUpdate(
                "WeblogEntryTagAggregate.removeByTotalLessEqual");
        removeq.setParameter(1, new Integer(0));
        removeq.executeUpdate();
    }
   
    /**
     * @inheritDoc
     */
    public WeblogHitCount getHitCount(String id) throws WebloggerException {
       
        // do lookup
        return (WeblogHitCount) strategy.load(WeblogHitCount.class, id);
    }
   
    /**
     * @inheritDoc
     */
    public WeblogHitCount getHitCountByWeblog(Weblog weblog)
    throws WebloggerException {
        Query q = strategy.getNamedQuery("WeblogHitCount.getByWeblog");
        q.setParameter(1, weblog);
        try {
            return (WeblogHitCount)q.getSingleResult();
        } catch (NoResultException e) {
            return null;
        }
    }
   
    /**
     * @inheritDoc
     */
    public List getHotWeblogs(int sinceDays, int offset, int length)
    throws WebloggerException {
       
        // figure out start date
        Calendar cal = Calendar.getInstance();
        cal.setTime(new Date());
        cal.add(Calendar.DATE, -1 * sinceDays);
        Date startDate = cal.getTime();
       
        Query query = strategy.getNamedQuery(
                "WeblogHitCount.getByWeblogEnabledTrueAndActiveTrue&DailyHitsGreaterThenZero&WeblogLastModifiedGreaterOrderByDailyHitsDesc");
        query.setParameter(1, startDate);
       
        // Was commented out due to https://glassfish.dev.java.net/issues/show_bug.cgi?id=2084
        // TODO: determine if this is still an issue. Is it a problem with other JPA implementations?
        if (offset != 0) {
            query.setFirstResult(offset);
        }
        if (length != -1) {
            query.setMaxResults(length);
        }       
        return query.getResultList();
    }
   
   
    /**
     * @inheritDoc
     */
    public void saveHitCount(WeblogHitCount hitCount) throws WebloggerException {
        this.strategy.store(hitCount);
    }
   
   
    /**
     * @inheritDoc
     */
    public void removeHitCount(WeblogHitCount hitCount) throws WebloggerException {
        this.strategy.remove(hitCount);
    }
   
   
    /**
     * @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.");
        }
       
        Query q = strategy.getNamedQuery("WeblogHitCount.getByWeblog");
        q.setParameter(1, weblog);
        WeblogHitCount hitCount = null;
        try {
            hitCount = (WeblogHitCount)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);
        }
    }
   
    /**
     * @inheritDoc
     */
    public void resetAllHitCounts() throws WebloggerException {      
        Query q = strategy.getNamedUpdate("WeblogHitCount.updateDailyHitCountZero");
        q.executeUpdate();
    }
   
    /**
     * @inheritDoc
     */
    public void resetHitCount(Weblog weblog) throws WebloggerException {
        Query q = strategy.getNamedQuery("WeblogHitCount.getByWeblog");
        q.setParameter(1, weblog);
        WeblogHitCount hitCount = null;
        try {
            hitCount = (WeblogHitCount)q.getSingleResult();
            hitCount.setDailyHits(0);
            strategy.store(hitCount);
        } catch (NoResultException e) {
            // ignore: no hit count for weblog
        }      

    }
   
    /**
     * @inheritDoc
     */
    public long getCommentCount() throws WebloggerException {
        Query q = strategy.getNamedQuery(
                "WeblogEntryComment.getCountAllDistinctByStatus");
        q.setParameter(1, WeblogEntryComment.APPROVED);
        List results = q.getResultList();
        return ((Long)results.get(0)).longValue();
    }
   
    /**
     * @inheritDoc
     */
    public long getCommentCount(Weblog website) throws WebloggerException {
        Query q = strategy.getNamedQuery(
                "WeblogEntryComment.getCountDistinctByWebsite&Status");
        q.setParameter(1, website);
        q.setParameter(2, WeblogEntryComment.APPROVED);
        List results = q.getResultList();
        return ((Long)results.get(0)).longValue();
    }
   
    /**
     * @inheritDoc
     */
    public long getEntryCount() throws WebloggerException {
        Query q = strategy.getNamedQuery(
                "WeblogEntry.getCountDistinctByStatus");
        q.setParameter(1, "PUBLISHED");
        List results = q.getResultList();
        return ((Long)results.get(0)).longValue();
    }
   
    /**
     * @inheritDoc
     */
    public long getEntryCount(Weblog website) throws WebloggerException {
        Query q = strategy.getNamedQuery(
                "WeblogEntry.getCountDistinctByStatus&Website");
        q.setParameter(1, "PUBLISHED");
        q.setParameter(2, website);
        List results = q.getResultList();
        return ((Long)results.get(0)).longValue();
    }
   
    /**
     * Appends given expression to given whereClause. If whereClause already
     * has other conditions, an " AND " is also appended before appending
     * the expression
     * @param whereClause The given where Clauuse
     * @param expression The given expression
     * @return the whereClause.
     */
    private static StringBuffer appendConjuctionToWhereclause(StringBuffer whereClause,
            String expression) {
        if(whereClause.length() != 0 && expression.length() != 0) {
            whereClause.append(" AND ");
        }
        return whereClause.append(expression);
    }
   
}
TOP

Related Classes of org.apache.roller.weblogger.business.jpa.JPAWeblogEntryManagerImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.