All Downloads are FREE. Search and download functionalities are using the official Maven repository.

xdev.db.jdbc.VTPageScroller Maven / Gradle / Ivy

/*
 * XDEV Application Framework - XDEV Application Framework
 * Copyright © 2003 XDEV Software (https://xdev.software)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see .
 */
package xdev.db.jdbc;


import static java.lang.Boolean.FALSE;
import static java.lang.Boolean.TRUE;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import xdev.db.DBException;
import xdev.db.DelegatingResult;
import xdev.db.Result;
import xdev.vt.VirtualTable;


/**
 * This class wraps a scrollable ResultSet object and provides
 * methods to create "pages" of it as VirtualTable objects. A
 * "page" is a number of consecutive rows of the ResultSet object,
 * ranging from rows x to y.
* The ResultSet object object is kept open until closed * explicitely. *

* Example:
*
* * //rs is any scrollable ResultSet object
* final VTPageScroller pager = new VTPageScroller(rs, 100, 1); * //ResultSet rs, int rowsPerPage, int firstRowIndex
*
* VirtualTable vt;
* vt = pager.currentPage();  * //create VT instance for current page (rows 1 to 100)
* vt = pager.nextPage();     * //scroll page index forward and create new VT instance (rows 101 to 200)
* vt = pager.nextPage();     * //scroll page index forward and create new VT instance (rows 201 to 300)
* vt = pager.previousPage(); * //scroll page index backward and create new VT instance (rows 101 to 200)
*
* pager.close(); //rs must be closed manually after use
*

* * @author Thomas Muenz * */ public class VTPageScroller { // ///////////////////////////////////////////////////////////////////////// // instance fields // // ////////////////// /** * the ResultSet object wrapped by this wrapper object. */ private final ResultSet rs; /** * A hint to the total row count the wrapped ResultSet object * can yield, may be null. */ private Integer totalRows; /** * The amount of rows to be retrieved per "page" (per scroll step) . */ private int rowsPerPage; /** * The index of the first row that will be contained in the next "page". */ private int currentRowIndex; /** * Flag to allow the page index to be negative (scroll rs from the end). */ private boolean allowNegativeRowIndex = true; // ///////////////////////////////////////////////////////////////////////// // constructors // // /////////////// /** * Alias for VTPageScroller(rs, 10). * * @param rs * the scrollable ResultSet object to be wrapped. * @throws SQLException * if rs is not scrollable or * rs.getType() throws a SQLExcpetion */ public VTPageScroller(final ResultSet rs) throws SQLException { this(rs,10); } /** * Alias for VTPageScroller(rs, rowsPerPage, 1). * * * @param rs * the scrollable ResultSet object to be wrapped. * @param rowsPerPage * the number of rows to be retrieved per "page". * @throws SQLException * if rs is not scrollable or * rs.getType() throws a SQLExcpetion */ public VTPageScroller(final ResultSet rs, final int rowsPerPage) throws SQLException { this(rs,rowsPerPage,1); } /** * Alias for * VTPageScroller(rs, rowsPerPage, firstRowIndex, null). * * @param rs * the scrollable ResultSet object to be wrapped. * @param rowsPerPage * the number of rows to be retrieved per "page". * @param firstRowIndex * the current row index of the first row in the first "page" to * be created. * @throws SQLException * if rs is not scrollable or * rs.getType() throws a SQLExcpetion */ public VTPageScroller(final ResultSet rs, final int rowsPerPage, final int firstRowIndex) throws SQLException { this(rs,rowsPerPage,firstRowIndex,null); } /** * Creates a new VTPageScroller object with rs as * its wrapped scrollable ResultSet object. If rs * is not scrollable, a is thrown. Also, the call of * rs.getType() my throw a SQLException depending on the state * and implementation of rs. * * @param rs * the scrollable ResultSet object to be wrapped. * @param rowsPerPage * the number of rows to be retrieved per "page". * @param firstRowIndex * the current row index of the first row in the first "page" to * be created. * @param totalRows * a hint to how much rows the ResultSet object * provides in total. * @throws SQLException * if rs is not scrollable or * rs.getType() throws a SQLExcpetion */ public VTPageScroller(final ResultSet rs, final int rowsPerPage, final int firstRowIndex, final Integer totalRows) throws SQLException { super(); final int rsType = rs.getType(); if(rsType != ResultSet.TYPE_SCROLL_SENSITIVE && rsType != ResultSet.TYPE_SCROLL_INSENSITIVE) { throw new SQLException("ResultSet of type " + rsType + " is not scrollable!"); } this.rs = rs; this.totalRows = totalRows; this.rowsPerPage = rowsPerPage; this.currentRowIndex = firstRowIndex; } // ///////////////////////////////////////////////////////////////////////// // getters // // /////////////////// /** * @return the totalRows */ public Integer getTotalRows() { return totalRows; } /** * @return the rowsPerPage */ public int getRowsPerPage() { return rowsPerPage; } /** * @return the currentRowIndex */ public int getCurrentRowIndex() { return currentRowIndex; } /** * @return the allowNegativePosition */ public boolean isAllowNegativeRowIndex() { return allowNegativeRowIndex; } // ///////////////////////////////////////////////////////////////////////// // setters // // /////////////////// /** * @param totalRows * the totalRows to set */ public VTPageScroller setTotalRows(Integer totalRows) { this.totalRows = totalRows; return this; } /** * @param rowsPerPage * the rowsPerPage to set */ public VTPageScroller setRowsPerPage(int rowsPerPage) { this.rowsPerPage = rowsPerPage; return this; } /** * @param currentRowIndex * the currentRowIndex to set */ public VTPageScroller setCurrentRowIndex(int currentRowIndex) { this.currentRowIndex = currentRowIndex; return this; } /** * @param allowNegativeRowIndex * the allowNegativeRowIndex to set */ public VTPageScroller setAllowNegativeRowIndex(boolean allowNegativeRowIndex) { this.allowNegativeRowIndex = allowNegativeRowIndex; return this; } // ///////////////////////////////////////////////////////////////////////// // declared methods // // /////////////////// /** * Sets the cursor (current row) of the wrapped scrollable * ResultSet object to rowIndexFrom and creates a * new VirtualTable object from that row on with a length of * rowCount rows. * * @param rowIndexFrom * the index of the ResultSet object row to be the * first row of the created "page". * @param rowCount * the amount of rows to be contained in the created "page" * @return a newly created VirtualTable object with rows from * rowIndexFrom till * (rowIndexFrom + rowCount). * @throws SQLException * any SQLException that can be thrown in the process by the * ResultSet implementation */ public VirtualTable createVirtualTable(final int rowIndexFrom, final int rowCount) throws SQLException { if(rowIndexFrom < 0 && !this.allowNegativeRowIndex) { throw new IndexOutOfBoundsException("No negative rowIndex allowed by setting"); } rs.absolute(rowIndexFrom); Result r = new JDBCResult(rs,0,0,rowsPerPage); r = new DelegatingResult(r) { public void close() throws DBException { // do nothing } }; return new VirtualTable(r,true); } /** * Alias for createVirtualTable(rowIndexFrom, getRowsPerPage()) * . * * @param rowIndexFrom * @return a newly created VirtualTable object with rows from * rowIndexFrom till * (rowIndexFrom + getRowsPerPage()). * @throws SQLException * any SQLException that can be thrown in the process by the * ResultSet implementation */ public VirtualTable createVirtualTable(final int rowIndexFrom) throws SQLException { return createVirtualTable(rowIndexFrom,getRowsPerPage()); } /** * Alias for * createVirtualTable(getCurrentRowIndex(), getRowsPerPage()). * * @return a newly created VirtualTable object with rows from * getCurrentRowIndex() till * (getCurrentRowIndex() + getRowsPerPage()). * @throws SQLException * any SQLException that can be thrown in the process by the * ResultSet implementation. */ public VirtualTable currentPage() throws SQLException { return createVirtualTable(getCurrentRowIndex(),getRowsPerPage()); } /** * * @return true if either allowNegativeRowIndex or * currentRowIndex - rowsPerPage >= 0 is true. */ public boolean hasPreviousPage() { return this.allowNegativeRowIndex || this.currentRowIndex - this.rowsPerPage >= 0; } /** * Decrements currentRowIndex by rowsPerPage and * calls createVirtualTable(currentRowIndex, rowsPerPage). * * @return a newly created VirtualTable containing the previous "page" (data * from currentRowIndex with a length of * rowsPerPage) * @throws SQLException * any SQLException that can be thrown in the process by the * ResultSet implementation. */ public VirtualTable previousPage() throws SQLException { if(!this.hasPreviousPage()) return null; return this.previousPageNoCheck(); } protected VirtualTable previousPageNoCheck() throws SQLException { this.currentRowIndex -= this.rowsPerPage; return createVirtualTable(this.currentRowIndex,this.rowsPerPage); } /** * If the totalRows value of this VTPageScroller * object is null (unknown), then null * (unknown) is returned.
* Otherwise, if currentRowIndex + rowsPerPage <= * totalRows, then TRUE is returned. Else * FALSE. * * @return either null (unknown), TRUE or * FALSEdescribing if there is a next page. */ public Boolean hasNextPage() { if(this.totalRows == null) return null; return this.currentRowIndex + this.rowsPerPage <= this.totalRows ? TRUE : FALSE; } /** * Increments currentRowIndex by rowsPerPage and * calls createVirtualTable(currentRowIndex, rowsPerPage). * * @return a newly created VirtualTable containing the next "page" (data * from currentRowIndex with a length of * rowsPerPage) or null if no next page is * available according to totalRows. * @throws SQLException */ public VirtualTable nextPage() throws SQLException { final Boolean b = this.hasNextPage(); if(b == null ? false : !b) return null; // if(isFalse(this.hasNextPage())) return null; return nextPageNoCheck(); } protected VirtualTable nextPageNoCheck() throws SQLException { this.currentRowIndex += this.rowsPerPage; return createVirtualTable(this.currentRowIndex,this.rowsPerPage); } /** * Tries to call ResultSet.close() on the used * ResultSet object.
* If a SQLexception occurs, it is ignored. To preserve the exception * without throwing it to the outer context, the occured SQLException is * returned. If not SQLException occured, null is returned. * * @return the occured SQLException or null if no exception * occured. */ public SQLException close() { try { this.rs.close(); return null; } catch(SQLException e) { return e; } } /** * If closeStatment is false this method behaves * exactely like close().
* Otherwise, the wrapped ResultSet object's statement is * closed (which automatically closes the ResultSet object as * specified in Statement.close()). If the wrapped * ResultSet object does not have an associated statment, again * simply close() is called. *

* If a SQLexception occurs, it is ignored. To preserve the exception * without throwing it to the outer context, the occured SQLException is * returned. If no SQLException occured, null is returned. * * @param closeStatement * flag indicating whether the ResultSet object's * statement shall be closed instead. * @return any SQLException occured during the process to preserve that * information. */ public SQLException close(final boolean closeStatement) { if(!closeStatement) { return this.close(); } try { final Statement stmt = this.rs.getStatement(); if(stmt == null) { return this.close(); } stmt.close(); // resultSet is closed automatically as demanded by // JDBC standard return null; } catch(SQLException e) { return e; } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy