blob: e59a3f42b8654561d87af3eb5b56829d210e5028 [file] [log] [blame]
// Copyright 2004 The Apache Software Foundation
//
// 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.apache.tapestry.vlib.components;
import java.rmi.RemoteException;
import org.apache.tapestry.AbstractComponent;
import org.apache.tapestry.IActionListener;
import org.apache.tapestry.IMarkupWriter;
import org.apache.tapestry.IPage;
import org.apache.tapestry.IRequestCycle;
import org.apache.tapestry.Tapestry;
import org.apache.tapestry.event.PageEvent;
import org.apache.tapestry.event.PageRenderListener;
import org.apache.tapestry.vlib.VirtualLibraryEngine;
import org.apache.tapestry.vlib.ejb.Book;
import org.apache.tapestry.vlib.ejb.IBookQuery;
/**
* Implements a paging browser for the results of a {@link IBookQuery}.
*
*
* @author Howard Lewis Ship
* @version $Id$
*
**/
public abstract class Browser extends AbstractComponent implements PageRenderListener
{
public abstract IBookQuery getQuery();
/**
* Default for the page size; the number of results viewed on each page.
*
**/
public static final int DEFAULT_PAGE_SIZE = 15;
/**
* The maximum number of items to display on a page.
*
**/
private int _pageSize = DEFAULT_PAGE_SIZE;
public abstract int getResultCount();
public abstract void setResultCount(int resultCount);
public abstract int getCurrentPage();
public abstract void setCurrentPage(int currentPage);
public abstract void setElement(String element);
public abstract String getElement();
public abstract void setValue(Object value);
public abstract IActionListener getListener();
public abstract Object[] getPageResults();
public abstract void setPageResults(Object[] pageResults);
/**
* Invoked by the container when the query (otherwise accessed via the query
* parameter) changes. Re-caches the number of results and sets the current page
* back to 1.
*
**/
public void initializeForResultCount(int resultCount)
{
setResultCount(resultCount);
setCurrentPage(1);
setPageCount(computePageCount());
}
public abstract int getPageCount();
public abstract void setPageCount(int pageCount);
private int computePageCount()
{
// For 0 ... pageSize elements, its just one page.
int resultCount = getResultCount();
if (resultCount <= _pageSize)
return 1;
// We need the number of results divided by the results per page.
int result = resultCount / _pageSize;
// If there's any left-over, then we need an additional page.
if (resultCount % _pageSize > 0)
result++;
return result;
}
/**
* Invoked to change the displayed page number.
*
* @param page page to display, numbered from one. The currentPage property will be
* updated. The value is constrained to fit in the valid range of pages
* for the component.
*
**/
public void jump(int page)
{
if (page < 2)
{
setCurrentPage(1);
return;
}
int pageCount = getPageCount();
if (page > getPageCount())
{
setCurrentPage(pageCount);
return;
}
setCurrentPage(page);
}
public boolean getDisableBack()
{
return getCurrentPage() <= 1;
}
public boolean getDisableNext()
{
return getCurrentPage() >= getPageCount();
}
public String getRange()
{
int currentPage = getCurrentPage();
int resultCount = getResultCount();
int low = (currentPage - 1) * _pageSize + 1;
int high = Math.min(currentPage * _pageSize, resultCount);
return low + " - " + high;
}
protected void renderComponent(IMarkupWriter writer, IRequestCycle cycle)
{
Object[] books = getPageResults();
int count = Tapestry.size(books);
String element = getElement();
for (int i = 0; i < count; i++)
{
setValue(books[i]);
if (element != null)
{
writer.begin(element);
renderInformalParameters(writer, cycle);
}
renderBody(writer, cycle);
if (element != null)
writer.end();
}
}
protected void finishLoad()
{
setElement("tr");
}
public void pageBeginRender(PageEvent event)
{
int resultCount = getResultCount();
int currentPage = getCurrentPage();
int low = (currentPage - 1) * _pageSize;
int high = Math.min(currentPage * _pageSize, resultCount) - 1;
if (low > high)
return;
Book[] pageResults = null;
int i = 0;
while (true)
{
try
{
pageResults = getQuery().get(low, high - low + 1);
break;
}
catch (RemoteException ex)
{
IPage page = getPage();
if (i++ == 0)
getListener().actionTriggered(this, page.getRequestCycle());
else
{
VirtualLibraryEngine vengine = (VirtualLibraryEngine) page.getEngine();
vengine.rmiFailure("Unable to retrieve query results.", ex, i);
}
}
}
setPageResults(pageResults);
}
}