package org.jblooming.page; import org.apache.log4j.Logger; import org.hibernate.HibernateException; import org.hibernate.Query; import org.hibernate.ScrollMode; import org.hibernate.ScrollableResults; import org.hibernate.search.FullTextQuery; import org.jblooming.PlatformRuntimeException; import org.jblooming.tracer.Tracer; import org.jblooming.waf.settings.PersistenceConfiguration; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; /** * @author Pietro Polsinelli ppolsinelli@open-lab.com */ public class HibernatePage implements Page { protected Query query; protected List elements; protected int pageSize; protected int pageNumber; protected int totalElements = -1; public static Set jdbcClassesSupportingScrollCursors = new HashSet(); private ScrollableResults scrollableResults; public static final int DEFAULT_PAGE_SIZE = 10 ; private HibernatePage(int pageNumber, int pageSize) { this.pageNumber = pageNumber; this.pageSize = pageSize; if (this.pageSize<=0) { this.pageSize= HibernatePage.DEFAULT_PAGE_SIZE; } } public boolean isFirstPage() { return getPageNumber() == 0; } public boolean isLastPage() { return getPageNumber() >= getLastPageNumber(); } public boolean hasNextPage() { return !isLastPage(); } public boolean hasPreviousPage() { return getPageNumber() > 0; } public int getLastPageNumber() { double totalResults = new Integer(getTotalNumberOfElements()-1).doubleValue(); return new Double(Math.floor((totalResults) / getPageSize())).intValue(); } public List getThisPageElements() { return elements; } public Logger getLogger() { return Tracer.hibernateLogger; } public int getTotalNumberOfElements() { return totalElements; } public int getThisPageFirstElementNumber() { return getPageNumber() * getPageSize() + 1; } public int getThisPageLastElementNumber() { int fullPage = getThisPageFirstElementNumber() + getPageSize() - 1; return getTotalNumberOfElements() < fullPage ? getTotalNumberOfElements() : fullPage; } public int getNextPageNumber() { return getPageNumber() + 1; } public int getPreviousPageNumber() { return getPageNumber() - 1; } public int getPageSize() { return pageSize; } public int getPageNumber() { return pageNumber; } public List getAllElements() { HibernatePage pageTmp = getHibernatePageInstance(query,1,getTotalNumberOfElements()); return pageTmp.getThisPageElements(); } public static HibernatePage getHibernatePageInstance(Query query, int pageNumber, int pageSize) { return getHibernatePageInstance(query, pageNumber, pageSize, PersistenceConfiguration.getDefaultPersistenceConfiguration().driver_class); } public static HibernatePage getHibernatePageInstance(Query query, int pageNumber, int pageSize, String driverClass) { if (query.getQueryString().toLowerCase().indexOf("order by")==-1 && !(query instanceof FullTextQuery)) { Tracer.platformLogger.warn("Using pagination without order by can lead to inconsistent results, for example on certain Oracle instances: "+query.getQueryString()); Tracer.platformLogger.warn("Query used in: "+Tracer.getCallTrace(false)); } query.setReadOnly(true); if (jdbcClassesSupportingScrollCursors.contains(driverClass)) return HibernatePage.getScrollPageInstanceWithTotalByScroll(query, pageNumber, pageSize); else return HibernatePage.getScrollPageInstanceWithTotalByList(query, pageNumber, pageSize); } /** * Construct a new HibernatePage. HibernatePage numbers are zero-based so the * first page is page 0. * * @param query the Hibernate Query * @param pageNumber the page number (zero-based); * if Integer.MAX_VALUE will return the last page for the query * @param pageSize the number of results to display on the page */ protected static HibernatePage getScrollPageInstanceWithTotalByScroll(Query query, int pageNumber, int pageSize) { HibernatePage sp = new HibernatePage(pageNumber, pageSize); sp.query = query; try { sp.scrollableResults = query.scroll(ScrollMode.SCROLL_SENSITIVE); sp.scrollableResults.last(); //modified with +1 on 22 Aug 2007 sp.totalElements = sp.scrollableResults.getRowNumber()+1; if (Integer.MAX_VALUE == sp.pageNumber) sp.pageNumber = (sp.totalElements / sp.pageSize); else if (sp.pageNumber>( (sp.totalElements-1)/sp.pageSize)) sp.pageNumber = (sp.totalElements-1)/sp.pageSize; sp.scrollableResults.first(); sp.scrollableResults.scroll(sp.pageNumber * sp.pageSize-1); sp.elements= new ArrayList(sp.pageSize+1); int stop=sp.pageSize; while (sp.scrollableResults.next() && stop>0){ Object[] objects = sp.scrollableResults.get(); if (objects.length>1) sp.elements.add(objects); else sp.elements.add(objects[0]); stop--; } sp.scrollableResults.close(); } catch (HibernateException e) { sp.getLogger().error("Failed to create ScrollPage by getScrollPageInstanceWithTotalByScroll: " + e.getMessage()); throw new PlatformRuntimeException(e); } return sp; } /** * Construct a new HibernatePage. HibernatePage numbers are zero-based so the * first page is page 0. * * @param query the Hibernate Query * @param pageNumber the page number (zero-based); * if Integer.MAX_VALUE will return the last page for the query * @param pageSize the number of results to display on the page */ protected static HibernatePage getScrollPageInstanceWithTotalByList(Query query, int pageNumber, int pageSize) { HibernatePage sp = new HibernatePage(pageNumber, pageSize); sp.query = query; try { List list = query.list(); sp.totalElements = list.size(); if (Integer.MAX_VALUE == sp.pageNumber) sp.pageNumber = (sp.totalElements / sp.pageSize); else if (sp.pageNumber>( (sp.totalElements-1)/sp.pageSize)) sp.pageNumber = (sp.totalElements-1)/sp.pageSize; int from=sp.pageNumber * sp.pageSize; int to=sp.pageNumber * sp.pageSize+sp.pageSize; to=to>sp.totalElements?sp.totalElements:to; sp.elements=list.subList(from,to); } catch (HibernateException e) { sp.getLogger().error("Failed to create ScrollPage by getScrollPageInstanceWithTotalByList: " + e.getMessage()); throw new PlatformRuntimeException(e); } return sp; } }