You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@roller.apache.org by cl...@apache.org on 2006/12/05 01:26:21 UTC

svn commit: r482428 [3/6] - in /incubator/roller/trunk/sandbox/jdobackend: src/org/apache/roller/business/datamapper/ src/org/apache/roller/business/jdo/ src/org/apache/roller/business/jpa/ src/org/apache/roller/planet/ src/org/apache/roller/planet/poj...

Modified: incubator/roller/trunk/sandbox/jdobackend/src/org/apache/roller/business/datamapper/DatamapperUserManagerImpl.java
URL: http://svn.apache.org/viewvc/incubator/roller/trunk/sandbox/jdobackend/src/org/apache/roller/business/datamapper/DatamapperUserManagerImpl.java?view=diff&rev=482428&r1=482427&r2=482428
==============================================================================
--- incubator/roller/trunk/sandbox/jdobackend/src/org/apache/roller/business/datamapper/DatamapperUserManagerImpl.java (original)
+++ incubator/roller/trunk/sandbox/jdobackend/src/org/apache/roller/business/datamapper/DatamapperUserManagerImpl.java Mon Dec  4 16:26:15 2006
@@ -18,18 +18,16 @@
  */
 package org.apache.roller.business.datamapper;
 
-import java.util.Collection;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.roller.RollerException;
-import org.apache.roller.model.RollerFactory;
-import org.apache.roller.model.UserManager;
-import org.apache.roller.model.WeblogManager;
+import org.apache.roller.business.BookmarkManager;
+import org.apache.roller.business.RollerFactory;
+import org.apache.roller.business.UserManager;
+import org.apache.roller.business.WeblogManager;
+import org.apache.roller.business.pings.AutoPingManager;
+import org.apache.roller.business.pings.PingTargetManager;
+import org.apache.roller.config.RollerConfig;
 import org.apache.roller.pojos.AutoPingData;
 import org.apache.roller.pojos.BookmarkData;
 import org.apache.roller.pojos.FolderData;
@@ -37,11 +35,22 @@
 import org.apache.roller.pojos.PingQueueEntryData;
 import org.apache.roller.pojos.PingTargetData;
 import org.apache.roller.pojos.RefererData;
+import org.apache.roller.pojos.StatCount;
 import org.apache.roller.pojos.UserData;
 import org.apache.roller.pojos.WeblogCategoryData;
 import org.apache.roller.pojos.WeblogEntryData;
 import org.apache.roller.pojos.WeblogTemplate;
 import org.apache.roller.pojos.WebsiteData;
