/*
* Copyright 2009 The Fornax Project Team, including the original
* author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sculptor.framework.domain;
import java.io.Serializable;
public class PagingParameter implements Serializable {
private static final long serialVersionUID = 3699427660197780892L;
public static final int UNKNOWN=-1;
public static final int DEFAULT_PAGE_SIZE = 50;
private final int startRow;
private final int rowCount;
private final boolean countTotal;
private final int additionalResultRows;
private final int pageSize;
// ###########################################
// # Constructors
// ###########################################
public static PagingParameter pageAccess(int pageSize) {
return pageAccess(pageSize, 1);
}
public static PagingParameter pageAccess(int pageSize, int page) {
return pageAccess(pageSize, page, false);
}
public static PagingParameter pageAccess(int pageSize, int page, boolean countTotalPages) {
return pageAccess(pageSize, page, countTotalPages, 0);
}
public static PagingParameter pageAccess(int pageSize, int page, int additionalResultPages) {
return pageAccess(pageSize, page, false, additionalResultPages);
}
public static PagingParameter pageAccess(int pageSize, int page, boolean countTotalPages, int additionalResultPages) {
if (page < 1) {
throw new IllegalArgumentException("Page numbers are 1 based");
}
int startRow = (page - 1) * pageSize;
// To ensure N additional pages we need only (N - 1) * pageSize + 1 rows
int additionalRows=additionalResultPages > 0 ? (additionalResultPages - 1) * pageSize + 1 : UNKNOWN;
return new PagingParameter(startRow, startRow + pageSize, countTotalPages, additionalRows, pageSize);
}
public static PagingParameter rowAccess(int startRow, int endRow) {
return new PagingParameter(startRow, endRow, false, 0, UNKNOWN);
}
public static PagingParameter rowAccess(int startRow, int endRow, boolean countTotalRows) {
return new PagingParameter(startRow, endRow, countTotalRows, 0, UNKNOWN);
}
public static PagingParameter rowAccess(int startRow, int endRow, int additionalResultRows) {
return new PagingParameter(startRow, endRow, false, additionalResultRows, UNKNOWN);
}
public static PagingParameter rowAccess(int startRow, int endRow, boolean countTotalRows, int additionalResultRows) {
return new PagingParameter(startRow, endRow, countTotalRows, additionalResultRows, UNKNOWN);
}
public static PagingParameter noLimits() {
return new PagingParameter();
}
private PagingParameter() {
this.startRow = UNKNOWN;
this.rowCount = UNKNOWN;
this.countTotal = false;
this.additionalResultRows=UNKNOWN;
this.pageSize = UNKNOWN;
}
private PagingParameter(int startRow, int endRow, boolean countTotal, int additionalResultRows, int pageSize) {
if (startRow < 0) {
throw new IllegalArgumentException("startRow must be 0 or possitive number (" + startRow + " < 0)");
}
if (endRow < 1) {
throw new IllegalArgumentException("endRow must be possitive number (" + endRow + " < 1)");
}
if (startRow >= endRow) {
throw new IllegalArgumentException("startRow must be less than endRow (" + startRow + " >= " + endRow + "");
}
this.startRow = startRow;
this.rowCount = endRow - startRow;
this.countTotal = countTotal;
this.additionalResultRows=additionalResultRows > 0 ? additionalResultRows : UNKNOWN;
this.pageSize = pageSize > 0 ? pageSize : UNKNOWN;
}
// ###########################################
// # Paging methods
// ###########################################
public boolean isPagedParameter() {
return pageSize != UNKNOWN;
}
public int getPage() {
return pageSize != UNKNOWN ? startRow / pageSize : UNKNOWN;
}
/**
* Number of results (rows) per page, i.e. same as {@link #getMaxResults}.
*/
public int getPageSize() {
return pageSize;
}
public int getAdditionalResultPages() {
return pageSize > 0 && additionalResultRows >= 0
? additionalResultRows / pageSize + (additionalResultRows % pageSize > 0 ? 1 : 0)
: UNKNOWN;
}
public boolean isCountTotal() {
return countTotal;
}
public static PagingParameter getNextPage(PagedResult<?> result) {
if (! result.isPagedResult()) {
throw new IllegalArgumentException("Is not paged result");
}
// TODO be more clever, look to getAdditionalPages or getTotalPages and if exceeded don't increment
// TODO cache total count, countTotal set to false but remember real count from previous result
int pageSize=result.getPageSize();
int startRow=result.getStartRow() + result.getPageSize();
return new PagingParameter(startRow, startRow + pageSize, false, result.getAdditionalResultPages(), pageSize);
}
public static PagingParameter getPreviousPage(PagedResult<?> result) {
if (! result.isPagedResult()) {
throw new IllegalArgumentException("Is not paged result");
}
int pageSize=result.getPageSize();
int startRow=result.getStartRow() - result.getPageSize();
startRow=startRow < 0 ? 0 : startRow;
return new PagingParameter(startRow, startRow + pageSize, false, result.getAdditionalResultPages(), pageSize);
}
public static PagingParameter getFirstPage(PagedResult<?> result) {
if (! result.isPagedResult()) {
throw new IllegalArgumentException("Is not paged result");
}
return new PagingParameter(0, result.getPageSize(), false, result.getAdditionalResultPages(), result.getPageSize());
}
public static PagingParameter getLastPage(PagedResult<?> result) {
if (! result.isPagedResult()) {
throw new IllegalArgumentException("Is not paged result");
}
if (result.getTotalPages() == UNKNOWN) {
throw new IllegalArgumentException("Unknown total pages - PagingParameter need countTotalPages=true");
}
int startRow=result.getTotalPages() * result.getPageSize();
int endRow=result.getTotalPages() * result.getPageSize();
return new PagingParameter(startRow, endRow, false, 0, result.getPageSize());
}
public static PagingParameter getPage(PagedResult<?> result, int pageNumber) {
if (! result.isPagedResult()) {
throw new IllegalArgumentException("Is not paged result");
}
int pageSize=result.getPageSize();
int startRow=pageNumber * pageSize - result.getPageSize();
return new PagingParameter(startRow, startRow + pageSize, false, result.getAdditionalResultPages(), pageSize);
}
// ###########################################
// # Row access methods
// ###########################################
/**
* The position of the first result (row) to retrieve, numbered from 0.
*/
public int getStartRow() {
return startRow;
}
/**
* The position of the end row to retrieve, numbered from 0 and exclusive.
*/
public int getEndRow() {
return startRow + rowCount;
}
/**
* Number of fetched rows
*/
public int getRowCount() {
return rowCount;
}
/**
* Number of really fetched rows including additionalResult Rows/Pages
*/
public int getRealFetchCount() {
return rowCount + (additionalResultRows > 0 ? additionalResultRows : 0);
}
public int getAdditionalResultRows() {
return additionalResultRows;
}
}