Merge from SEAMIST3

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@10719 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
David Caruana
2008-09-04 10:41:04 +00:00
parent a0a36dd1ed
commit 9bb82eff7f
10 changed files with 2163 additions and 0 deletions

View File

@@ -0,0 +1,454 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
*
* 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 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.web.util;
/**
* Paging cursor. A utility for maintaining paged indexes for a collection of N items.
*
* There are two types of cursor:
*
* a) Paged
*
* This type of cursor is driven from a page number and page size. Random access within
* the collection is possible by jumping straight to a page. A simple scroll through
* the collection is supported by iterating through each next page.
*
* b) Rows
*
* This type of cursor is driven from a skip row count and maximum number of rows. Random
* access is not supported. The collection of items is simply scrolled through from
* start to end by iterating through each next set of rows.
*
* In either case, a paging cursor provides a start row and end row which may be used
* to extract the items for the page from the collection of N items.
*
* A zero (or less) page size or row maximum means "unlimited".
*
* Zero or one based Page and Rows indexes are supported. By default, Pages are 1 based and
* Rows are 0 based.
*
* At any time, -1 is returned to represent "out of range" i.e. for next, previous, last page
* and next skip count.
*
* Pseudo-code for traversing through a collection of N items (10 at a time):
*
* PagingCursor cursor = new PagingCursor();
* Page page = cursor.createPageCursor(N, 10, 1);
* while (page.isInRange())
* {
* for (long i = page.getStartRow(); i <= page.getEndRow(); i++)
* {
* ...collection[i]...
* }
* page = cursor.createPageCursor(N, 10, page.getNextPage());
* }
*
* Rows rows = cursor.createRowsCursor(N, 10, 0);
* while (rows.isInRange())
* {
* for (long i = page.getStartRow(); i <= page.getEndRow(); i++)
* {
* ...collection[i]...
* }
* rows = cursor.createRowsCursor(N, 10, rows.getNextSkipRows());
* }
*
* @author davidc
*/
public class PagingCursor
{
boolean zeroBasedPage = false;
boolean zeroBasedRow = true;
/**
* Sets zero based page index
*
* Note: scoped to this paging cursor instance
*
* @param zeroBasedPage true => 0 based, false => 1 based
*/
public void setZeroBasedPage(boolean zeroBasedPage)
{
this.zeroBasedPage = zeroBasedPage;
}
/**
* Is zero based page index?
*
* Note: scoped to this paging cursor instance
*
* @return true => 0 based, false => 1 based
*/
public boolean isZeroBasedPage()
{
return zeroBasedPage;
}
/**
* Sets zero based row index
*
* Note: scoped to this paging cursor instance
*
* @param zeroBasedRow true => 0 based, false => 1 based
*/
public void setZeroBasedRow(boolean zeroBasedRow)
{
this.zeroBasedRow = zeroBasedRow;
}
/**
* Is zero based row index?
*
* Note: scoped to this paging cursor instance
*
* @return true => 0 based, false => 1 based
*/
public boolean isZeroBasedRow()
{
return zeroBasedRow;
}
/**
* Create a Page based Cursor
*
* @param totalRows total rows in collection
* @param rowsPerPage page size
* @param page page number (0 or 1 based)
* @return Page Cursor
*/
public Page createPageCursor(long totalRows, int rowsPerPage, int page)
{
return new Page(totalRows, rowsPerPage, page, zeroBasedPage, zeroBasedRow);
}
/**
* Create a Page based Cursor
*
* @param totalRows total rows in collection
* @param rowsPerPage page size
* @param page page number (0 or 1 based)
* @param zeroBasedPage true => 0 based, false => 1 based
* @param zeroBasedRow true => 0 based, false => 1 based
* @return Page Cursor
*/
public Page createPageCursor(long totalRows, int rowsPerPage, int page, boolean zeroBasedPage, boolean zeroBasedRow)
{
return new Page(totalRows, rowsPerPage, page, zeroBasedPage, zeroBasedRow);
}
/**
* Create a Rows based Cursor
*
* @param totalRows total rows in collection
* @param maxRows maximum number of rows in page
* @param skipRows number of rows to skip (0 - none)
* @return Rows Cursor
*/
public Rows createRowsCursor(long totalRows, long maxRows, long skipRows)
{
return new Rows(totalRows, maxRows, skipRows, zeroBasedRow);
}
/**
* Create a Rows based Cursor
*
* @param totalRows total rows in collection
* @param maxRows maximum number of rows in page
* @param skipRows number of rows to skip (0 - none)
* @param zeroBasedRow true => 0 based, false => 1 based
* @return Rows Cursor
*/
public Rows createRowsCursor(long totalRows, long maxRows, long skipRows, boolean zeroBasedRow)
{
return new Rows(totalRows, maxRows, skipRows, zeroBasedRow);
}
/**
* Page based Cursor
*/
public static class Page
{
boolean zeroBasedPage;
boolean zeroBasedRow;
long totalRows;
int rowsPerPage;
long pageSize;
int currentPage;
int currentRow;
/**
* Create a Page based Cursor
*
* @param totalRows total rows in collection
* @param rowsPerPage page size
* @param page page number (0 or 1 based)
* @param zeroBasedPage true => 0 based, false => 1 based
* @param zeroBasedRow true => 0 based, false => 1 based
*/
public Page(long totalRows, int rowsPerPage, int page, boolean zeroBasedPage, boolean zeroBasedRow)
{
this.zeroBasedPage = zeroBasedPage;
this.zeroBasedRow = zeroBasedRow;
this.totalRows = totalRows;
this.rowsPerPage = rowsPerPage;
this.pageSize = (rowsPerPage <=0) ? totalRows : rowsPerPage;
this.currentPage = (zeroBasedPage) ? page : page - 1;
}
/**
* Gets total rows
*
* @return total rows
*/
public long getTotalRows()
{
return totalRows;
}
/**
* Gets total number of pages
*
* @return total number of pages
*/
public int getTotalPages()
{
if (totalRows == 0)
return 0;
int totalPages = (int)(totalRows / pageSize);
totalPages += (totalRows % pageSize != 0) ? 1 : 0;
return totalPages;
}
/**
* Gets page size
*
* @return page size
*/
public int getRowsPerPage()
{
return rowsPerPage;
}
/**
* Is the cursor within range of the total number of rows
*
* @return true => within range of total rows
*/
public boolean isInRange()
{
return currentPage >= 0 && getCurrentPage() <= getLastPage();
}
/**
* Gets the current page number
*
* @return current page number
*/
public int getCurrentPage()
{
return currentPage + (zeroBasedPage ? 0 : 1);
}
/**
* Gets the next page number
*
* @return next page number (-1 if no more pages)
*/
public int getNextPage()
{
return getCurrentPage() < getLastPage() ? getCurrentPage() + 1 : - 1;
}
/**
* Gets the previous page number
*
* @return previous page number (-1 if no previous pages)
*/
public int getPreviousPage()
{
return currentPage > 0 ? getCurrentPage() - 1 : - 1;
}
/**
* Gets the first page number
*
* @return first page number
*/
public int getFirstPage()
{
if (totalRows == 0)
return -1;
return zeroBasedPage ? 0 : 1;
}
/**
* Gets the last page number
*
* @return last page number
*/
public int getLastPage()
{
if (totalRows == 0)
return -1;
return getTotalPages() - (zeroBasedPage ? 1 : 0);
}
/**
* Gets the start row within collection for this page
*
* @return start row index
*/
public long getStartRow()
{
if (totalRows == 0)
return -1;
return (currentPage * pageSize) + (zeroBasedRow ? 0 : 1);
}
/**
* Gets the end row within collection for this page
*
* @return end row index
*/
public long getEndRow()
{
if (totalRows == 0)
return -1;
return getStartRow() + Math.min(pageSize, totalRows - (currentPage * pageSize)) - 1;
}
}
/**
* Rows based Cursor
*/
public static class Rows
{
boolean zeroBasedRow;
long totalRows;
long skipRows;
long maxRows;
long pageSize;
/**
* Create a Rows based Cursor
*
* @param totalRows total rows in collection
* @param maxRows maximum number of rows in page
* @param skipRows number of rows to skip (0 - none)
* @param zeroBasedRow true => 0 based, false => 1 based
*/
public Rows(long totalRows, long maxRows, long skipRows, boolean zeroBasedRow)
{
this.zeroBasedRow = zeroBasedRow;
this.totalRows = totalRows;
this.maxRows = maxRows;
this.skipRows = skipRows;
this.pageSize = (maxRows <= 0) ? totalRows - skipRows : maxRows;
}
/**
* Gets the total number of rows
*
* @return total rows
*/
public long getTotalRows()
{
return totalRows;
}
/**
* Gets the number rows skipped
*
* @return skipped row count
*/
public long getSkipRows()
{
return skipRows;
}
/**
* Gets the maximum number of rows to include in this page
*
* @return maximum of numbers
*/
public long getMaxRows()
{
return maxRows;
}
/**
* Is the cursor within range of the total number of rows
*
* @return true => within range of total rows
*/
public boolean isInRange()
{
return skipRows >= 0 && skipRows < totalRows;
}
/**
* Gets the start row within collection for this page
*
* @return start row index
*/
public long getStartRow()
{
if (totalRows == 0)
return -1;
return skipRows + (zeroBasedRow ? 0 : 1);
}
/**
* Gets the end row within collection for this page
*
* @return end row index
*/
public long getEndRow()
{
if (totalRows == 0)
return -1;
return getStartRow() + Math.min(pageSize, totalRows - skipRows) - 1;
}
/**
* Gets the next skip count
*
* @return next skip row
*/
public long getNextSkipRows()
{
return (skipRows + pageSize < totalRows) ? skipRows + pageSize : -1;
}
}
}

View File

@@ -0,0 +1,341 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
*
* 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 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.web.util;
import junit.framework.TestCase;
import org.alfresco.repo.web.util.PagingCursor.Page;
import org.alfresco.repo.web.util.PagingCursor.Rows;
/**
* Test Paged and Row Based Cursors
*
* @author davidc
*/
public class PagingCursorTest extends TestCase
{
protected PagingCursor pageCursor;
@Override
protected void setUp() throws Exception
{
pageCursor = new PagingCursor();
}
public void testZeroBasedBooleans()
{
assertFalse(pageCursor.isZeroBasedPage());
pageCursor.setZeroBasedPage(true);
assertTrue(pageCursor.isZeroBasedPage());
assertTrue(pageCursor.isZeroBasedRow());
pageCursor.setZeroBasedRow(false);
assertFalse(pageCursor.isZeroBasedRow());
}
public void testZeroRowsPageCursor()
{
Page page = pageCursor.createPageCursor(0, 10, 1);
assertNotNull(page);
assertEquals(0, page.getTotalRows());
assertEquals(0, page.getTotalPages());
assertEquals(10, page.getRowsPerPage());
assertFalse(page.isInRange());
assertEquals(1, page.getCurrentPage());
assertEquals(-1, page.getFirstPage());
assertEquals(-1, page.getLastPage());
assertEquals(-1, page.getPreviousPage());
assertEquals(-1, page.getNextPage());
assertEquals(-1, page.getStartRow());
assertEquals(-1, page.getEndRow());
}
public void testOutOfBoundsPageCursor()
{
Page page1 = pageCursor.createPageCursor(1, 1, 1);
assertNotNull(page1);
assertTrue(page1.isInRange());
Page page2 = pageCursor.createPageCursor(1, 1, 2);
assertNotNull(page2);
assertFalse(page2.isInRange());
Page page3 = pageCursor.createPageCursor(1, 2, 1);
assertNotNull(page3);
assertTrue(page3.isInRange());
Page page4 = pageCursor.createPageCursor(10, 2, 5);
assertNotNull(page4);
assertTrue(page4.isInRange());
Page page5 = pageCursor.createPageCursor(10, 2, 6);
assertNotNull(page5);
assertFalse(page5.isInRange());
Page page6 = pageCursor.createPageCursor(11, 2, 5);
assertNotNull(page6);
assertTrue(page6.isInRange());
Page page7 = pageCursor.createPageCursor(11, 2, 6);
assertNotNull(page7);
assertTrue(page7.isInRange());
Page page8 = pageCursor.createPageCursor(11, 2, 0);
assertNotNull(page8);
assertFalse(page8.isInRange());
pageCursor.setZeroBasedPage(true);
Page page10 = pageCursor.createPageCursor(1, 1, 0);
assertNotNull(page10);
assertTrue(page10.isInRange());
Page page11 = pageCursor.createPageCursor(1, 1, 1);
assertNotNull(page11);
assertFalse(page11.isInRange());
Page page12 = pageCursor.createPageCursor(1, 2, 0);
assertNotNull(page12);
assertTrue(page12.isInRange());
Page page13 = pageCursor.createPageCursor(10, 2, 4);
assertNotNull(page13);
assertTrue(page13.isInRange());
Page page14 = pageCursor.createPageCursor(10, 2, 5);
assertNotNull(page14);
assertFalse(page14.isInRange());
Page page15 = pageCursor.createPageCursor(11, 2, 4);
assertNotNull(page15);
assertTrue(page15.isInRange());
Page page16 = pageCursor.createPageCursor(11, 2, 5);
assertNotNull(page16);
assertTrue(page16.isInRange());
Page page17 = pageCursor.createPageCursor(11, 2, -1);
assertNotNull(page17);
assertFalse(page17.isInRange());
}
public void testTotalPageCursor()
{
Page page1 = pageCursor.createPageCursor(10, 1, 1);
assertEquals(10, page1.getTotalRows());
assertEquals(10, page1.getTotalPages());
Page page2 = pageCursor.createPageCursor(10, 10, 1);
assertEquals(10, page2.getTotalRows());
assertEquals(1, page2.getTotalPages());
Page page3 = pageCursor.createPageCursor(9, 10, 1);
assertEquals(9, page3.getTotalRows());
assertEquals(1, page3.getTotalPages());
Page page4 = pageCursor.createPageCursor(11, 10, 1);
assertEquals(11, page4.getTotalRows());
assertEquals(2, page4.getTotalPages());
Page page5 = pageCursor.createPageCursor(20, 10, 1);
assertEquals(20, page5.getTotalRows());
assertEquals(2, page5.getTotalPages());
}
public void testPagingPageCursor()
{
Page page1 = pageCursor.createPageCursor(10, 1, 1);
assertEquals(1, page1.getCurrentPage());
assertEquals(1, page1.getFirstPage());
assertEquals(10, page1.getLastPage());
assertEquals(-1, page1.getPreviousPage());
assertEquals(2, page1.getNextPage());
assertEquals(0, page1.getStartRow());
assertEquals(0, page1.getEndRow());
Page page2 = pageCursor.createPageCursor(10, 1, 2);
assertEquals(2, page2.getCurrentPage());
assertEquals(1, page2.getFirstPage());
assertEquals(10, page2.getLastPage());
assertEquals(1, page2.getPreviousPage());
assertEquals(3, page2.getNextPage());
assertEquals(1, page2.getStartRow());
assertEquals(1, page2.getEndRow());
Page page3 = pageCursor.createPageCursor(10, 10, 1);
assertEquals(1, page3.getCurrentPage());
assertEquals(1, page3.getFirstPage());
assertEquals(1, page3.getLastPage());
assertEquals(-1, page3.getPreviousPage());
assertEquals(-1, page3.getNextPage());
assertEquals(0, page3.getStartRow());
assertEquals(9, page3.getEndRow());
Page page4 = pageCursor.createPageCursor(9, 10, 1);
assertEquals(1, page4.getCurrentPage());
assertEquals(1, page4.getFirstPage());
assertEquals(1, page4.getLastPage());
assertEquals(-1, page4.getPreviousPage());
assertEquals(-1, page4.getNextPage());
assertEquals(0, page4.getStartRow());
assertEquals(8, page4.getEndRow());
Page page5 = pageCursor.createPageCursor(11, 10, 1);
assertEquals(1, page5.getCurrentPage());
assertEquals(1, page5.getFirstPage());
assertEquals(2, page5.getLastPage());
assertEquals(-1, page5.getPreviousPage());
assertEquals(2, page5.getNextPage());
assertEquals(0, page5.getStartRow());
assertEquals(9, page5.getEndRow());
Page page6 = pageCursor.createPageCursor(20, 10, 1);
assertEquals(1, page6.getCurrentPage());
assertEquals(1, page6.getFirstPage());
assertEquals(2, page6.getLastPage());
assertEquals(-1, page6.getPreviousPage());
assertEquals(2, page6.getNextPage());
assertEquals(0, page6.getStartRow());
assertEquals(9, page6.getEndRow());
Page page7 = pageCursor.createPageCursor(20, 10, 2);
assertEquals(2, page7.getCurrentPage());
assertEquals(1, page7.getFirstPage());
assertEquals(2, page7.getLastPage());
assertEquals(1, page7.getPreviousPage());
assertEquals(-1, page7.getNextPage());
assertEquals(10, page7.getStartRow());
assertEquals(19, page7.getEndRow());
Page page8 = pageCursor.createPageCursor(11, 10, 2);
assertEquals(2, page8.getCurrentPage());
assertEquals(1, page8.getFirstPage());
assertEquals(2, page8.getLastPage());
assertEquals(1, page8.getPreviousPage());
assertEquals(-1, page8.getNextPage());
assertEquals(10, page8.getStartRow());
assertEquals(10, page8.getEndRow());
}
public void testUnlimitedPageCursor()
{
Page page1 = pageCursor.createPageCursor(100, 0, 1);
assertTrue(page1.isInRange());
assertEquals(1, page1.getCurrentPage());
assertEquals(1, page1.getFirstPage());
assertEquals(1, page1.getLastPage());
assertEquals(-1, page1.getPreviousPage());
assertEquals(-1, page1.getNextPage());
assertEquals(0, page1.getStartRow());
assertEquals(99, page1.getEndRow());
Page page2 = pageCursor.createPageCursor(100, 0, 2);
assertFalse(page2.isInRange());
}
public void testScrollPageCursor()
{
int count = 0;
long[] coll = new long[100];
Page page = pageCursor.createPageCursor(100, 10, 1);
while (page.isInRange())
{
for (long i = page.getStartRow(); i <= page.getEndRow(); i++)
{
coll[(int)i] = i;
count++;
}
page = pageCursor.createPageCursor(100, 10, page.getNextPage());
}
assertEquals(100, count);
for (int test = 0; test < count; test++)
{
assertEquals(test, coll[test]);
}
}
public void testZeroRowsIndexCursor()
{
Rows rows = pageCursor.createRowsCursor(0, 10, 0);
assertNotNull(rows);
assertEquals(0, rows.getTotalRows());
assertFalse(rows.isInRange());
assertEquals(10, rows.getMaxRows());
assertEquals(-1, rows.getStartRow());
assertEquals(-1, rows.getEndRow());
assertEquals(-1, rows.getNextSkipRows());
}
public void testOutOfBoundsRowsCursor()
{
Rows rows1 = pageCursor.createRowsCursor(1, 1, 0);
assertNotNull(rows1);
assertTrue(rows1.isInRange());
Rows rows2 = pageCursor.createRowsCursor(1, 1, 1);
assertNotNull(rows2);
assertFalse(rows2.isInRange());
Rows rows3 = pageCursor.createRowsCursor(1, -1, 0);
assertNotNull(rows3);
assertTrue(rows3.isInRange());
}
public void testTotalRowsCursor()
{
Rows rows1 = pageCursor.createRowsCursor(10, 1, 1);
assertEquals(10, rows1.getTotalRows());
}
public void testPagingRowsCursor()
{
Rows rows1 = pageCursor.createRowsCursor(10, 1, 0);
assertEquals(0, rows1.getStartRow());
assertEquals(0, rows1.getEndRow());
assertEquals(1, rows1.getNextSkipRows());
Rows rows2 = pageCursor.createRowsCursor(10, 7, 0);
assertEquals(0, rows2.getStartRow());
assertEquals(6, rows2.getEndRow());
assertEquals(7, rows2.getNextSkipRows());
Rows rows3 = pageCursor.createRowsCursor(10, 7, 7);
assertEquals(7, rows3.getStartRow());
assertEquals(9, rows3.getEndRow());
assertEquals(-1, rows3.getNextSkipRows());
Rows rows4 = pageCursor.createRowsCursor(10, 10, 0);
assertEquals(0, rows4.getStartRow());
assertEquals(9, rows4.getEndRow());
assertEquals(-1, rows4.getNextSkipRows());
Rows rows5 = pageCursor.createRowsCursor(10, 11, 0);
assertEquals(0, rows5.getStartRow());
assertEquals(9, rows5.getEndRow());
assertEquals(-1, rows5.getNextSkipRows());
}
public void testUnlimitedRowsCursor()
{
Rows rows1 = pageCursor.createRowsCursor(100, 0, 0);
assertTrue(rows1.isInRange());
assertEquals(0, rows1.getStartRow());
assertEquals(99, rows1.getEndRow());
assertEquals(-1, rows1.getNextSkipRows());
}
public void testScrollRowsCursor()
{
int count = 0;
long[] coll = new long[100];
Rows rows = pageCursor.createRowsCursor(100, 10, 0);
while (rows.isInRange())
{
for (long i = rows.getStartRow(); i <= rows.getEndRow(); i++)
{
coll[(int)i] = i;
count++;
}
rows = pageCursor.createRowsCursor(100, 10, rows.getNextSkipRows());
}
assertEquals(100, count);
for (int test = 0; test < count; test++)
{
assertEquals(test, coll[test]);
}
}
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
*
* 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 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.web.util.paging;
import java.io.Serializable;
/**
* Implementation of Paged Results based on an array result set.
*
* @author davidc
*/
public class ArrayPagedResults implements PagedResults, Serializable
{
private static final long serialVersionUID = 5905699888354619269L;
private Object[] results;
private Cursor cursor;
/**
* Construct
*
* @param results results for the page within cursor
* @param cursor the cursor
*/
/*Package*/ ArrayPagedResults(Object[] results, Cursor cursor)
{
this.results = results;
this.cursor = cursor;
}
/* (non-Javadoc)
* @see org.alfresco.repo.web.util.paging.PagedResults#getResults()
*/
public Object[] getResults()
{
return results;
}
/* (non-Javadoc)
* @see org.alfresco.repo.web.util.paging.PagedResults#getCursor()
*/
public Cursor getCursor()
{
return cursor;
}
}

View File

@@ -0,0 +1,154 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
*
* 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 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.web.util.paging;
/**
* Cursor - Allows for scrolling through a row set.
*
* @author davidc
*/
public interface Cursor
{
/**
* Gets the page type
*
* @return page type
*/
public String getPageType();
/**
* Gets the page size
*
* @return page size
*/
int getPageSize();
/**
* Gets total number of pages
*
* @return total number of pages
*/
int getTotalPages();
/**
* Gets total rows
*
* @return total rows
*/
int getTotalRows();
/**
* Gets the current page number
*
* @return current page number
*/
int getCurrentPage();
/**
* Gets the first page number
*
* @return first page number
*/
int getFirstPage();
/**
* Gets the last page number
*
* @return last page number
*/
int getLastPage();
/**
* Gets the next page number
*
* @return next page number (-1 if no more pages)
*/
int getNextPage();
/**
* Gets the previous page number
*
* @return previous page number (-1 if no previous pages)
*/
int getPrevPage();
/**
* Is the page within range of the result set
*
* @return true => page is within range
*/
boolean isInRange();
/**
* Is there a known first page?
*
* @return true => getFirstPage() will succeed
*/
boolean getHasFirstPage();
/**
* Is there a known last page?
*
* @return true => getLastPage() will succeed
*/
boolean getHasLastPage();
/**
* Is there a known next page?
*
* @return true => getNextPage() will succeed
*/
boolean getHasNextPage();
/**
* Is there a known prev page?
*
* @return true => getPrevPage() will succeed
*/
boolean getHasPrevPage();
/**
* Gets the start row within result set for this page
*
* @return start row index
*/
int getStartRow();
/**
* Gets the end row within result set for this page
*
* @return end row index
*/
int getEndRow();
/**
* Gets the count of rows within result set for this page
*
* @return row count
*/
int getRowCount();
}

View File

@@ -0,0 +1,96 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
*
* 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 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.web.util.paging;
/**
* A Page within a Cursor.
*
* @author davidc
*/
public class Page
{
Paging.PageType pageType;
boolean zeroBasedIdx;
int startIdx;
int pageSize;
/**
* Construct
*
* @param pageType Page or Window
* @param zeroBasedIdx true => start index from 0
* @param startIdx start index
* @param pageSize page size
*/
/*package*/ Page(Paging.PageType pageType, boolean zeroBasedIdx, int startIdx, int pageSize)
{
this.pageType = pageType;
this.zeroBasedIdx = zeroBasedIdx;
this.startIdx = startIdx;
this.pageSize = pageSize;
}
/**
* Gets the Page Type
*
* @return page type
*/
/*package*/ Paging.PageType getType()
{
return pageType;
}
/**
* Gets the page number
*
* @return page number
*/
public int getNumber()
{
return startIdx;
}
/**
* Gets the page size
*
* @return page size
*/
public int getSize()
{
return pageSize;
}
/**
* Is zero based page index
*
* @return true => page number starts from zero
*/
public boolean isZeroBasedIdx()
{
return zeroBasedIdx;
}
}

View File

@@ -0,0 +1,224 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
*
* 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 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.web.util.paging;
import java.io.Serializable;
import org.alfresco.repo.web.util.paging.Paging.PageType;
/**
* Implementation of cursor based on notion of a Page.
*
* @author davidc
*/
public class PagedCursor implements Cursor, Serializable
{
private static final long serialVersionUID = -1041155610387669590L;
private boolean zeroBasedPage;
private boolean zeroBasedRow;
private int totalRows;
private int pageSize;
private int rowsPerPage;
private int page;
/**
* Construct
*
* @param zeroBasedRow true => row index starts at zero
* @param totalRows total number of rows (-1 for don't know)
* @param zeroBasedPage true => page number starts at zero
* @param page page number
* @param pageSize page size
*/
/*package*/ PagedCursor(boolean zeroBasedRow, int totalRows, boolean zeroBasedPage, int page, int pageSize)
{
this.zeroBasedRow = zeroBasedRow;
this.totalRows = totalRows;
this.zeroBasedPage = zeroBasedPage;
this.page = (zeroBasedPage) ? page : page - 1;
this.pageSize = pageSize;
this.rowsPerPage = (pageSize <=0) ? totalRows : pageSize;
}
/* (non-Javadoc)
* @see org.alfresco.repo.web.util.paging.Cursor#getPageType()
*/
public String getPageType()
{
return PageType.PAGE.toString();
}
/* (non-Javadoc)
* @see org.alfresco.repo.web.util.paging.Cursor#getPageSize()
*/
public int getPageSize()
{
return pageSize;
}
/* (non-Javadoc)
* @see org.alfresco.repo.web.util.paging.Cursor#getTotalPages()
*/
public int getTotalPages()
{
if (totalRows <= 0)
return 0;
int totalPages = (int)(totalRows / rowsPerPage);
totalPages += (totalRows % rowsPerPage != 0) ? 1 : 0;
return totalPages;
}
/* (non-Javadoc)
* @see org.alfresco.repo.web.util.paging.Cursor#getTotalRows()
*/
public int getTotalRows()
{
return totalRows;
}
/* (non-Javadoc)
* @see org.alfresco.repo.web.util.paging.Cursor#getCurrentPage()
*/
public int getCurrentPage()
{
return page + (zeroBasedPage ? 0 : 1);
}
/* (non-Javadoc)
* @see org.alfresco.repo.web.util.paging.Cursor#getFirstPage()
*/
public int getFirstPage()
{
if (totalRows <= 0)
return -1;
return zeroBasedPage ? 0 : 1;
}
/* (non-Javadoc)
* @see org.alfresco.repo.web.util.paging.Cursor#getLastPage()
*/
public int getLastPage()
{
if (totalRows <= 0)
return -1;
return getTotalPages() - (zeroBasedPage ? 1 : 0);
}
/* (non-Javadoc)
* @see org.alfresco.repo.web.util.paging.Cursor#getNextPage()
*/
public int getNextPage()
{
return getCurrentPage() < getLastPage() ? getCurrentPage() + 1 : - 1;
}
/* (non-Javadoc)
* @see org.alfresco.repo.web.util.paging.Cursor#getPrevPage()
*/
public int getPrevPage()
{
return page > 0 ? getCurrentPage() - 1 : - 1;
}
/* (non-Javadoc)
* @see org.alfresco.repo.web.util.paging.Cursor#isInRange()
*/
public boolean isInRange()
{
return page >= 0 && getCurrentPage() <= getLastPage();
}
/* (non-Javadoc)
* @see org.alfresco.repo.web.util.paging.Cursor#hasFirstPage()
*/
public boolean getHasFirstPage()
{
return getFirstPage() != -1;
}
/* (non-Javadoc)
* @see org.alfresco.repo.web.util.paging.Cursor#hasLastPage()
*/
public boolean getHasLastPage()
{
return getLastPage() != -1;
}
/* (non-Javadoc)
* @see org.alfresco.repo.web.util.paging.Cursor#hasNextPage()
*/
public boolean getHasNextPage()
{
return getNextPage() != -1;
}
/* (non-Javadoc)
* @see org.alfresco.repo.web.util.paging.Cursor#hasPrevPage()
*/
public boolean getHasPrevPage()
{
return getPrevPage() != -1;
}
/* (non-Javadoc)
* @see org.alfresco.repo.web.util.paging.Cursor#getStartRow()
*/
public int getStartRow()
{
if (totalRows <= 0)
return 0;
return (page * rowsPerPage) + (zeroBasedRow ? 0 : 1);
}
/* (non-Javadoc)
* @see org.alfresco.repo.web.util.paging.Cursor#getEndRow()
*/
public int getEndRow()
{
if (totalRows <= 0)
return -1;
return getStartRow() + Math.min(rowsPerPage, totalRows - (page * rowsPerPage)) - 1;
}
/* (non-Javadoc)
* @see org.alfresco.repo.web.util.paging.Cursor#getRowCount()
*/
public int getRowCount()
{
if (totalRows <= 0)
return 0;
return getEndRow() - getStartRow() + 1;
}
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
*
* 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 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.web.util.paging;
/**
* A Paged Result Set
*
* @author davidc
*/
public interface PagedResults
{
/**
* An array of the results for the given page within the cursor
* @return the paged results
*/
Object[] getResults();
/**
* Gets the cursor
*
* @return cursor
*/
Cursor getCursor();
}

View File

@@ -0,0 +1,193 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
*
* 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 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.web.util.paging;
/**
* Paging. A utility for maintaining paged indexes for a collection of N items.
*
* There are two types of cursor:
*
* a) Paged
*
* This type of cursor is driven from a page number and page size. Random access within
* the collection is possible by jumping straight to a page. A simple scroll through
* the collection is supported by iterating through each next page.
*
* b) Windowed
*
* This type of cursor is driven from a skip row count and maximum number of rows. Random
* access is not supported. The collection of items is simply scrolled through from
* start to end by iterating through each next set of rows.
*
* In either case, a paging cursor provides a start row and end row which may be used
* to extract the items for the page from the collection of N items.
*
* A zero (or less) page size or row maximum means "unlimited".
*
* Zero or one based Page and Rows indexes are supported. By default, Pages are 1 based and
* Rows are 0 based.
*
* At any time, -1 is returned to represent "out of range" i.e. for next, previous, last page.
*
* Pseudo-code for traversing through a collection of N items (10 at a time):
*
* Paging paging = new Paging();
* Cursor page = paging.createCursor(N, paging.createPage(1, 10));
* while (page.isInRange())
* {
* for (long i = page.getStartRow(); i <= page.getEndRow(); i++)
* {
* ...collection[i]...
* }
* page = paging.createCursor(N, paging.createPage(page.getNextPage(), page.getPageSize());
* }
*
* Cursor window = paging.createCursor(N, paging.createWindow(0, 10));
* while (window.isInRange())
* {
* for (long i = window.getStartRow(); i <= window.getEndRow(); i++)
* {
* ...collection[i]...
* }
* window = paging.createCursor(N, paging.createWindow(window.getNextPage(), window.getPageSize());
* }
*
* @author davidc
*/
public class Paging
{
public enum PageType
{
PAGE,
WINDOW
};
boolean zeroBasedPage = false;
boolean zeroBasedRow = true;
/**
* Sets zero based page index
*
* Note: scoped to this paging cursor instance
*
* @param zeroBasedPage true => 0 based, false => 1 based
*/
public void setZeroBasedPage(boolean zeroBasedPage)
{
this.zeroBasedPage = zeroBasedPage;
}
/**
* Is zero based page index?
*
* Note: scoped to this paging cursor instance
*
* @return true => 0 based, false => 1 based
*/
public boolean isZeroBasedPage()
{
return zeroBasedPage;
}
/**
* Sets zero based row index
*
* Note: scoped to this paging cursor instance
*
* @param zeroBasedRow true => 0 based, false => 1 based
*/
public void setZeroBasedRow(boolean zeroBasedRow)
{
this.zeroBasedRow = zeroBasedRow;
}
/**
* Is zero based row index?
*
* Note: scoped to this paging cursor instance
*
* @return true => 0 based, false => 1 based
*/
public boolean isZeroBasedRow()
{
return zeroBasedRow;
}
/**
* Create a Page
*
* @param pageNumber page number
* @param pageSize page size
* @return the page
*/
public Page createPage(int pageNumber, int pageSize)
{
return new Page(PageType.PAGE, zeroBasedPage, pageNumber, pageSize);
}
/**
* Create a Window
* @param skipRows number of rows to skip
* @param maxRows maximum number of rows in window
* @return the window
*/
public Page createWindow(int skipRows, int maxRows)
{
return new Page(PageType.WINDOW, zeroBasedRow, skipRows, maxRows);
}
/**
* Create a Cursor
*
* @param totalRows total number of rows in cursor (< 0 for don't know)
* @param page the page / window within cursor
* @return the cursor
*/
public Cursor createCursor(int totalRows, Page page)
{
if (page.getType() == PageType.PAGE)
{
return new PagedCursor(zeroBasedRow, totalRows, page.zeroBasedIdx, page.startIdx, page.pageSize);
}
else if (page.getType() == PageType.WINDOW)
{
return new WindowedCursor(zeroBasedRow, totalRows, page.startIdx, page.pageSize);
}
return null;
}
/**
* Create a Paged Result Set
*
* @param results the results for the page within the cursor
* @param cursor the cursor
* @return the paged result set
*/
public PagedResults createPagedResults(Object[] results, Cursor cursor)
{
return new ArrayPagedResults(results, cursor);
}
}

View File

@@ -0,0 +1,371 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
*
* 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 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.web.util.paging;
import junit.framework.TestCase;
/**
* Test Paged and Window Based Cursors
*
* @author davidc
*/
public class PagingTest extends TestCase
{
protected Paging paging;
@Override
protected void setUp() throws Exception
{
paging = new Paging();
}
public void testZeroBasedBooleans()
{
assertFalse(paging.isZeroBasedPage());
paging.setZeroBasedPage(true);
assertTrue(paging.isZeroBasedPage());
assertTrue(paging.isZeroBasedRow());
paging.setZeroBasedRow(false);
assertFalse(paging.isZeroBasedRow());
}
public void testCreatePage()
{
Page page = paging.createPage(1, 10);
assertNotNull(page);
assertEquals(Paging.PageType.PAGE, page.getType());
assertFalse(page.isZeroBasedIdx());
assertEquals(1, page.getNumber());
assertEquals(10, page.getSize());
Page window = paging.createWindow(1, 10);
assertNotNull(window);
assertEquals(Paging.PageType.WINDOW, window.getType());
assertTrue(window.isZeroBasedIdx());
assertEquals(1, window.getNumber());
assertEquals(10, window.getSize());
}
public void testZeroRowsPage()
{
Cursor cursor = paging.createCursor(0, paging.createPage(1, 10));
assertNotNull(cursor);
assertEquals(0, cursor.getTotalRows());
assertEquals(0, cursor.getTotalPages());
assertEquals(10, cursor.getPageSize());
assertFalse(cursor.isInRange());
assertEquals(1, cursor.getCurrentPage());
assertEquals(-1, cursor.getFirstPage());
assertEquals(-1, cursor.getLastPage());
assertEquals(-1, cursor.getPrevPage());
assertEquals(-1, cursor.getNextPage());
assertEquals(0, cursor.getStartRow());
assertEquals(-1, cursor.getEndRow());
assertEquals(0, cursor.getRowCount());
}
public void testOutOfBoundsPage()
{
Cursor cursor1 = paging.createCursor(1, paging.createPage(1, 1));
assertNotNull(cursor1);
assertTrue(cursor1.isInRange());
Cursor cursor2 = paging.createCursor(1, paging.createPage(2, 1));
assertNotNull(cursor2);
assertFalse(cursor2.isInRange());
Cursor cursor3 = paging.createCursor(1, paging.createPage(1, 2));
assertNotNull(cursor3);
assertTrue(cursor3.isInRange());
Cursor cursor4 = paging.createCursor(10, paging.createPage(5, 2));
assertNotNull(cursor4);
assertTrue(cursor4.isInRange());
Cursor cursor5 = paging.createCursor(10, paging.createPage(6, 2));
assertNotNull(cursor5);
assertFalse(cursor5.isInRange());
Cursor cursor6 = paging.createCursor(11, paging.createPage(5, 2));
assertNotNull(cursor6);
assertTrue(cursor6.isInRange());
Cursor cursor7 = paging.createCursor(11, paging.createPage(6, 2));
assertNotNull(cursor7);
assertTrue(cursor7.isInRange());
Cursor cursor8 = paging.createCursor(11, paging.createPage(0, 2));
assertNotNull(cursor8);
assertFalse(cursor8.isInRange());
paging.setZeroBasedPage(true);
Cursor cursor10 = paging.createCursor(1, paging.createPage(0, 1));
assertNotNull(cursor10);
assertTrue(cursor10.isInRange());
Cursor cursor11 = paging.createCursor(1, paging.createPage(1, 1));
assertNotNull(cursor11);
assertFalse(cursor11.isInRange());
Cursor cursor12 = paging.createCursor(1, paging.createPage(0, 2));
assertNotNull(cursor12);
assertTrue(cursor12.isInRange());
Cursor cursor13 = paging.createCursor(10, paging.createPage(4, 2));
assertNotNull(cursor13);
assertTrue(cursor13.isInRange());
Cursor cursor14 = paging.createCursor(10, paging.createPage(5, 2));
assertNotNull(cursor14);
assertFalse(cursor14.isInRange());
Cursor cursor15 = paging.createCursor(11, paging.createPage(4, 2));
assertNotNull(cursor15);
assertTrue(cursor15.isInRange());
Cursor cursor16 = paging.createCursor(11, paging.createPage(5, 2));
assertNotNull(cursor16);
assertTrue(cursor16.isInRange());
Cursor cursor17 = paging.createCursor(11, paging.createPage(-1, 2));
assertNotNull(cursor17);
assertFalse(cursor17.isInRange());
}
public void testTotalPage()
{
Cursor cursor1 = paging.createCursor(10, paging.createPage(1, 1));
assertEquals(10, cursor1.getTotalRows());
assertEquals(10, cursor1.getTotalPages());
Cursor cursor2 = paging.createCursor(10, paging.createPage(1, 10));
assertEquals(10, cursor2.getTotalRows());
assertEquals(1, cursor2.getTotalPages());
Cursor cursor3 = paging.createCursor(9, paging.createPage(1, 10));
assertEquals(9, cursor3.getTotalRows());
assertEquals(1, cursor3.getTotalPages());
Cursor cursor4 = paging.createCursor(11, paging.createPage(1, 10));
assertEquals(11, cursor4.getTotalRows());
assertEquals(2, cursor4.getTotalPages());
Cursor cursor5 = paging.createCursor(20, paging.createPage(1, 10));
assertEquals(20, cursor5.getTotalRows());
assertEquals(2, cursor5.getTotalPages());
}
public void testCursorPage()
{
Cursor cursor1 = paging.createCursor(10, paging.createPage(1, 1));
assertEquals(1, cursor1.getCurrentPage());
assertEquals(1, cursor1.getFirstPage());
assertEquals(10, cursor1.getLastPage());
assertEquals(-1, cursor1.getPrevPage());
assertEquals(2, cursor1.getNextPage());
assertEquals(0, cursor1.getStartRow());
assertEquals(0, cursor1.getEndRow());
assertEquals(1, cursor1.getRowCount());
Cursor cursor2 = paging.createCursor(10, paging.createPage(2, 1));
assertEquals(2, cursor2.getCurrentPage());
assertEquals(1, cursor2.getFirstPage());
assertEquals(10, cursor2.getLastPage());
assertEquals(1, cursor2.getPrevPage());
assertEquals(3, cursor2.getNextPage());
assertEquals(1, cursor2.getStartRow());
assertEquals(1, cursor2.getEndRow());
assertEquals(1, cursor2.getRowCount());
Cursor cursor3 = paging.createCursor(10, paging.createPage(1, 10));
assertEquals(1, cursor3.getCurrentPage());
assertEquals(1, cursor3.getFirstPage());
assertEquals(1, cursor3.getLastPage());
assertEquals(-1, cursor3.getPrevPage());
assertEquals(-1, cursor3.getNextPage());
assertEquals(0, cursor3.getStartRow());
assertEquals(9, cursor3.getEndRow());
assertEquals(10, cursor3.getRowCount());
Cursor cursor4 = paging.createCursor(9, paging.createPage(1, 10));
assertEquals(1, cursor4.getCurrentPage());
assertEquals(1, cursor4.getFirstPage());
assertEquals(1, cursor4.getLastPage());
assertEquals(-1, cursor4.getPrevPage());
assertEquals(-1, cursor4.getNextPage());
assertEquals(0, cursor4.getStartRow());
assertEquals(8, cursor4.getEndRow());
assertEquals(9, cursor4.getRowCount());
Cursor cursor5 = paging.createCursor(11, paging.createPage(1, 10));
assertEquals(1, cursor5.getCurrentPage());
assertEquals(1, cursor5.getFirstPage());
assertEquals(2, cursor5.getLastPage());
assertEquals(-1, cursor5.getPrevPage());
assertEquals(2, cursor5.getNextPage());
assertEquals(0, cursor5.getStartRow());
assertEquals(9, cursor5.getEndRow());
assertEquals(10, cursor5.getRowCount());
Cursor cursor6 = paging.createCursor(20, paging.createPage(1, 10));
assertEquals(1, cursor6.getCurrentPage());
assertEquals(1, cursor6.getFirstPage());
assertEquals(2, cursor6.getLastPage());
assertEquals(-1, cursor6.getPrevPage());
assertEquals(2, cursor6.getNextPage());
assertEquals(0, cursor6.getStartRow());
assertEquals(9, cursor6.getEndRow());
assertEquals(10, cursor6.getRowCount());
Cursor cursor7 = paging.createCursor(20, paging.createPage(2, 10));
assertEquals(2, cursor7.getCurrentPage());
assertEquals(1, cursor7.getFirstPage());
assertEquals(2, cursor7.getLastPage());
assertEquals(1, cursor7.getPrevPage());
assertEquals(-1, cursor7.getNextPage());
assertEquals(10, cursor7.getStartRow());
assertEquals(19, cursor7.getEndRow());
assertEquals(10, cursor7.getRowCount());
Cursor cursor8 = paging.createCursor(11, paging.createPage(2, 10));
assertEquals(2, cursor8.getCurrentPage());
assertEquals(1, cursor8.getFirstPage());
assertEquals(2, cursor8.getLastPage());
assertEquals(1, cursor8.getPrevPage());
assertEquals(-1, cursor8.getNextPage());
assertEquals(10, cursor8.getStartRow());
assertEquals(10, cursor8.getEndRow());
assertEquals(1, cursor8.getRowCount());
}
public void testUnlimitedPage()
{
Cursor cursor1 = paging.createCursor(100, paging.createPage(1, 0));
assertTrue(cursor1.isInRange());
assertEquals(1, cursor1.getCurrentPage());
assertEquals(1, cursor1.getFirstPage());
assertEquals(1, cursor1.getLastPage());
assertEquals(-1, cursor1.getPrevPage());
assertEquals(-1, cursor1.getNextPage());
assertEquals(0, cursor1.getStartRow());
assertEquals(99, cursor1.getEndRow());
Cursor cursor2 = paging.createCursor(100, paging.createPage(2, 0));
assertFalse(cursor2.isInRange());
}
public void testScrollPage()
{
int count = 0;
long[] coll = new long[100];
Cursor cursor = paging.createCursor(coll.length, paging.createPage(1, 10));
while (cursor.isInRange())
{
for (long i = cursor.getStartRow(); i <= cursor.getEndRow(); i++)
{
coll[(int)i] = i;
count++;
}
cursor = paging.createCursor(coll.length, paging.createPage(cursor.getNextPage(), cursor.getPageSize()));
}
assertEquals(100, count);
for (int test = 0; test < count; test++)
{
assertEquals(test, coll[test]);
}
}
public void testZeroRowsWindow()
{
Cursor rows = paging.createCursor(0, paging.createWindow(0, 10));
assertNotNull(rows);
assertEquals(0, rows.getTotalRows());
assertFalse(rows.isInRange());
assertEquals(10, rows.getPageSize());
assertEquals(0, rows.getStartRow());
assertEquals(-1, rows.getEndRow());
assertEquals(0, rows.getRowCount());
assertEquals(-1, rows.getNextPage());
}
public void testOutOfBoundsWindow()
{
Cursor cursor1 = paging.createCursor(1, paging.createWindow(0, 1));
assertNotNull(cursor1);
assertTrue(cursor1.isInRange());
Cursor cursor2 = paging.createCursor(1, paging.createWindow(1, 1));
assertNotNull(cursor2);
assertFalse(cursor2.isInRange());
Cursor cursor3 = paging.createCursor(1, paging.createWindow(0, -1));
assertNotNull(cursor3);
assertTrue(cursor3.isInRange());
}
public void testTotalWindow()
{
Cursor cursor1 = paging.createCursor(10, paging.createWindow(1, 1));
assertEquals(10, cursor1.getTotalRows());
}
public void testCursorWindow()
{
Cursor cursor1 = paging.createCursor(10, paging.createWindow(0, 1));
assertEquals(0, cursor1.getStartRow());
assertEquals(0, cursor1.getEndRow());
assertEquals(1, cursor1.getRowCount());
assertEquals(1, cursor1.getNextPage());
Cursor cursor2 = paging.createCursor(10, paging.createWindow(0, 7));
assertEquals(0, cursor2.getStartRow());
assertEquals(6, cursor2.getEndRow());
assertEquals(7, cursor2.getRowCount());
assertEquals(7, cursor2.getNextPage());
Cursor cursor3 = paging.createCursor(10, paging.createWindow(7, 7));
assertEquals(7, cursor3.getStartRow());
assertEquals(9, cursor3.getEndRow());
assertEquals(3, cursor3.getRowCount());
assertEquals(-1, cursor3.getNextPage());
Cursor cursor4 = paging.createCursor(10, paging.createWindow(0, 10));
assertEquals(0, cursor4.getStartRow());
assertEquals(9, cursor4.getEndRow());
assertEquals(10, cursor4.getRowCount());
assertEquals(-1, cursor4.getNextPage());
Cursor cursor5 = paging.createCursor(10, paging.createWindow(0, 11));
assertEquals(0, cursor5.getStartRow());
assertEquals(9, cursor5.getEndRow());
assertEquals(10, cursor5.getRowCount());
assertEquals(-1, cursor5.getNextPage());
}
public void testUnlimitedWindow()
{
Cursor cursor1 = paging.createCursor(100, paging.createWindow(0, 0));
assertTrue(cursor1.isInRange());
assertEquals(0, cursor1.getStartRow());
assertEquals(99, cursor1.getEndRow());
assertEquals(100, cursor1.getRowCount());
assertEquals(-1, cursor1.getNextPage());
}
public void testScrollWindow()
{
int count = 0;
long[] coll = new long[100];
Cursor cursor = paging.createCursor(coll.length, paging.createWindow(0, 10));
while (cursor.isInRange())
{
for (long i = cursor.getStartRow(); i <= cursor.getEndRow(); i++)
{
coll[(int)i] = i;
count++;
}
cursor = paging.createCursor(coll.length, paging.createWindow(cursor.getNextPage(), cursor.getPageSize()));
}
assertEquals(100, count);
for (int test = 0; test < count; test++)
{
assertEquals(test, coll[test]);
}
}
}

View File

@@ -0,0 +1,212 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
*
* 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 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.web.util.paging;
import java.io.Serializable;
import org.alfresco.repo.web.util.paging.Paging.PageType;
/**
* Cursor implementation based on notion of a Window.
*
* @author davidc
*/
public class WindowedCursor implements Cursor, Serializable
{
private static final long serialVersionUID = 521131539938276413L;
private boolean zeroBasedRow;
private int totalRows;
private int skipRows;
private int maxRows;
private int rowsPerPage;
/**
* Construct
*
* @param zeroBasedRow true => 0 based, false => 1 based
* @param totalRows total rows in collection
* @param skipRows number of rows to skip (0 - none)
* @param maxRows maximum number of rows in window
*/
WindowedCursor(boolean zeroBasedRow, int totalRows, int skipRows, int maxRows)
{
this.zeroBasedRow = zeroBasedRow;
this.totalRows = totalRows;
this.skipRows = skipRows;
this.maxRows = maxRows;
this.rowsPerPage = (maxRows <= 0) ? totalRows - skipRows : maxRows;
}
/* (non-Javadoc)
* @see org.alfresco.repo.web.util.paging.Cursor#getPageType()
*/
public String getPageType()
{
return PageType.WINDOW.toString();
}
/* (non-Javadoc)
* @see org.alfresco.repo.web.util.paging.Cursor#getPageSize()
*/
public int getPageSize()
{
return maxRows;
}
/* (non-Javadoc)
* @see org.alfresco.repo.web.util.paging.Cursor#getTotalPages()
*/
public int getTotalPages()
{
return -1;
}
/* (non-Javadoc)
* @see org.alfresco.repo.web.util.paging.Cursor#getTotalRows()
*/
public int getTotalRows()
{
return totalRows;
}
/* (non-Javadoc)
* @see org.alfresco.repo.web.util.paging.Cursor#getCurrentPage()
*/
public int getCurrentPage()
{
return skipRows;
}
/* (non-Javadoc)
* @see org.alfresco.repo.web.util.paging.Cursor#getFirstPage()
*/
public int getFirstPage()
{
if (totalRows <=0)
return -1;
return zeroBasedRow ? 0 : 1;
}
/* (non-Javadoc)
* @see org.alfresco.repo.web.util.paging.Cursor#getLastPage()
*/
public int getLastPage()
{
return -1;
}
/* (non-Javadoc)
* @see org.alfresco.repo.web.util.paging.Cursor#getNextPage()
*/
public int getNextPage()
{
return (skipRows + rowsPerPage < totalRows) ? skipRows + maxRows : -1;
}
/* (non-Javadoc)
* @see org.alfresco.repo.web.util.paging.Cursor#getPrevPage()
*/
public int getPrevPage()
{
return (skipRows > 0) ? Math.max(0, skipRows - maxRows) : -1;
}
/* (non-Javadoc)
* @see org.alfresco.repo.web.util.paging.Cursor#isInRange()
*/
public boolean isInRange()
{
return skipRows >= 0 && skipRows < totalRows;
}
/* (non-Javadoc)
* @see org.alfresco.repo.web.util.paging.Cursor#hasFirstPage()
*/
public boolean getHasFirstPage()
{
return getFirstPage() != -1;
}
/* (non-Javadoc)
* @see org.alfresco.repo.web.util.paging.Cursor#hasLastPage()
*/
public boolean getHasLastPage()
{
return getLastPage() != -1;
}
/* (non-Javadoc)
* @see org.alfresco.repo.web.util.paging.Cursor#hasNextPage()
*/
public boolean getHasNextPage()
{
return getNextPage() != -1;
}
/* (non-Javadoc)
* @see org.alfresco.repo.web.util.paging.Cursor#hasPrevPage()
*/
public boolean getHasPrevPage()
{
return getPrevPage() != -1;
}
/* (non-Javadoc)
* @see org.alfresco.repo.web.util.paging.Cursor#getStartRow()
*/
public int getStartRow()
{
if (totalRows <= 0)
return 0;
return skipRows + (zeroBasedRow ? 0 : 1);
}
/* (non-Javadoc)
* @see org.alfresco.repo.web.util.paging.Cursor#getEndRow()
*/
public int getEndRow()
{
if (totalRows <= 0)
return -1;
return getStartRow() + Math.min(rowsPerPage, totalRows - skipRows) - 1;
}
/* (non-Javadoc)
* @see org.alfresco.repo.web.util.paging.Cursor#getRowCount()
*/
public int getRowCount()
{
if (totalRows <= 0)
return 0;
return getEndRow() - getStartRow() + 1;
}
}