Author: [email protected]
Date: Wed Feb 16 12:05:31 2011
New Revision: 793

Log:
[AMDATU-303] Fixed error and added a Unit test to excessively test the proper 
working of search results paging. Also improved UserAdmin gadget to properly 
handle the fact that there are no start, end, previous or next pages.

Added:
   trunk/amdatu-authorization/useradmin-rest/src/test/
   trunk/amdatu-authorization/useradmin-rest/src/test/java/
   trunk/amdatu-authorization/useradmin-rest/src/test/java/org/
   trunk/amdatu-authorization/useradmin-rest/src/test/java/org/amdatu/
   
trunk/amdatu-authorization/useradmin-rest/src/test/java/org/amdatu/authorization/
   
trunk/amdatu-authorization/useradmin-rest/src/test/java/org/amdatu/authorization/useradmin/
   
trunk/amdatu-authorization/useradmin-rest/src/test/java/org/amdatu/authorization/useradmin/rest/
   
trunk/amdatu-authorization/useradmin-rest/src/test/java/org/amdatu/authorization/useradmin/rest/UserAdminSearchResultsTest.java
Modified:
   
trunk/amdatu-authorization/useradmin-gadget/src/main/resources/static/images/end.gif
   
trunk/amdatu-authorization/useradmin-gadget/src/main/resources/static/images/start.gif
   
trunk/amdatu-authorization/useradmin-gadget/src/main/resources/static/js/useradmin.js
   trunk/amdatu-authorization/useradmin-rest/pom.xml
   
trunk/amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/bean/RoleBean.java
   
trunk/amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/bean/SearchResultBean.java
   
trunk/amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/service/ResourceBase.java
   
trunk/amdatu-libraries/utilities/src/main/java/org/amdatu/libraries/utilities/rest/AtomSyndicationLink.java

Modified: 
trunk/amdatu-authorization/useradmin-gadget/src/main/resources/static/images/end.gif
==============================================================================
Binary files. No diff available.

Modified: 
trunk/amdatu-authorization/useradmin-gadget/src/main/resources/static/images/start.gif
==============================================================================
Binary files. No diff available.

Modified: 
trunk/amdatu-authorization/useradmin-gadget/src/main/resources/static/js/useradmin.js
==============================================================================
--- 
trunk/amdatu-authorization/useradmin-gadget/src/main/resources/static/js/useradmin.js
       (original)
+++ 
trunk/amdatu-authorization/useradmin-gadget/src/main/resources/static/js/useradmin.js
       Wed Feb 16 12:05:31 2011
@@ -34,6 +34,18 @@
          }
       }
     }
+    if (prev == null) {
+      prev = getDisabledNavigationLink("previous_disabled.gif");
+    }
+    if (next == null) {
+      next = getDisabledNavigationLink("next_disabled.gif");
+    }
+    if (end == null) {
+      end = getDisabledNavigationLink("end_disabled.gif");
+    }
+    if (start == null) {
+      start = getDisabledNavigationLink("start_disabled.gif");
+    }
 
     var html = "";
 
@@ -311,6 +323,11 @@
   return result;
 }
 