+import org.apache.roller.pojos.CommentData;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.Collections;
 
 /*
  * DatamapperUserManagerImpl.java
@@ -51,522 +60,940 @@
  */
 public class DatamapperUserManagerImpl implements UserManager {
     
+    /** The logger instance for this class. */
+    private static Log log = LogFactory.getLog(DatamapperUserManagerImpl.class);    
+
     private DatamapperPersistenceStrategy strategy;
     
-    /** The logger instance for this class. */
-    private static Log logger = LogFactory
-            .getFactory().getInstance(DatamapperPingTargetManagerImpl.class);
 
-    /** Creates a new instance of DatamapperPropertiesManagerImpl */
-    public DatamapperUserManagerImpl
-            (DatamapperPersistenceStrategy strategy) {
-        this.strategy = strategy;
-    }
+    // cached mapping of weblogHandles -> weblogIds
+    private Map weblogHandleToIdMap = new Hashtable();
 
-    public void addUser(UserData newUser) 
-            throws RollerException {
-    }
-
-    public void saveUser(UserData data) 
-           throws RollerException {
-        strategy.store(data);
-    }
+    // cached mapping of userNames -> userIds
+    private Map userNameToIdMap = new Hashtable();
 
-    public void removeUser(UserData user) 
-            throws RollerException {
-        strategy.remove(user);
-    }
+    public DatamapperUserManagerImpl(DatamapperPersistenceStrategy strat) {
+        log.debug("Instantiating Datamapper User Manager");
 
-    public UserData getUser(String id) 
-            throws RollerException {
-        return (UserData)strategy.load(UserData.class, id);
+        this.strategy = strat;
     }
 
     /**
-     * Get user object by user name (only enabled users)
+     * Update existing website.
      */
-    public UserData getUserByUserName(String userName) throws RollerException {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
-    }
+    public void saveWebsite(WebsiteData website) throws RollerException {
 
-    /**
-     * Get user object by user name, optionally include dis-enabled users
-     */
-    public UserData getUserByUserName(String userName, Boolean enabled)
-            throws RollerException {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
+        website.setLastModified(new java.util.Date());
+        strategy.store(website);
     }
 
-    /**
-     * Get all enabled users
-     */
-    public List getUsers(int offset, int length) throws RollerException {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
-    }
+    public void removeWebsite(WebsiteData weblog) throws RollerException {
 
-    /**
-     * Get all users, optionally include dis-enabled users.
-     * @param enabled True for enabled only, false for disabled only, null for
-     * all
-     * @param startDate Restrict to those created after (or null for all)
-     * @param endDate Restrict to those created before (or null for all)
-     */
-    public List getUsers(Boolean enabled, Date startDate, Date endDate,
-            int offset, int length) throws RollerException {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
+        // remove contents first, then remove website
+        this.removeWebsiteContents(weblog);
+        this.strategy.remove(weblog);
+
+        // remove entry from cache mapping
+        this.weblogHandleToIdMap.remove(weblog.getHandle());
     }
 
     /**
-     * Get all users or a website.
-     * @param website Get all users of this website (or null for all)
-     * @returns List of UserData objects.
+     * convenience method for removing contents of a weblog.
+     * TODO BACKEND: use manager methods instead of queries here
+     * TODO DatamapperPort: Use bulk deletes instead of current approach
      */
-    public List getUsers(WebsiteData website, Boolean enabled, int offset,
-            int length) throws RollerException {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    private void removeWebsiteContents(WebsiteData website) throws  RollerException {
+
+        BookmarkManager bmgr = RollerFactory.getRoller().getBookmarkManager();
+        WeblogManager wmgr = RollerFactory.getRoller().getWeblogManager();
+
+        // Remove the website's ping queue entries
+        List queueEntries = (List)strategy.newQuery(PingQueueEntryData.class,
+                "PingQueueEntryData.getByWebsite").execute(website);
+        Iterator it = queueEntries.iterator();
+        while(it.hasNext()) {
+            this.strategy.remove((PingQueueEntryData) it.next());
+        }
+
+        // Remove the website's auto ping configurations
+        AutoPingManager autoPingMgr = RollerFactory.getRoller().getAutopingManager();
+        List autopings = autoPingMgr.getAutoPingsByWebsite(website);
+        it = autopings.iterator();
+        while(it.hasNext()) {
+            this.strategy.remove((AutoPingData) it.next());
+        }
+
+        // Remove the website's custom ping targets
+        PingTargetManager pingTargetMgr = RollerFactory.getRoller().getPingTargetManager();
+        List pingtargets = pingTargetMgr.getCustomPingTargets(website);
+        it = pingtargets.iterator();
+        while(it.hasNext()) {
+            this.strategy.remove((PingTargetData) it.next());
+        }
+
+        // remove entries
+        List entries = (List)strategy.newQuery(PingQueueEntryData.class,
+                "WeblogEntryData.getByWebsite").execute();
+
+        for (Iterator iter = entries.iterator(); iter.hasNext();) {
+            WeblogEntryData entry = (WeblogEntryData) iter.next();
+
+            this.strategy.remove(entry);
+        }
+
+        // remove associated referers
+        List referers = (List)strategy.newQuery(RefererData.class,
+                "RefererData.getByWebsite").execute();
+        for (Iterator iter = referers.iterator(); iter.hasNext();) {
+            RefererData referer = (RefererData) iter.next();
+            this.strategy.remove(referer);
+        }
+
+        // remove associated pages
+        List pages = (List)strategy.newQuery(WeblogTemplate.class,
+                "WeblogTemplate.getByWebsite").execute();
+
+        for (Iterator iter = pages.iterator(); iter.hasNext();) {
+            WeblogTemplate page = (WeblogTemplate) iter.next();
+            this.strategy.remove(page);
+        }
+
+        // remove folders (including bookmarks)
+        FolderData rootFolder = bmgr.getRootFolder(website);
+        if (null != rootFolder) {
+            this.strategy.remove(rootFolder);
+
+            // Still cannot get all Bookmarks cleared!
+//            Iterator allFolders = bmgr.getAllFolders(website).iterator();
+//            while (allFolders.hasNext()) {
+//                FolderData aFolder = (FolderData)allFolders.next();
+//                bmgr.removeFolderContents(aFolder);
+//                this.strategy.remove(aFolder);
+//            }
+        }
+
+        // remove categories
+        WeblogCategoryData rootCat = wmgr.getRootWeblogCategory(website);
+        if (null != rootCat) {
+            this.strategy.remove(rootCat);
+        }
+
     }
 
-    /**
-     * Returns users whose usernames or email addresses start with a string.
-     * @param startsWith String to match userNames and emailAddresses against
-     * @param offset Offset into results (for paging)
-     * @param length Max to return (for paging)
-     * @param enabled True for only enalbed, false for disabled, null for all
-     * @return List of (up to length) users that match startsWith string
-     */
-    public List getUsersStartingWith(String startsWith, Boolean enabled,
-            int offset, int length) throws RollerException {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    public void saveUser(UserData data) throws RollerException {
+        this.strategy.store(data);
     }
 
-    /**
-     * Get map with 26 entries, one for each letter A-Z and containing integers
-     * reflecting the number of users whose names start with each letter.
-     */
-    public Map getUserNameLetterMap() throws RollerException {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    public void removeUser(UserData user) throws RollerException {
+        this.strategy.remove(user);
+
+        // remove entry from cache mapping
+        this.userNameToIdMap.remove(user.getUserName());
     }
 
-    /**
-     * Get collection of users whose names begin with specified letter
-     */
-    public List getUsersByLetter(char letter, int offset, int length)
-            throws RollerException {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    public void savePermissions(PermissionsData perms) throws RollerException {
+        this.strategy.store(perms);
     }
 
-    /**
-     * Get map with 26 entries, one for each letter A-Z and containing integers
-     * reflecting the number of weblogs whose names start with each letter.
-     */
-    public Map getWeblogHandleLetterMap() throws RollerException {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    public void removePermissions(PermissionsData perms) throws RollerException {
+        this.strategy.remove(perms);
     }
 
     /**
-     * Get collection of weblogs whose handles begin with specified letter
+     * @see org.apache.roller.business.UserManager#savePage(org.apache.roller.pojos.WeblogTemplate)
      */
-    public List getWeblogsByLetter(char letter, int offset, int length)
-            throws RollerException {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    public void savePage(WeblogTemplate page) throws RollerException {
+        this.strategy.store(page);
+
+        // update weblog last modified date.  date updated by saveWebsite()
+        RollerFactory.getRoller().getUserManager().saveWebsite(page.getWebsite());
     }
 
-    public UserData getUserByUsername(String userName) 
-            throws RollerException {
-        return getUserByUsername(userName, Boolean.TRUE);
+    public void removePage(WeblogTemplate page) throws RollerException {
+        this.strategy.remove(page);
     }
 
-    public UserData getUserByUsername(String userName, Boolean enabled) 
-            throws RollerException {
-        if (userName==null )
-            throw new RollerException("userName cannot be null");
-        if (enabled == null) {
-            return (UserData)strategy.newQuery(UserData.class,
-                    "getUniqueByName")
-                .execute(userName);
-        } else {
-            return (UserData)strategy.newQuery(UserData.class,
-                    "getUniqueByName&&Enabled")
-                .execute(new Object[]{userName, enabled});
+    public void addUser(UserData newUser) throws RollerException {
+
+        if(newUser == null)
+            throw new RollerException("cannot add null user");
+
+        // TODO BACKEND: we must do this in a better fashion, like getUserCnt()?
+        boolean adminUser = false;
+        List existingUsers = this.getUsers(0, 1);
+        if(existingUsers.size() == 0) {
+            // Make first user an admin
+            adminUser = true;
         }
-    }
 
-    public List getUsers() 
-            throws RollerException {
-        return getUsers(Boolean.TRUE);
-    }
+        if(getUserByUserName(newUser.getUserName()) != null ||
+                getUserByUserName(newUser.getUserName().toLowerCase()) != null) {
+            throw new RollerException("error.add.user.userNameInUse");
+        }
 
-    public List getUsers(Boolean enabled) 
-            throws RollerException {
-        if (enabled == null) {
-            return (List)strategy.newQuery(UserData.class,
-                    "all")
-                .execute();
-        } else {
-            return (List)strategy.newQuery(UserData.class,
-                    "getByEnabled")
-                .execute(enabled);
+        newUser.grantRole("editor");
+        if(adminUser) {
+            newUser.grantRole("admin");
         }
-    }
 
-    public List getUsers(WebsiteData website, Boolean enabled) 
-            throws RollerException {
-        return (List)strategy.newQuery(UserData.class,
-                "getByWebsite&&Enabled")
-            .execute(new Object[]{website, enabled});
+        this.strategy.store(newUser);
     }
 
-    public List getUsersStartingWith
-            (String startsWith, int offset, int length, Boolean enabled) 
-            throws RollerException {
-        return (List)strategy.newQuery(UserData.class,
-                "getByEnabled&&UserNameStartsWith||EmailStartsWith.range")
-            .setRange(offset, offset+length)
-            .execute(new Object[]{enabled, startsWith});
+    public void addWebsite(WebsiteData newWeblog) throws RollerException {
+
+        this.strategy.store(newWeblog);
+        this.addWeblogContents(newWeblog);
     }
 
-    public void addWebsite(WebsiteData newWebsite) 
-            throws RollerException {
-        strategy.store(newWebsite);
-        
+    private void addWeblogContents(WebsiteData newWeblog) throws RollerException {
+
         // grant weblog creator ADMIN permissions
         PermissionsData perms = new PermissionsData();
-        perms.setUser(newWebsite.getCreator());
-        perms.setWebsite(newWebsite);
+        perms.setUser(newWeblog.getCreator());
+        perms.setWebsite(newWeblog);
         perms.setPending(false);
         perms.setPermissionMask(PermissionsData.ADMIN);
-        strategy.store(perms);
-        
+        this.strategy.store(perms);
+
         // add default categories
         WeblogCategoryData rootCat = new WeblogCategoryData(
-                null,      // id
-                newWebsite, // newWeblog
+                newWeblog, // newWeblog
                 null,      // parent
                 "root",    // name
                 "root",    // description
                 null );    // image
-        strategy.store(rootCat);
-        
-        String cats = getProperty("newuser.categories");
-        WeblogCategoryData firstCat = rootCat; 
+        this.strategy.store(rootCat);
+
+        String cats = RollerConfig.getProperty("newuser.categories");
+        WeblogCategoryData firstCat = rootCat;
         if (cats != null) {
             String[] splitcats = cats.split(",");
-            for (int i = 0; i < splitcats.length; i++) {
+            for (int i=0; i<splitcats.length; i++) {
                 WeblogCategoryData c = new WeblogCategoryData(
-                    null,            // id
-                    newWebsite,      // newWebsite
-                    rootCat,         // parent
-                    splitcats[i],    // name
-                    splitcats[i],    // description
-                    null );          // image
+                        newWeblog,       // newWeblog
+                        rootCat,         // parent
+                        splitcats[i],    // name
+                        splitcats[i],    // description
+                        null );          // image
                 if (i == 0) firstCat = c;
-                strategy.store(c);
+                this.strategy.store(c);
             }
         }
         // Use first category as default for Blogger API
-        newWebsite.setBloggerCategory(firstCat);
-        
+        newWeblog.setBloggerCategory(firstCat);
+
         // But default category for weblog itself should be  root
-        newWebsite.setDefaultCategory(rootCat);
+        newWeblog.setDefaultCategory(rootCat);
+
+        this.strategy.store(newWeblog);
 
-        strategy.store(newWebsite);
-        
         // add default bookmarks
-        FolderData root = new FolderData(null, "root", "root", newWebsite);
-        strategy.store(root);
-        
+        FolderData root = new FolderData(
+                null, "root", "root", newWeblog);
+        this.strategy.store(root);
+
         Integer zero = new Integer(0);
-        String blogroll = getProperty("newuser.blogroll");
+        String blogroll = RollerConfig.getProperty("newuser.blogroll");
         if (blogroll != null) {
             String[] splitroll = blogroll.split(",");
-            for (int i = 0; i < splitroll.length; i++) {
+            for (int i=0; i<splitroll.length; i++) {
                 String[] rollitems = splitroll[i].split("\\|");
                 if (rollitems != null && rollitems.length > 1) {
-                    strategy.store(new BookmarkData(
-                        root,                // parent
-                        rollitems[0],        // name
-                        "",                  // description
-                        rollitems[1].trim(), // url
-                        null,                // feedurl
-                        zero,                // weight
-                        zero,                // priority
-                        null));              // image
+                    BookmarkData b = new BookmarkData(
+                            root,                // parent
+                            rollitems[0],        // name
+                            "",                  // description
+                            rollitems[1].trim(), // url
+                            null,                // feedurl
+                            zero,                // weight
+                            zero,                // priority
+                            null);               // image
+                    this.strategy.store(b);
                 }
             }
         }
-        
+
         // add any auto enabled ping targets
-        Collection pingTargets = (Collection)strategy.newQuery(
-                PingTargetData.class,
-                "getByWebsiteNull&&AutoPingTrue")
-            .execute();
-        Iterator pingTargetIterator = pingTargets.iterator();
+        PingTargetManager pingTargetMgr = RollerFactory.getRoller().getPingTargetManager();
+        AutoPingManager autoPingMgr = RollerFactory.getRoller().getAutopingManager();
+
+        Iterator pingTargets = pingTargetMgr.getCommonPingTargets().iterator();
         PingTargetData pingTarget = null;
-        while(pingTargetIterator.hasNext()) {
-             pingTarget = (PingTargetData)pingTargetIterator.next();
-            strategy.store(new AutoPingData(null, pingTarget, newWebsite));
+        while(pingTargets.hasNext()) {
+            pingTarget = (PingTargetData) pingTargets.next();
+
+            if(pingTarget.isAutoEnabled()) {
+                AutoPingData autoPing = new AutoPingData(null, pingTarget, newWeblog);
+                autoPingMgr.saveAutoPing(autoPing);
+            }
         }
     }
 
-    public void saveWebsite(WebsiteData data) 
-            throws RollerException {
-        strategy.store(data);
+    /**
+     * Creates and stores a pending PermissionsData for user and website specified.
+     * TODO BACKEND: do we really need this?  can't we just use storePermissions()?
+     */
+    public PermissionsData inviteUser(WebsiteData website,
+            UserData user, short mask) throws RollerException {
+
+        if (website == null) throw new RollerException("Website cannot be null");
+        if (user == null) throw new RollerException("User cannot be null");
+
+        PermissionsData perms = new PermissionsData();
+        perms.setWebsite(website);
+        perms.setUser(user);
+        perms.setPermissionMask(mask);
+        this.strategy.store(perms);
+
+        return perms;
     }
 
-    public void removeWebsite(WebsiteData website) 
-            throws RollerException {
+    /**
+     * Remove user permissions from a website.
+     *
+     * TODO: replace this with a domain model method like weblog.retireUser(user)
+     */
+    public void retireUser(WebsiteData website, UserData user) throws RollerException {
+
+        if (website == null) throw new RollerException("Website cannot be null");
+        if (user == null) throw new RollerException("User cannot be null");
+
+        Iterator perms = website.getPermissions().iterator();
+        PermissionsData target = null;
+        while (perms.hasNext()) {
+            PermissionsData pd = (PermissionsData)perms.next();
+            if (pd.getUser().getId().equals(user.getId())) {
+                target = pd;
+                break;
+            }
+        }
+        if (target == null) throw new RollerException("User not member of website");
 
-        // Remove the website's ping queue entries
-        strategy.newQuery(PingQueueEntryData.class,
-                "getByWebsite")
-            .execute(website);
-        
-        // Remove the website's auto ping configurations
-        strategy.newQuery(AutoPingData.class,
-                "getByWebsite")
-            .execute(website);
+        website.removePermission(target);
+        this.strategy.remove(target);
+    }
+
+    public WebsiteData getWebsite(String id) throws RollerException {
+        return (WebsiteData) this.strategy.load(WebsiteData.class, id);
+    }
+
+    public WebsiteData getWebsiteByHandle(String handle) throws RollerException {
+        return getWebsiteByHandle(handle, Boolean.TRUE);
+    }
+
+    /**
+     * Return website specified by handle.
+     */
+    public WebsiteData getWebsiteByHandle(String handle, Boolean enabled)
+    throws RollerException {
+
+        if (handle==null )
+            throw new RollerException("Handle cannot be null");
+
+        // check cache first
+        // NOTE: if we ever allow changing handles then this needs updating
+        if(this.weblogHandleToIdMap.containsKey(handle)) {
+
+            WebsiteData weblog = this.getWebsite((String) this.weblogHandleToIdMap.get(handle));
+            if(weblog != null) {
+                // only return weblog if enabled status matches
+                if(enabled == null || enabled.equals(weblog.getEnabled())) {
+                    log.debug("weblogHandleToId CACHE HIT - "+handle);
+                    return weblog;
+                }
+            } else {
+                // mapping hit with lookup miss?  mapping must be old, remove it
+                this.weblogHandleToIdMap.remove(handle);
+            }
+        }
+
+        // cache failed, do lookup
+        DatamapperQuery query;
+        Object[] params;
+        if (enabled != null) {
+            query = strategy.newQuery(WebsiteData.class,"WebsiteData.getByHandle&enabled");
+            params = new Object[] {handle, enabled};
+        } else {
+            query = strategy.newQuery(WebsiteData.class,"WebsiteData.getByHandle");
+            params = new Object[] {handle};
+        }
+        query.setUnique();
+        WebsiteData website = (WebsiteData) query.execute(params);
+
+        // add mapping to cache
+        if(website != null) {
+            log.debug("weblogHandleToId CACHE MISS - "+handle);
+            this.weblogHandleToIdMap.put(website.getHandle(), website.getId());
+        }
+
+        return website;
+    }
+
+    /**
+     * Get websites of a user
+     */
+    public List getWebsites(
+        UserData user, Boolean enabled, Boolean active,
+        Date startDate, Date endDate, int offset, int length) throws RollerException {
         
-        // Remove the website's custom ping targets
-        strategy.newQuery(PingTargetData.class,
-                "getByWebsite")
-            .execute(website);
+        DatamapperQuery query = null;
+        List results = null;
+        boolean setRange = offset != 0 || length != -1;
         
-        // Remove the website's weblog entries
-        strategy.newQuery(WeblogEntryData.class,
-                "getByWebsite")
-            .execute(website);
+        // TODO: ATLAS getWebsites DONE TESTED
+        if (endDate == null) endDate = new Date();
+
+        if (length == -1) {
+            length = Integer.MAX_VALUE - offset;
+        }
         
-        // Remove the website's associated referrers
-        strategy.newQuery(RefererData.class,
-                "getByWebsite")
-            .execute(website);
-                
-        // Remove the website's associated templates
-        strategy.newQuery(WeblogTemplate.class,
-                "getByWebsite")
-            .execute(website);
-
-        // Remove all the website's bookmarks in all folders
-        strategy.newQuery(BookmarkData.class,
-                "getByFolderByWebsite")
-            .execute(website);
+        if (startDate != null) {
+           if (enabled != null) {
+               if (active != null) {
+                  if (user != null) {
+                      query = strategy.newQuery(UserData.class, "WebsiteData.getByEndDate&StartDate&Enabled&Active&Permissions.user&Permissions.pendingOrderByDateCreatedDesc");
+                      if (setRange) query.setRange(offset, offset + length);
+                      results = (List) query.execute(new Object[] {endDate, startDate, enabled, active, user, Boolean.FALSE});                
+                  } else {
+                      query = strategy.newQuery(UserData.class, "WebsiteData.getByEndDate&StartDate&Enabled&ActiveOrderByDateCreatedDesc");
+                      if (setRange) query.setRange(offset, offset + length);
+                      results = (List) query.execute(new Object[] {endDate, startDate, enabled, active});                                      
+                  }
+               } else {
+                   if (user != null) {
+                       query = strategy.newQuery(UserData.class, "WebsiteData.getByEndDate&StartDate&Enabled&Permissions.user&Permissions.pendingOrderByDateCreatedDesc");
+                       if (setRange) query.setRange(offset, offset + length);
+                       results = (List) query.execute(new Object[] {endDate, startDate, enabled, user, Boolean.FALSE});                
+                   } else {
+                       query = strategy.newQuery(UserData.class, "WebsiteData.getByEndDate&StartDate&EnabledOrderByDateCreatedDesc");
+                       if (setRange) query.setRange(offset, offset + length);
+                       results = (List) query.execute(new Object[] {endDate, startDate, enabled});                
+                   }
+               }
+           } else {
+               if (active != null) {
+                   if (user != null) {
+                       query = strategy.newQuery(UserData.class, "WebsiteData.getByEndDate&StartDate&Active&Permissions.user&Permissions.pendingOrderByDateCreatedDesc");
+                       if (setRange) query.setRange(offset, offset + length);
+                       results = (List) query.execute(new Object[] {endDate, startDate, active, user, Boolean.FALSE});                
+                   } else {
+                       query = strategy.newQuery(UserData.class, "WebsiteData.getByEndDate&StartDate&ActiveOrderByDateCreatedDesc");
+                       if (setRange) query.setRange(offset, offset + length);
+                       results = (List) query.execute(new Object[] {endDate, startDate, active});                
+                   }
+               } else {
+                   if (user != null) {
+                       query = strategy.newQuery(UserData.class, "WebsiteData.getByEndDate&StartDate&Permissions.user&Permissions.pendingOrderByDateCreatedDesc");
+                       if (setRange) query.setRange(offset, offset + length);
+                       results = (List) query.execute(new Object[] {endDate, startDate, user, Boolean.FALSE});                
+                   } else {
+                       query = strategy.newQuery(UserData.class, "WebsiteData.getByEndDate&StartDateOrderByDateCreatedDesc");
+                       if (setRange) query.setRange(offset, offset + length);
+                       results = (List) query.execute(new Object[] {endDate, startDate});                
+                   }
+               }
+           }
+        } else {
+            if (enabled != null) {
+                if (active != null) {
+                   if (user != null) {
+                       query = strategy.newQuery(UserData.class, "WebsiteData.getByEndDate&Enabled&Active&Permissions.user&Permissions.pendingOrderByDateCreatedDesc");
+                       if (setRange) query.setRange(offset, offset + length);
+                       results = (List) query.execute(new Object[] {endDate, enabled, active, user, Boolean.FALSE});                
+                   } else {
+                       query = strategy.newQuery(UserData.class, "WebsiteData.getByEndDate&Enabled&ActiveOrderByDateCreatedDesc");
+                       if (setRange) query.setRange(offset, offset + length);
+                       results = (List) query.execute(new Object[] {endDate, enabled, active});                                      
+                   }
+                } else {
+                    if (user != null) {
+                        query = strategy.newQuery(UserData.class, "WebsiteData.getByEndDate&Enabled&Permissions.user&Permissions.pendingOrderByDateCreatedDesc");
+                        if (setRange) query.setRange(offset, offset + length);
+                        results = (List) query.execute(new Object[] {endDate, enabled, user, Boolean.FALSE});                
+                    } else {
+                        query = strategy.newQuery(UserData.class, "WebsiteData.getByEndDate&EnabledOrderByDateCreatedDesc");
+                        if (setRange) query.setRange(offset, offset + length);
+                        results = (List) query.execute(new Object[] {endDate, enabled});                
+                    }
+                }
+            } else {
+                if (active != null) {
+                    if (user != null) {
+                        query = strategy.newQuery(UserData.class, "WebsiteData.getByEndDate&Active&Permissions.user&Permissions.pendingOrderByDateCreatedDesc");
+                        if (setRange) query.setRange(offset, offset + length);
+                        results = (List) query.execute(new Object[] {endDate, active, user, Boolean.FALSE});                
+                    } else {
+                        query = strategy.newQuery(UserData.class, "WebsiteData.getByEndDate&ActiveOrderByDateCreatedDesc");
+                        if (setRange) query.setRange(offset, offset + length);
+                        results = (List) query.execute(new Object[] {endDate, active});                
+                    }
+                } else {
+                    if (user != null) {
+                        query = strategy.newQuery(UserData.class, "WebsiteData.getByEndDate&Permissions.user&Permissions.pendingOrderByDateCreatedDesc");
+                        if (setRange) query.setRange(offset, offset + length);
+                        results = (List) query.execute(new Object[] {endDate, user, Boolean.FALSE});                
+                    } else {
+                        query = strategy.newQuery(UserData.class, "WebsiteData.getByEndDateOrderByDateCreatedDesc");
+                        if (setRange) query.setRange(offset, offset + length);
+                        results = (List) query.execute(endDate);                
+                    }
+                }
+            }
+        }        
         
-        // Remove all the website's folders
-        strategy.newQuery(FolderData.class,
-                "getByWebsite")
-            .execute(website);
-                
-        // Remove the website's categories
-        strategy.newQuery(WeblogCategoryData.class,
-                "getByWebsite")
-            .execute(website);
+        return results;
+    }
 
-        // Finally, remove the website
-        strategy.remove(website);
+    public UserData getUser(String id) throws RollerException {
+        return (UserData)this.strategy.load(UserData.class, id);
     }
 
-    public WebsiteData getWebsite(String id) 
-            throws RollerException {
-        return (WebsiteData)strategy.load(WebsiteData.class, id);
+    public UserData getUserByUserName(String userName) throws RollerException {
+        return getUserByUserName(userName, Boolean.TRUE);
     }
 
-    public WebsiteData getWebsiteByHandle(String handle) 
-            throws RollerException {
-        return getWebsiteByHandle(handle, Boolean.TRUE);
+    public UserData getUserByUserName(String userName, Boolean enabled)
+    throws RollerException {
+
+        if (userName==null )
+            throw new RollerException("userName cannot be null");
+
+        // check cache first
+        // NOTE: if we ever allow changing usernames then this needs updating
+        if(this.userNameToIdMap.containsKey(userName)) {
+
+            UserData user = this.getUser((String) this.userNameToIdMap.get(userName));
+            if(user != null) {
+                // only return the user if the enabled status matches
+                if(enabled == null || enabled.equals(user.getEnabled())) {
+                    log.debug("userNameToIdMap CACHE HIT - "+userName);
+                    return user;
+                }
+            } else {
+                // mapping hit with lookup miss?  mapping must be old, remove it
+                this.userNameToIdMap.remove(userName);
+            }
+        }
+
+        // cache failed, do lookup
+        DatamapperQuery query;
+        Object[] params;
+        if (enabled != null) {
+            query = strategy.newQuery(UserData.class,"UserData.getByUserName&enabled");
+            params = new Object[] {userName, enabled};
+        } else {
+            query = strategy.newQuery(WebsiteData.class,"UserData.getByUserName");
+            params = new Object[] {userName};
+        }
+        query.setUnique();
+        UserData user = (UserData) query.execute(params);
+
+        // add mapping to cache
+        if(user != null) {
+            log.debug("userNameToIdMap CACHE MISS - "+userName);
+            this.userNameToIdMap.put(user.getUserName(), user.getId());
+        }
+
+        return user;
     }
 
-    public WebsiteData getWebsiteByHandle(String handle, Boolean enabled) 
+    public List getUsers(WebsiteData weblog, Boolean enabled, Date startDate, 
+                         Date endDate, int offset, int length) 
             throws RollerException {
-        // XXX cache websites by handle?
-        return (WebsiteData)strategy.newQuery(WebsiteData.class,
-                "getByHandle&&Enabled")
-            .execute(new Object[]{handle, enabled});
+        DatamapperQuery query = null;
+        List results = null;
+        boolean setRange = offset != 0 || length != -1;
+
+        if (length == -1) {
+            length = Integer.MAX_VALUE - offset;
+        }
+        
+        // if we are doing date range then we must have an end date
+        if (startDate != null && endDate == null) {
+            endDate = new Date();
+        }
+        
+        if (weblog != null) {
+            if (enabled != null) {
+                if (startDate != null) {
+                    query = strategy.newQuery(UserData.class, "UserData.getByPermissions.website&Enabled&EndDate&StartDate");
+                    if (setRange) query.setRange(offset, offset + length);
+                    results = (List) query.execute(new Object[] {weblog, enabled, endDate, startDate});
+                } else {
+                    query = strategy.newQuery(UserData.class, "UserData.getByEnabled&Permissions.website");
+                    if (setRange) query.setRange(offset, offset + length);
+                    results = (List) query.execute(new Object[] {enabled, weblog});
+                }
+            } else {
+                if (startDate != null) {
+                    query = strategy.newQuery(UserData.class, "UserData.getByPermissions.website&EndDate&StartDate");
+                    if (setRange) query.setRange(offset, offset + length);
+                    results = (List) query.execute(new Object[] {weblog, endDate, startDate});
+                } else {
+                    query = strategy.newQuery(UserData.class, "UserData.getByPermissions.website");
+                    if (setRange) query.setRange(offset, offset + length);
+                    results = (List) query.execute(weblog);
+                }
+            }
+        } else {
+            if (enabled != null) {
+                if (startDate != null) {
+                    query = strategy.newQuery(UserData.class, "UserData.getByEnabled&EndDate&StartDate");
+                    if (setRange) query.setRange(offset, offset + length);
+                    results = (List) query.execute(new Object[] {enabled, endDate, startDate});
+                } else {
+                    query = strategy.newQuery(UserData.class, "UserData.getByEnabled");
+                    if (setRange) query.setRange(offset, offset + length);
+                    results = (List) query.execute(new Object[] {enabled});
+                }
+            } else {
+                if (startDate != null) {
+                    query = strategy.newQuery(UserData.class, "UserData.getByPermissions.website&EndDate&StartDate");
+                    if (setRange) query.setRange(offset, offset + length);
+                    results = (List) query.execute(new Object[] {endDate, startDate});
+                } else {
+                    query = strategy.newQuery(UserData.class, "UserData.getAll");
+                    if (setRange) query.setRange(offset, offset + length);
+                    results = (List) query.execute();
+                }
+            }
+        }
+        
+        return results;
     }
 
-    public List getWebsites(UserData user, Boolean enabled, Boolean active) 
-            throws RollerException {
-        return (List)strategy.newQuery(WebsiteData.class,
-                "getByPermissionsContainsUser&&Enabled&&Active")
-            .execute(new Object[]{user, enabled, active});
+    public List getUsers(int offset, int length) throws RollerException {
+        return getUsers(Boolean.TRUE, null, null, offset, length);
+    }
+
+    public List getUsers(Boolean enabled, Date startDate, Date endDate, int offset, int length) throws RollerException {
+        DatamapperQuery query = null;
+        List results = null;
+        boolean setRange = offset != 0 || length != -1;
+
+        if (endDate == null) endDate = new Date();
+
+        if (length == -1) {
+            length = Integer.MAX_VALUE - offset;
+        }
+
+        if (enabled != null) {
+              if (startDate != null) {
+                  query = strategy.newQuery(UserData.class, "UserData.getByEnabled&EndDate&StartDateOrderByStartDateDesc");
+                  if (setRange) query.setRange(offset, offset + length);
+                  results = (List) query.execute(new Object[] {enabled, endDate, startDate});                
+              } else {
+                  query = strategy.newQuery(UserData.class, "UserData.getByEnabled&EndDateOrderByStartDateDesc");
+                  if (setRange) query.setRange(offset, offset + length);
+                  results = (List) query.execute(new Object[] {enabled, endDate});                
+              }
+        } else {
+            if (startDate != null) {
+                query = strategy.newQuery(UserData.class, "UserData.getByEndDate&StartDateOrderByStartDateDesc");
+                if (setRange) query.setRange(offset, offset + length);
+                results = (List) query.execute(new Object[] {endDate, startDate});                
+            } else {
+                query = strategy.newQuery(UserData.class, "UserData.getByEndDateOrderByStartDateDesc");
+                if (setRange) query.setRange(offset, offset + length);
+                results = (List) query.execute(endDate);                
+            }
+        }
+
+        return results;
     }
 
     /**
-     * Get websites optionally restricted by user, enabled and active status.
-     * @param user    Get all websites for this user (or null for all)
-     * @param offset  Offset into results (for paging)
-     * @param len     Maximum number of results to return (for paging)
-     * @param enabled Get all with this enabled state (or null or all)
-     * @param active  Get all with this active state (or null or all)
-     * @param startDate Restrict to those created after (or null for all)
-     * @param endDate Restrict to those created before (or null for all)
-     * @returns List of WebsiteData objects.
+     * Get users of a website
      */
-    public List getWebsites(
-            UserData user, 
-            Boolean  enabled, 
-            Boolean  active, 
-            Date     startDate, 
-            Date     endDate, 
-            int      offset, 
-            int      length) 
-            throws RollerException {
-        return null;
+    public List getUsers(WebsiteData website, Boolean enabled, int offset, int length) throws RollerException {
+        DatamapperQuery query = null;
+        List results = null;
+        boolean setRange = offset != 0 || length != -1;
+
+        if (length == -1) {
+            length = Integer.MAX_VALUE - offset;
+        }
+
+        if (enabled != null) {
+            if (website != null) {
+                query = strategy.newQuery(UserData.class, "UserData.getByEnabled&Permissions.website");
+                if (setRange) query.setRange(offset, offset + length);
+                results = (List) query.execute(new Object[] {enabled, website});                
+            } else {
+                query = strategy.newQuery(UserData.class, "UserData.getByEnabled");
+                if (setRange) query.setRange(offset, offset + length);
+                results = (List) query.execute(enabled);                
+            }
+        } else {
+            if (website != null) {
+                query = strategy.newQuery(UserData.class, "UserData.getByPermissions.website");
+                if (setRange) query.setRange(offset, offset + length);
+                results = (List) query.execute(website);                
+            } else {
+                query = strategy.newQuery(UserData.class, "UserData.getAll");
+                if (setRange) query.setRange(offset, offset + length);
+                results = (List) query.execute();                
+            }
+        }
+        return results;
     }
-    
-    /**
-     * Get websites ordered by descending number of comments.
-     * @param startDate Restrict to those created after (or null for all)
-     * @param endDate Restrict to those created before (or null for all)
-     * @param offset    Offset into results (for paging)
-     * @param len       Maximum number of results to return (for paging)
-     * @return List of WebsiteData objects.
-     */
-    public List getMostCommentedWebsites(
-            Date startDate, 
-            Date endDate, 
-            int  offset, 
-            int  length) 
-            throws RollerException {
-        return null;
+
+    public List getUsersStartingWith(String startsWith, Boolean enabled,
+            int offset, int length) throws RollerException {
+        DatamapperQuery query = null;
+        List results = null;
+        boolean setRange = offset != 0 || length != -1;
+
+        if (length == -1) {
+            length = Integer.MAX_VALUE - offset;
+        }
+
+        if (enabled != null) {
+            if (startsWith != null) {
+                query = strategy.newQuery(UserData.class, "UserData.getByEnabled&UserNameOrEmailAddressStartsWith");
+                if (setRange) query.setRange(offset, offset + length);
+                results = (List) query.execute(new Object[] {enabled, startsWith});
+            } else {
+                query = strategy.newQuery(UserData.class, "UserData.getByEnabled");
+                if (setRange) query.setRange(offset, offset + length);
+                results = (List) query.execute(enabled);                
+            }
+        } else { 
+            if (startsWith != null) {
+                query = strategy.newQuery(UserData.class, "UserData.getByUserNameOrEmailAddressStartsWith");
+                if (setRange) query.setRange(offset, offset + length);
+                results = (List) query.execute(startsWith);
+            } else {
+                query = strategy.newQuery(UserData.class, "UserData.getAll");
+                if (setRange) query.setRange(offset, offset + length);
+                results = (List) query.execute();                
+            }
+        }
+        return results;
     }
-    
-    public void savePermissions(PermissionsData perms) 
-            throws RollerException {
-        strategy.store(perms);
+
+    public WeblogTemplate getPage(String id) throws RollerException {
+        // Don't hit database for templates stored on disk
+        if (id != null && id.endsWith(".vm")) return null;
+
+        return (WeblogTemplate)this.strategy.load(WeblogTemplate.class,id);
     }
 
-    public void removePermissions(PermissionsData perms) 
+    /**
+     * Use Datamapper directly because Roller's Query API does too much allocation.
+     */
+    public WeblogTemplate getPageByLink(WebsiteData website, String pagelink)
             throws RollerException {
-        strategy.remove(perms);
+
+        if (website == null)
+            throw new RollerException("userName is null");
+
+        if (pagelink == null)
+            throw new RollerException("Pagelink is null");
+
+        DatamapperQuery query = strategy.newQuery(
+                WeblogTemplate.class, "WeblogTemplate.getByWebsite&Link");
+        query.setRange(1, 2);  // => query.setFirstResult(1).setMaxResult(1)
+        List list = (List)query.execute(new Object[] {website, pagelink});
+        return list.size()!=0 ? (WeblogTemplate)list.get(0) : null;
     }
 
-    public PermissionsData getPermissions(String id) 
+    /**
+     * @see org.apache.roller.business.UserManager#getPageByName(WebsiteData, java.lang.String)
+     */
+    public WeblogTemplate getPageByName(WebsiteData website, String pagename)
             throws RollerException {
-        return (PermissionsData)strategy.load(PermissionsData.class, id);
+
+        if (website == null)
+            throw new RollerException("website is null");
+
+        if (pagename == null)
+            throw new RollerException("Page name is null");
+
+        DatamapperQuery query = strategy.newQuery(
+                WeblogTemplate.class, "WeblogTemplate.getByWebsite&Name");
+        query.setRange(1, 2);  // => query.setFirstResult(1).setMaxResult(1)
+        List list = (List)query.execute(new Object[] {website, pagename}); 
+        return list.size()!=0? (WeblogTemplate)list.get(0) : null;
     }
 
-    public List getPendingPermissions(UserData user) 
-            throws RollerException {
-        return (List)strategy.newQuery(PermissionsData.class,
-                "getByUser&&Pending")
-            .execute(user);
+    /**
+     * @see org.apache.roller.business.UserManager#getPages(WebsiteData)
+     */
+    public List getPages(WebsiteData website) throws RollerException {
+        if (website == null)
+            throw new RollerException("website is null");
+        return (List) strategy.newQuery(WeblogTemplate.class,
+                "WeblogTemplate.getByWebsiteOrderByName").execute(website);
     }
 
-    public List getPendingPermissions(WebsiteData website) 
-            throws RollerException {
-        return (List)strategy.newQuery(PermissionsData.class,
-                "getByWebsite&&Pending")
-            .execute(website);
+    public PermissionsData getPermissions(String inviteId) throws RollerException {
+        return (PermissionsData)this.strategy.load(PermissionsData.class, inviteId);
     }
 
-    public PermissionsData getPermissions(WebsiteData website, UserData user) 
-            throws RollerException {
-        return (PermissionsData)strategy.newQuery(PermissionsData.class,
-                "getUniqueByWebsite&&User")
-            .execute(new Object[]{website, user});
+    /**
+     * Return permissions for specified user in website
+     */
+    public PermissionsData getPermissions(
+            WebsiteData website, UserData user) throws RollerException {
+        List list = (List) strategy.newQuery(PermissionsData.class, "PermissionsData.getByWebsiteAndUser").
+                execute(new Object[] {website, user} );
+        return list.size()!=0 ? (PermissionsData)list.get(0) : null;
     }
 
-    public List getAllPermissions(WebsiteData website) 
-            throws RollerException {
-        return (List)strategy.newQuery(PermissionsData.class,
-                "getByWebsite&&NotPending")
-            .execute(website);
+    /**
+     * Get pending permissions for user
+     */
+    public List getPendingPermissions(UserData user) throws RollerException {
+        return (List) strategy.newQuery(PermissionsData.class, "PermissionsData.getByUserAndPending").
+                execute(new Object[] {user, Boolean.TRUE} );
     }
 
-    public List getAllPermissions(UserData user) 
-            throws RollerException {
-        return (List)strategy.newQuery(PermissionsData.class,
-                "getByUser&&NotPending")
-            .execute(user);
+    /**
+     * Get pending permissions for website
+     */
+    public List getPendingPermissions(WebsiteData website) throws RollerException {
+        return (List) strategy.newQuery(PermissionsData.class, "PermissionsData.getByWebsiteAndPending").
+                execute(new Object[] {website, Boolean.TRUE} );
     }
 
-    public PermissionsData inviteUser
-            (WebsiteData website, UserData user, short mask) 
-            throws RollerException {
-        if (website == null) 
-            throw new RollerException("inviteUser: Website cannot be null");
-        if (user == null) 
-            throw new RollerException("inviteUser: User cannot be null");
+    /**
+     * Get all permissions of a website (pendings not including)
+     */
+    public List getAllPermissions(WebsiteData website) throws RollerException {
+        return (List) strategy.newQuery(PermissionsData.class, "PermissionsData.getByWebsiteAndPending").
+                execute(new Object[] {website, Boolean.FALSE} );
 
-        PermissionsData perms = new PermissionsData();
-        perms.setWebsite(website);
-        perms.setUser(user);
-        perms.setPermissionMask(mask);
-        strategy.store(perms);
-        
-        return perms;
     }
 
-    public void retireUser(WebsiteData website, UserData user) 
-            throws RollerException {
-        if (website == null) 
-            throw new RollerException("retireUser: Website cannot be null");
-        if (user == null) 
-            throw new RollerException("retireUser: User cannot be null");
+    /**
+     * Get all permissions of a user.
+     */
+    public List getAllPermissions(UserData user) throws RollerException {
+        return (List) strategy.newQuery(PermissionsData.class, "PermissionsData.getByUserAndPending").
+                execute(new Object[] {user, Boolean.FALSE} );
 
-        strategy.newQuery(PermissionsData.class,
-                "getByWebsite&&UserId")
-            .execute(new Object[]{website, user});
     }
 
-    public void savePage(WeblogTemplate data) 
-            throws RollerException {
-        strategy.store(data);
-        saveWebsite(data.getWebsite());
-    }
+    public void release() {}
 
-    public void removePage(WeblogTemplate page) 
-            throws RollerException {
-        strategy.remove(page);
+    public Map getUserNameLetterMap() throws RollerException {
+        // TODO: ATLAS getUserNameLetterMap DONE TESTED
+        String lc = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+        Map results = new TreeMap();
+        DatamapperQuery query = strategy.newQuery(UserData.class, "UserData.getCountByUserNameLike");
+        for (int i=0; i<26; i++) {
+            char currentChar = lc.charAt(i);
+            List row = (List) query.execute(currentChar + "%");
+            Integer count = (Integer) row.get(0);
+            results.put(String.valueOf(currentChar), count);
+        }
+        return results;
     }
 
-    public WeblogTemplate getPage(String id) 
-            throws RollerException {
-        // For templates stored on disk, just return
-        if (id != null && id.endsWith(".vm")) 
-            return null;
-        return (WeblogTemplate)strategy.load(WeblogTemplate.class, id);
+    public List getUsersByLetter(char letter, int offset, int length)
+        throws RollerException {
+        // TODO: ATLAS getUsersByLetter DONE
+        DatamapperQuery query = strategy.newQuery(UserData.class, "UserData.getByUserNameOrderByUserName");
+        query.setRange(offset, offset + length);
+        return (List) query.execute(letter + "%");
     }
 
-    public WeblogTemplate getPageByName(WebsiteData website, String pageName) 
-            throws RollerException {
-        if (website == null)
-            throw new RollerException(
-                    "getPageByName: website cannot be null");
-        if (pageName == null)
-            throw new RollerException(
-                    "getPageByName: Page name cannot be null");
-        return (WeblogTemplate)strategy.newQuery(WeblogTemplate.class,
-                "getUniqueByWebsite&&Name")
-            .execute(new Object[]{website, pageName});
+    public Map getWeblogHandleLetterMap() throws RollerException {
+        String lc = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+        Map results = new TreeMap();
+        DatamapperQuery query = strategy.newQuery(WebsiteData.class, "WebsiteData.getCountByHandleLike");
+        for (int i=0; i<26; i++) {
+            char currentChar = lc.charAt(i);
+            List row = (List) query.execute(currentChar + "%");
+            Integer count = (Integer) row.get(0);
+            results.put(String.valueOf(currentChar), count);
+        }
+        return results;
     }
 
-    public WeblogTemplate getPageByLink(WebsiteData website, String pageLink) 
-            throws RollerException {
-        if (website == null)
-            throw new RollerException(
-                    "getPageByLink: website cannot be null");
-        if (pageLink == null)
-            throw new RollerException(
-                    "getPageByLink: Page link cannot be null");
-        return (WeblogTemplate)strategy.newQuery(WeblogTemplate.class,
-                "getUniqueByWebsite&&Link")
-            .execute(new Object[]{website, pageLink});
+    public List getWeblogsByLetter(char letter, int offset, int length)
+        throws RollerException {
+        // TODO: ATLAS getWeblogsByLetter DONE
+        DatamapperQuery query = strategy.newQuery(WebsiteData.class, "WebsiteData.getByHandleOrderByHandle");
+        if (offset != 0 || length != -1) {
+            if (length == -1) {
+                length = Integer.MAX_VALUE - offset;
+            }            
+            query.setRange(offset, offset + length);
+        }
+        return (List) query.execute(letter + "%");
     }
 
-    public List getPages(WebsiteData website) 
-            throws RollerException {
-        return (List)strategy.newQuery(WeblogTemplate.class,
-                "getByWebsite.orderByName")
-            .execute(website);
-    }
+    public List getMostCommentedWebsites(Date startDate, Date endDate, int offset, int length)
+        throws RollerException {
+        // TODO: ATLAS getMostCommentedWebsites DONE TESTED
+
+        DatamapperQuery query = null;
+        List queryResults = null;
+        boolean setRange = offset != 0 || length != -1;
+
+        if (length == -1) {
+            length = Integer.MAX_VALUE - offset;
+        }
+
+        if (endDate == null) endDate = new Date();
+        
+        if (startDate != null) {
+            query = strategy.newQuery(CommentData.class, "CommentData.getMostCommentedWebsiteByEndDate&StartDate");
+            if (setRange) query.setRange(offset, offset + length);
+            queryResults = (List) query.execute(new Object[] {endDate, startDate});            
+        } else {
+            query = strategy.newQuery(CommentData.class, "CommentData.getMostCommentedWebsiteByEndDate");
+            if (setRange) query.setRange(offset, offset + length);
+            queryResults = (List) query.execute(endDate);
+        }
 
-    public void release() {
+        // TODO: DatamapperPort - The original query list column not present in group by clause in select clause
+        // this is not allowed by JPA spec (and many db vendors).
+        // Changed the select clause to match group by clause.
+        // Currently, the only caller of this method is SiteModel.getMostCommentedWeblogs() (apart from a junit test)
+        // check with roller developers what is the expected behavior of this query 
+
+        List results = new ArrayList();
+        for (Iterator iter = queryResults.iterator(); iter.hasNext();) {
+            Object[] row = (Object[]) iter.next();
+            results.add(new StatCount(
+                (String)row[1],
+                (String)row[2],
+                (String)row[3],
+                "statCount.weblogCommentCountType",
+                new Long(((Integer)row[0]).intValue()).longValue()));
+        }
+        // TODO Collections.sort(results, StatCount.getComparator());
+        Collections.reverse(results);
+        return results;
     }
 
-    private String getProperty(String property) throws RollerException {
-        return RollerFactory.getRoller().getPropertiesManager()
-            .getProperty(property).getValue();
+    /**
+     * Get count of weblogs, active and inactive
+     */    
+    public long getWeblogCount() throws RollerException {
+        long ret = 0;
+        List results = (List) strategy.newQuery(WebsiteData.class, "WebsiteData.getCountAllDistinct").execute();
+
+        ret = ((Integer)results.get(0)).intValue();
+        
+        return ret;
     }
 
+    
+    /**
+     * Get count of users, enabled only
+     */    
+    public long getUserCount() throws RollerException {
+        long ret = 0;
+        List results = (List) strategy.newQuery(UserData.class, "UserData.getCountEnabledDistinct").execute(Boolean.TRUE);
+
+        ret =((Integer)results.get(0)).intValue();
+
+        return ret;
+    }
+    
+    
 }