+function getDisabledNavigationLink(image) {
+  var result = "<img src='" + imgBaseUrl + "/" + image + "'/>";
+  return result;
+}
+
 function editRole(link) {
   loadRole(escape(unescape(link)), onRoleLoaded);
   showEditRole();

Modified: trunk/amdatu-authorization/useradmin-rest/pom.xml
==============================================================================
--- trunk/amdatu-authorization/useradmin-rest/pom.xml   (original)
+++ trunk/amdatu-authorization/useradmin-rest/pom.xml   Wed Feb 16 12:05:31 2011
@@ -59,6 +59,18 @@
       <scope>provided</scope>
       <type>bundle</type>
     </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+      <version>1.5.6</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-jdk14</artifactId>
+      <version>1.5.6</version>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <build>
@@ -72,8 +84,8 @@
             
<Bundle-SymbolicName>org.amdatu.authorization.useradmin.rest</Bundle-SymbolicName>
             
<Private-Package>org.amdatu.authorization.useradmin.rest.*,org.apache.wink.common.internal.uri</Private-Package>
             <Embed-Dependency>json,utilities;scope=compile</Embed-Dependency>
-                       <Export-Package>!*</Export-Package>
-                       
<Import-Package>!org.apache.wink.common.internal.*,*</Import-Package>
+      <Export-Package>!*</Export-Package>
+      <Import-Package>!org.apache.wink.common.internal.*,*</Import-Package>
           </instructions>
         </configuration>
       </plugin>

Modified: 
trunk/amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/bean/RoleBean.java
==============================================================================
--- 
trunk/amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/bean/RoleBean.java
  (original)
+++ 
trunk/amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/bean/RoleBean.java
  Wed Feb 16 12:05:31 2011
@@ -150,8 +150,10 @@
         roleBean.setProperties(toStringMap(role.getProperties()));
         String href = "/rest/";
         if (role.getType() == Role.USER) {
-            String[] impliedRoles = userAdmin.getAuthorization((User) 
role).getRoles();
-            roleBean.setImpliedRoles(impliedRoles);
+            if (userAdmin != null) {
+                String[] impliedRoles = userAdmin.getAuthorization((User) 
role).getRoles();
+                roleBean.setImpliedRoles(impliedRoles);
+            }
             href += "users/" + encode(name);
         }
         else {
@@ -184,6 +186,9 @@
 
     @SuppressWarnings("unchecked")
     private static Map<String, String> toStringMap(Dictionary dic) {
+        if (dic == null) {
+            return null;
+        }
         Map<String, String> map = new HashMap<String, String>();
         Enumeration keyEnum = dic.keys();
         while (keyEnum.hasMoreElements()) {

Modified: 
trunk/amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/bean/SearchResultBean.java
==============================================================================
--- 
trunk/amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/bean/SearchResultBean.java
  (original)
+++ 
trunk/amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/bean/SearchResultBean.java
  Wed Feb 16 12:05:31 2011
@@ -34,19 +34,19 @@
 public class SearchResultBean {
     // Default encoding for role properties
     public final static String DEFAULT_CHARSET = "UTF-8";
-    
+
     // Atom links
     private List<AtomSyndicationLink> m_links = new 
ArrayList<AtomSyndicationLink>();
 
     // Paged result properties
-    private int m_pageStartIndex; // Index of first result displayed on 
current page 
+    private int m_pageStartIndex; // Index of first result displayed on 
current page
     private int m_pageEndIndex; // End index of last result displayed on 
current page
     private int m_pageCount; // Amount of results displayed on current page
     private int m_pageMax;  // Maximum number of results displayed on one page
 
     // Result count: total amount of available results (unpaged)
     private int m_resultCount;
-    
+
     // The actual results
     private List<RoleBean> m_roles = new ArrayList<RoleBean>();
 
@@ -109,11 +109,22 @@
     public void setRoles(List<RoleBean> users) {
         m_roles = users;
     }
-    
+
     public void addRoles(List<Role> roles, UserAdmin userAdmin) throws 
URISyntaxException {
         for (Role role : roles) {
             RoleBean roleBean = RoleBean.fromRole(role, userAdmin);
             m_roles.add(roleBean);
         }
     }
+
+    @Override
+    public String toString() {
+        StringBuffer sb = new StringBuffer();
+        sb.append("Calculated paging results for total of '" + 
getResultCount() + "' results:\n");
+        sb.append("    Current page=" + getPageStartIndex() + "-" + 
getPageEndIndex() + "\n");
+        for (AtomSyndicationLink link : getLinks()) {
+            sb.append("    link: " + link.toString() + "\n");
+        }
+        return sb.toString();
+    }
 }

Modified: 
trunk/amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/service/ResourceBase.java
==============================================================================
--- 
trunk/amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/service/ResourceBase.java
   (original)
+++ 
trunk/amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/service/ResourceBase.java
   Wed Feb 16 12:05:31 2011
@@ -54,6 +54,9 @@
     // FIXME: Temporary fix for AMDATU-81
     private static final String DEFAULT_ADMIN_GROUP = "Administrators";
 
+    // Debug mode. If set to true, search results are logged on DEBUG level
+    private static final boolean DEBUG_MODE = false;
+
     // Service dependencies injected by the depedency manager
     protected volatile LogService m_logService;
     protected volatile UserAdmin m_userAdmin;
@@ -71,15 +74,15 @@
     }
 
     public void init(Component component) throws TenantException {
-       // Retrieve the tenant
-       String tenantId = (String) 
component.getServiceProperties().get(Tenant.TENANT_ID_SERVICEPROPERTY);
-       m_tenant = m_tenantManagementService.getTenantById(tenantId);
-
-       // Create a service dependency on the token provider for 'our' tenant
-               String tenantFilter = "(&(" + Tenant.TENANT_ID_SERVICEPROPERTY 
+ "=" + tenantId + ")(" + Constants.OBJECTCLASS
-               + "=" + TokenProvider.class.getName() + "))";
-               m_component.add(m_dependencyManager.createServiceDependency()
-                               .setService(TokenProvider.class, 
tenantFilter).setRequired(true).setInstanceBound(true));
+        // Retrieve the tenant
+        String tenantId = (String) 
component.getServiceProperties().get(Tenant.TENANT_ID_SERVICEPROPERTY);
+        m_tenant = m_tenantManagementService.getTenantById(tenantId);
+
+        // Create a service dependency on the token provider for 'our' tenant
+        String tenantFilter = "(&(" + Tenant.TENANT_ID_SERVICEPROPERTY + "=" + 
tenantId + ")(" + Constants.OBJECTCLASS
+        + "=" + TokenProvider.class.getName() + "))";
+        m_component.add(m_dependencyManager.createServiceDependency()
+            .setService(TokenProvider.class, 
tenantFilter).setRequired(true).setInstanceBound(true));
     }
 
     /**
@@ -103,96 +106,10 @@
 
             // First retrieve all roles with the specified filter
             Role[] roles = m_userAdmin.getRoles(null);
-            final boolean descending = "desc".equalsIgnoreCase(sortOrder) || 
"descending".equalsIgnoreCase(sortOrder);
-
-            // Now filter out the user or groups (we should only return roles 
of type roleType)
-            List<Role> filteredRoles = new ArrayList<Role>();
-            if (roles != null) {
-                for (Role role : roles) {
-                    if (roleType == Role.ROLE) {
-                        filteredRoles.add(role);
-                    } else if (role.getType() == roleType) {
-                        if (filter == null || role.getName().matches("(?i:.*" 
+ filter + ".*)")) {
-                            filteredRoles.add(role);
-                        }
-                    }
-                }
+            if (roles == null) {
+                return buildNotFound();
             }
-
-            // Finally sort it
-            Comparator<Role> userComparator = new Comparator<Role>() {
-                public int compare(Role r1, Role r2) {
-                    if (descending) {
-                        return -r1.getName().compareTo(r2.getName());
-                    }
-                    return r1.getName().compareTo(r2.getName());
-                }
-            };
-            Collections.sort(filteredRoles, userComparator);
-
-            // Now filter from startIndex - endIndex
-            if (startIndex > filteredRoles.size()) {
-                // Start index out of range, shift!
-                startIndex = Math.max(0, startIndex - maxResults);
-            }
-            List<Role> roleRange = new ArrayList<Role>();
-            for (int i = (startIndex - 1); i < (startIndex + maxResults - 1) 
&& i < filteredRoles.size(); i++) {
-                roleRange.add(filteredRoles.get(i));
-            }
-
-            SearchResultBean result = new SearchResultBean();
-            result.addRoles(roleRange, m_userAdmin);
-
-            // Calculate paging
-            Paging paging = new Paging();
-            paging.calculate(startIndex, roleRange.size(), maxResults, 
filteredRoles.size());
-            String debugMsg = "Calculated paging results for total of '" + 
paging.resultCount + "' results:\n";
-            debugMsg += "    Current page=" + paging.pageStartIndex + "-" + 
paging.pageEndIndex + "\n";
-            debugMsg += "    Start page=" + paging.firstStartIndex + "-" + 
paging.firstEndIndex + "\n";
-            debugMsg += "    Previous page=" + paging.previousStartIndex + "-" 
+ paging.previousEndIndex + "\n";
-            debugMsg += "    Next page=" + paging.nextStartIndex + "-" + 
paging.nextEndIndex + "\n";
-            debugMsg += "    End page=" + paging.lastStartIndex + "-" + 
paging.lastEndIndex;
-            m_logService.log(LogService.LOG_DEBUG, debugMsg);
-
-            // Set the 5 Atom links current, first, previous, next and start
-            String url = "";
-
-            // Start
-            url =
-                getBaseUrl() + "?startIndex=" + paging.pageStartIndex + 
"&endIndex=" + paging.pageEndIndex
-                + "&maxResults=" + maxResults;
-            result.addLink(new 
AtomSyndicationLink().setHref(url).setRel("Alternate").setType("application/json"));
-
-            // Start
-            url =
-                getBaseUrl() + "?startIndex=" + paging.firstStartIndex + 
"&endIndex=" + paging.firstEndIndex
-                + "&maxResults=" + maxResults;
-            result.addLink(new 
AtomSyndicationLink().setHref(url).setRel("Start").setType("application/json"));
-
-            // Prev
-            url =
-                getBaseUrl() + "?startIndex=" + paging.previousStartIndex + 
"&endIndex=" + paging.previousEndIndex
-                + "&maxResults=" + maxResults;
-            result.addLink(new 
AtomSyndicationLink().setHref(url).setRel("Prev").setType("application/json"));
-
-            // Next
-            url =
-                getBaseUrl() + "?startIndex=" + paging.nextStartIndex + 
"&endIndex=" + paging.nextEndIndex
-                + "&maxResults=" + maxResults;
-            result.addLink(new 
AtomSyndicationLink().setHref(url).setRel("Next").setType("application/json"));
-
-            // Last
-            url =
-                getBaseUrl() + "?startIndex=" + paging.lastStartIndex + 
"&endIndex=" + paging.lastEndIndex
-                + "&maxResults=" + maxResults;
-            result.addLink(new 
AtomSyndicationLink().setHref(url).setRel("End").setType("application/json"));
-
-            result.setPageMax(paging.pageMax);
-            result.setPageStartIndex(paging.pageStartIndex);
-            result.setPageEndIndex(paging.pageEndIndex);
-            result.setPageCount(paging.pageCount);
-            result.setResultCount(paging.resultCount);
-
+            SearchResultBean result = getSearchResultBean(roles, filter, 
sortOrder, startIndex, maxResults, roleType);
             return Response.ok(result).cacheControl(m_cacheControl).build();
         }
         catch (InvalidSyntaxException e) {
@@ -206,6 +123,90 @@
         return buildServerError();
     }
 
+    public SearchResultBean getSearchResultBean(Role[] roles, String filter, 
String sortOrder, int startIndex, int maxResults, int roleType) throws 
URISyntaxException {
+        if (startIndex <= 0) {
+            startIndex = 1;
+        }
+        if (maxResults < 0) {
+            maxResults = 50;
+        }
+
+        // First retrieve all roles with the specified filter
+        final boolean descending = "desc".equalsIgnoreCase(sortOrder) || 
"descending".equalsIgnoreCase(sortOrder);
+
+        // Now filter out the user or groups (we should only return roles of 
type roleType)
+        List<Role> filteredRoles = new ArrayList<Role>();
+        if (roles != null) {
+            for (Role role : roles) {
+                if (roleType == Role.ROLE) {
+                    filteredRoles.add(role);
+                } else if (role.getType() == roleType) {
+                    if (filter == null || role.getName().matches("(?i:.*" + 
filter + ".*)")) {
+                        filteredRoles.add(role);
+                    }
+                }
+            }
+        }
+
+        // Finally sort it
+        Comparator<Role> userComparator = new Comparator<Role>() {
+            public int compare(Role r1, Role r2) {
+                if (descending) {
+                    return -r1.getName().compareTo(r2.getName());
+                }
+                return r1.getName().compareTo(r2.getName());
+            }
+        };
+        Collections.sort(filteredRoles, userComparator);
+
+        // Now filter from startIndex - endIndex
+        if (startIndex > filteredRoles.size()) {
+            // Start index out of range, shift!
+            startIndex = Math.max(1, startIndex - maxResults);
+        }
+        if (startIndex < 1) {
+
+            System.out.println("startIndex="+startIndex+", 
maxResults="+maxResults + ", filteredRoles.size()="+filteredRoles.size());
+        }
+        List<Role> roleRange = new ArrayList<Role>();
+        for (int i = (startIndex - 1); i < (startIndex + maxResults - 1) && i 
< filteredRoles.size(); i++) {
+            roleRange.add(filteredRoles.get(i));
+        }
+
+        SearchResultBean result = new SearchResultBean();
+        result.addRoles(roleRange, m_userAdmin);
+
+        // Calculate paging
+        Paging paging = new Paging();
+        paging.calculate(startIndex, roleRange.size(), maxResults, 
filteredRoles.size());
+        if (DEBUG_MODE) {
+            m_logService.log(LogService.LOG_DEBUG, result.toString());
+        }
+
+        // Set the 5 Atom links current, first, previous, next and start
+        addLink(result, "Alternate", paging.pageStartIndex, 
paging.pageEndIndex, maxResults);
+        addLink(result, "Start", paging.firstStartIndex, paging.firstEndIndex, 
maxResults);
+        addLink(result, "Prev", paging.previousStartIndex, 
paging.previousEndIndex, maxResults);
+        addLink(result, "Next", paging.nextStartIndex, paging.nextEndIndex, 
maxResults);
+        addLink(result, "End", paging.lastStartIndex, paging.lastEndIndex, 
maxResults);
+
+        result.setPageMax(paging.pageMax);
+        result.setPageStartIndex(paging.pageStartIndex);
+        result.setPageEndIndex(paging.pageEndIndex);
+        result.setPageCount(paging.pageCount);
+        result.setResultCount(paging.resultCount);
+
+        return result;
+    }
+
+    private void addLink(SearchResultBean bean, String type, int start, int 
end, int max) {
+        if (start != -1 && end != -1) {
+            String url =
+                getBaseUrl() + "?startIndex=" + start + "&endIndex=" + end + 
"&maxResults=" + max;
+            bean.addLink(new 
AtomSyndicationLink().setHref(url).setRel(type).setType("application/json"));
+        }
+    }
+
     protected Response getRole(String name, int roleType) {
         Role role = m_userAdmin.getRole(name);
         if (role != null && role.getType() == roleType) {
@@ -317,6 +318,24 @@
          * @param totalResults The total amount of available results
          */
         public void calculate(int currentStartIndex, int pageResults, int 
maxResults, int totalResults) {
+            if (totalResults == 0) {
+                // No guts no glory, no results no links
+                previousStartIndex = -1;
+                previousEndIndex = -1;
+                nextStartIndex = -1;
+                nextEndIndex = -1;
+                lastStartIndex = -1;
+                lastEndIndex = -1;
+                firstStartIndex = -1;
+                firstEndIndex = -1;
+                resultCount = totalResults;
+                pageCount = 0;
+                pageMax = maxResults;
+                pageStartIndex = 0;
+                pageEndIndex = 0;
+                return;
+            }
+
             resultCount = totalResults;
             pageCount = pageResults;
             pageMax = maxResults;
@@ -324,17 +343,27 @@
             pageEndIndex = Math.max(0, pageStartIndex + (pageResults - 1));
 
             // Calculate first page
-            firstStartIndex = pageResults > 0 ? 1 : 0;
-            firstEndIndex = Math.min(pageResults, maxResults);
+            firstStartIndex = totalResults > 0 ? 1 : 0;
+            firstEndIndex = Math.min(totalResults, maxResults);
 
             // Calculate previous page
             if (currentStartIndex - maxResults < firstStartIndex) {
-                previousStartIndex = firstStartIndex;
-                previousEndIndex = firstEndIndex;
+                if (currentStartIndex > firstStartIndex) {
+                    previousStartIndex = firstStartIndex;
+                    previousEndIndex = currentStartIndex - 1;
+                } else {
+                    previousStartIndex = -1;
+                    previousEndIndex = -1;
+                }
             }
             else {
-                previousStartIndex = currentStartIndex - maxResults;
-                previousEndIndex = currentStartIndex - 1;
+                if (currentStartIndex <= totalResults) {
+                    previousStartIndex = currentStartIndex - maxResults;
+                    previousEndIndex = currentStartIndex - 1;
+                } else {
+                    previousStartIndex = -1;
+                    previousEndIndex = -1;
+                }
             }
 
             // Calculate last page
@@ -348,16 +377,17 @@
 
             // Calculate next page
             if (currentStartIndex + maxResults > lastStartIndex) {
-                nextStartIndex = lastStartIndex;
+                nextStartIndex = -1;
+                nextEndIndex = -1;
             }
             else {
                 nextStartIndex = currentStartIndex + maxResults;
-            }
-            if (nextStartIndex + maxResults > lastEndIndex) {
-                nextEndIndex = lastEndIndex;
-            }
-            else {
-                nextEndIndex = Math.min(nextStartIndex + maxResults, 
totalResults);
+                if (nextStartIndex + maxResults > lastEndIndex) {
+                    nextEndIndex = lastEndIndex;
+                }
+                else {
+                    nextEndIndex = Math.min(nextStartIndex + maxResults - 1, 
totalResults);
+                }
             }
         }
     }

Added: 
trunk/amdatu-authorization/useradmin-rest/src/test/java/org/amdatu/authorization/useradmin/rest/UserAdminSearchResultsTest.java
==============================================================================
--- (empty file)
+++ 
trunk/amdatu-authorization/useradmin-rest/src/test/java/org/amdatu/authorization/useradmin/rest/UserAdminSearchResultsTest.java
     Wed Feb 16 12:05:31 2011
@@ -0,0 +1,294 @@
+/*
+    Copyright (C) 2010 Amdatu.org
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.amdatu.authorization.useradmin.rest;
+
+import java.net.URISyntaxException;
+import java.util.Dictionary;
+import java.util.List;
+
+import junit.framework.Assert;
+
+import org.amdatu.authorization.useradmin.rest.bean.RoleBean;
+import org.amdatu.authorization.useradmin.rest.bean.SearchResultBean;
+import org.amdatu.authorization.useradmin.rest.service.UsersResource;
+import org.amdatu.libraries.utilities.rest.AtomSyndicationLink;
+import org.junit.Test;
+import org.osgi.service.useradmin.Role;
+
+public class UserAdminSearchResultsTest {
+    /**
+     * Test the proper search results when no results are returned.
+     * @throws URISyntaxException
+     */
+    @Test
+    public void testNoSearchResults() throws URISyntaxException {
+        // No roles, no results
+        Role[] roles = new Role[0];
+        String filter = "";
+        String sortOrder = "";
+        int startIndex = 1;
+        int maxResults = 50;
+        int roleType = Role.USER;
+
+        UsersResource users = new UsersResource();
+        SearchResultBean bean = users.getSearchResultBean(roles, filter, 
sortOrder, startIndex, maxResults, roleType);
+        assertCurrentPage(bean, 0, 0, 0, maxResults, 0);
+        assertNoPage(bean, "Next"); // There should be no Next page
+        assertNoPage(bean, "Prev"); // There should be no Previous page
+        assertNoPage(bean, "Start"); // There should be no Start page
+        assertNoPage(bean, "End"); // There should be no End page
+
+        // Different maxResults
+        maxResults = 100;
+        bean = users.getSearchResultBean(roles, filter, sortOrder, startIndex, 
maxResults, roleType);
+        assertCurrentPage(bean, 0, 0, 0, maxResults, 0);
+        assertNoPage(bean, "Next"); // There should be no Next page
+        assertNoPage(bean, "Prev"); // There should be no Previous page
+        assertNoPage(bean, "Start"); // There should be no Start page
+        assertNoPage(bean, "End"); // There should be no End page
+
+        // Invalid start index
+        startIndex = -23;
+        bean = users.getSearchResultBean(roles, filter, sortOrder, startIndex, 
maxResults, roleType);
+        assertCurrentPage(bean, 0, 0, 0, maxResults, 0);
+        assertNoPage(bean, "Next"); // There should be no Next page
+        assertNoPage(bean, "Prev"); // There should be no Previous page
+        assertNoPage(bean, "Start"); // There should be no Start page
+        assertNoPage(bean, "End"); // There should be no End page
+
+        startIndex = 34543;
+        bean = users.getSearchResultBean(roles, filter, sortOrder, startIndex, 
maxResults, roleType);
+        assertCurrentPage(bean, 0, 0, 0, maxResults, 0);
+        assertNoPage(bean, "Next"); // There should be no Next page
+        assertNoPage(bean, "Prev"); // There should be no Previous page
+        assertNoPage(bean, "Start"); // There should be no Start page
+        assertNoPage(bean, "End"); // There should be no End page
+
+        // Invalid sort order
+        sortOrder = "invalid";
+        bean = users.getSearchResultBean(roles, filter, sortOrder, startIndex, 
maxResults, roleType);
+        assertCurrentPage(bean, 0, 0, 0, maxResults, 0);
+        assertNoPage(bean, "Next"); // There should be no Next page
+        assertNoPage(bean, "Prev"); // There should be no Previous page
+        assertNoPage(bean, "Start"); // There should be no Start page
+        assertNoPage(bean, "End"); // There should be no End page
+    }
+
+    /**
+     * Implements an excessive paging test. Search results are paged by n 
results, where n is
+     * configurable. For example, if there are 256 results available and n is 
50, page 1 is 1-50,
+     * page 2 is 51-100, etc.
+     * Another argument is the start index, which determined the first record 
returned by the result.
+     * If the start index is provided (defaults to 1), paging is calculated 
from this index. So for
+     * example when the start index is 123, the results returned are 123-152, 
the previous page is
+     * 73-122 and the next page is 153-202.
+     * The first page always starts at 1 and the last page always ends with 
the last record (256 in this example).
+     * Note that the first and last pages returned are independent of the 
provided start index; they
+     * just return the very first page available and the last page available 
according to the configured
+     * amount of records on 1 page; n.
+     * @throws URISyntaxException
+     */
+    @Test
+    public void testSearchResultPaging() throws URISyntaxException {
+        // Test with 256 roles, paged with 50 results on each page
+        Role[] roles = new Role[256];
+        for (int i=0; i<roles.length; i++) {
+            roles[i] = createRandomUser();
+        }
+        String filter = "";
+        String sortOrder = "asc";
+        int startIndex = 1;
+        int maxResults = 50;
+        int roleType = Role.USER;
+
+        UsersResource users = new UsersResource();
+        SearchResultBean bean = users.getSearchResultBean(roles, filter, 
sortOrder, startIndex, maxResults, roleType);
+
+        assertCurrentPage(bean, 50, 1, 50, maxResults, 256); // Current page 
should return 50 results; 1-50 of 256
+        assertPage(bean, "Next", 51, 100, maxResults); // Next page should 
return results 51-100
+        assertNoPage(bean, "Prev"); // There should be no previous page
+        assertPage(bean, "Start", 1, 50, maxResults); // Start page should 
return results 1-50
+        assertPage(bean, "End", 251, 256, maxResults); // End page should 
return results 251-256
+        assertOrder(bean.getRoles(), true); // Verify ordering of results
+
+        // Same test but in descending order
+        sortOrder = "desc";
+        bean = users.getSearchResultBean(roles, filter, sortOrder, startIndex, 
maxResults, roleType);
+        assertCurrentPage(bean, 50, 1, 50, maxResults, 256); // Current page 
should return 50 results; 1-50 of 256
+        assertPage(bean, "Next", 51, 100, maxResults); // Next page should 
return results 51-100
+        assertNoPage(bean, "Prev"); // There should be no previous page
+        assertPage(bean, "Start", 1, 50, maxResults); // Start page should 
return results 1-50
+        assertPage(bean, "End", 251, 256, maxResults); // End page should 
return results 251-256
+        assertOrder(bean.getRoles(), false); // Verify ordering of results
+
+        // Now test with several start indices
+        // Start index = 0
+        startIndex = 0;
+        bean = users.getSearchResultBean(roles, filter, sortOrder, startIndex, 
maxResults, roleType);
+        assertCurrentPage(bean, 50, 1, 50, maxResults, 256); // Current page 
should return 50 results; 1-50 of 256
+        assertPage(bean, "Next", 51, 100, maxResults); // Next page should 
return results 51-100
+        assertNoPage(bean, "Prev"); // There should be no previous page
+        assertPage(bean, "Start", 1, 50, maxResults); // Start page should 
return results 1-50
+        assertPage(bean, "End", 251, 256, maxResults); // End page should 
return results 251-256
+        assertOrder(bean.getRoles(), false); // Verify ordering of results
+
+        // Start index = 43
+        startIndex = 43;
+        bean = users.getSearchResultBean(roles, filter, sortOrder, startIndex, 
maxResults, roleType);
+        assertCurrentPage(bean, 50, 43, 92, maxResults, 256); // Current page 
should return 50 results; 43-92 of 256
+        assertPage(bean, "Next", 93, 142, maxResults); // Next page should 
return results 51-100
+        assertPage(bean, "Prev", 1, 42, maxResults); // Previous page should 
return results 1-50
+        assertPage(bean, "Start", 1, 50, maxResults); // Start page should 
return results 1-50
+        assertPage(bean, "End", 251, 256, maxResults); // End page should 
return results 251-256
+        assertOrder(bean.getRoles(), false); // Verify ordering of results
+
+        // Start index = 50
+        startIndex = 50;
+        bean = users.getSearchResultBean(roles, filter, sortOrder, startIndex, 
maxResults, roleType);
+        assertCurrentPage(bean, 50, 50, 99, maxResults, 256); // Current page 
should return 50 results; 50-99 of 256
+        assertPage(bean, "Next", 100, 149, maxResults); // Next page should 
return results 100-149
+        assertPage(bean, "Prev", 1, 49, maxResults); // Previous page should 
return results 1-50
+        assertPage(bean, "Start", 1, 50, maxResults); // Start page should 
return results 1-50
+        assertPage(bean, "End", 251, 256, maxResults); // End page should 
return results 251-256
+        assertOrder(bean.getRoles(), false); // Verify ordering of results
+
+        // Start index = 51
+        startIndex = 51;
+        bean = users.getSearchResultBean(roles, filter, sortOrder, startIndex, 
maxResults, roleType);
+        assertCurrentPage(bean, 50, 51, 100, maxResults, 256); // Current page 
should return 50 results; 1-50 of 256
+        assertPage(bean, "Next", 101, 150, maxResults); // Next page should 
return results 51-100
+        assertPage(bean, "Prev", 1, 50, maxResults); // Previous page should 
return results 1-50
+        assertPage(bean, "Start", 1, 50, maxResults); // Start page should 
return results 1-50
+        assertPage(bean, "End", 251, 256, maxResults); // End page should 
return results 251-256
+        assertOrder(bean.getRoles(), false); // Verify ordering of results
+
+        // Start index = 133
+        startIndex = 133;
+        bean = users.getSearchResultBean(roles, filter, sortOrder, startIndex, 
maxResults, roleType);
+        assertCurrentPage(bean, 50, 133, 182, maxResults, 256); // Current 
page should return 50 results; 133-182 of 256
+        assertPage(bean, "Next", 183, 232, maxResults); // Next page should 
return results 183-232
+        assertPage(bean, "Prev", 83, 132, maxResults); // Previous page should 
return results 83-132
+        assertPage(bean, "Start", 1, 50, maxResults); // Start page should 
return results 1-50
+        assertPage(bean, "End", 251, 256, maxResults); // End page should 
return results 251-256
+        assertOrder(bean.getRoles(), false); // Verify ordering of results
+
+        // Start index = 223
+        startIndex = 223;
+        bean = users.getSearchResultBean(roles, filter, sortOrder, startIndex, 
maxResults, roleType);
+        assertCurrentPage(bean, 34, 223, 256, maxResults, 256); // Current 
page should return 34 results; 223-256 of 256
+        assertNoPage(bean, "Next"); // There should be no Next page
+        assertPage(bean, "Prev", 173, 222, maxResults); // Previous page 
should return results 83-132
+        assertPage(bean, "Start", 1, 50, maxResults); // Start page should 
return results 1-50
+        assertPage(bean, "End", 251, 256, maxResults); // End page should 
return results 251-256
+        assertOrder(bean.getRoles(), false); // Verify ordering of results
+
+        // Start index = 255
+        startIndex = 255;
+        bean = users.getSearchResultBean(roles, filter, sortOrder, startIndex, 
maxResults, roleType);
+        assertCurrentPage(bean, 2, 255, 256, maxResults, 256); // Current page 
should return 2 results; 255-256 of 256
+        assertNoPage(bean, "Next"); // There should be no Next page
+        assertPage(bean, "Prev", 205, 254, maxResults); // Previous page 
should return results 205-254
+        assertPage(bean, "Start", 1, 50, maxResults); // Start page should 
return results 1-50
+        assertPage(bean, "End", 251, 256, maxResults); // End page should 
return results 251-256
+        assertOrder(bean.getRoles(), false); // Verify ordering of results
+
+        // Start index = 256
+        startIndex = 256;
+        bean = users.getSearchResultBean(roles, filter, sortOrder, startIndex, 
maxResults, roleType);
+        assertCurrentPage(bean, 1, 256, 256, maxResults, 256); // Current page 
should return 1 result; 256-256 of 256
+        assertNoPage(bean, "Next"); // There should be no Next page
+        assertPage(bean, "Prev", 206, 255, maxResults); // Previous page 
should return results 206-255
+        assertPage(bean, "Start", 1, 50, maxResults); // Start page should 
return results 1-50
+        assertPage(bean, "End", 251, 256, maxResults); // End page should 
return results 251-256
+        assertOrder(bean.getRoles(), false); // Verify ordering of results
+
+        // Start index = 389
+        startIndex = 389;
+        bean = users.getSearchResultBean(roles, filter, sortOrder, startIndex, 
maxResults, roleType);
+        assertCurrentPage(bean, 0, 0,0, maxResults, 256); // Current page 
should return 0 results; 0-0 of 256
+        assertNoPage(bean, "Next"); // There should be no Next page
+        assertNoPage(bean, "Prev"); // There should be no Previous page
+        assertPage(bean, "Start", 1, 50, maxResults); // Start page should 
return results 1-50
+        assertPage(bean, "End", 251, 256, maxResults); // End page should 
return results 251-256
+        assertOrder(bean.getRoles(), false); // Verify ordering of results
+    }
+
+    private void assertCurrentPage(SearchResultBean bean, int pageCount, int 
start, int end, int max, int results) {
+        Assert.assertEquals("Page count:", pageCount, bean.getPageCount());
+        Assert.assertEquals("Page start index: ", start, 
bean.getPageStartIndex());
+        Assert.assertEquals("Page end index: ", end, bean.getPageEndIndex());
+        Assert.assertEquals("Page max: ", max, bean.getPageMax());
+        Assert.assertEquals("Number of results: ", results, 
bean.getResultCount());
+    }
+
+    private void assertPage(SearchResultBean bean, String pageType, int start, 
int end, int max) {
+        AtomSyndicationLink pageLink = null;
+        for (AtomSyndicationLink link : bean.getLinks()) {
+            if (link.getRel().equals(pageType)) {
+                pageLink = link;
+            }
+        }
+        Assert.assertNotNull(pageLink);
+        String expectedHref = "/rest/users?startIndex=" + start + "&endIndex=" 
+ end + "&maxResults=" + max;
+        Assert.assertEquals(pageType + " page:", expectedHref, 
pageLink.getHref());
+    }
+
+    private void assertNoPage(SearchResultBean bean, String pageType) {
+        AtomSyndicationLink pageLink = null;
+        for (AtomSyndicationLink link : bean.getLinks()) {
+            if (link.getRel().equals(pageType)) {
+                pageLink = link;
+            }
+        }
+        Assert.assertNull(pageLink);
+    }
+
+    private void assertOrder(List<RoleBean> roles, boolean asc) {
+        for (int i=0; i<roles.size(); i++) {
+            if (i > 0) {
+                String r1 = roles.get(i-1).getName();
+                String r2 = roles.get(i).getName();
+                if (asc) {
+                    Assert.assertTrue(r1.compareTo(r2) <= 0);
+                } else {
+                    Assert.assertTrue(r1.compareTo(r2) >= 0);
+                }
+            }
+        }
+    }
+
+    private Role createRandomUser() {
+        return new Role() {
+            String m_name = null;
+            public String getName() {
+                if (m_name == null) {
+                    m_name = "User " + Math.round(Math.random()*1000000);
+                }
+                return m_name;
+            }
+
+            @SuppressWarnings("unchecked")
+            public Dictionary getProperties() {
+                return null;
+            }
+
+            public int getType() {
+                return Role.USER;
+            }
+        };
+    }
+}

Modified: 
trunk/amdatu-libraries/utilities/src/main/java/org/amdatu/libraries/utilities/rest/AtomSyndicationLink.java
==============================================================================
--- 
trunk/amdatu-libraries/utilities/src/main/java/org/amdatu/libraries/utilities/rest/AtomSyndicationLink.java
 (original)
+++ 
trunk/amdatu-libraries/utilities/src/main/java/org/amdatu/libraries/utilities/rest/AtomSyndicationLink.java
 Wed Feb 16 12:05:31 2011
@@ -108,4 +108,7 @@
         m_type = type;
         return this;
     }
+
+    public String toString() {
+        return "href='" + getHref() + "', rel='" + getRel() + "', type='" + 
getType() + "'";    }
 }
_______________________________________________
Amdatu-commits mailing list
[email protected]
http://lists.amdatu.org/mailman/listinfo/amdatu-commits

Reply via email to