/**********************************************************************************
* $URL: https://source.sakaiproject.org/svn/sam/trunk/samigo-app/src/java/org/sakaiproject/tool/assessment/jsf/renderer/PagerRenderer.java $
* $Id: PagerRenderer.java 106463 2012-04-02 12:20:09Z david.horwitz@uct.ac.za $
***********************************************************************************
*
* Copyright (c) 2004, 2005, 2006, 2007, 2008, 2009 The Sakai Foundation
*
* Licensed under the Educational Community 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.opensource.org/licenses/ECL-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.sakaiproject.tool.assessment.jsf.renderer;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import javax.faces.component.NamingContainer;
import javax.faces.component.UIComponent;
import javax.faces.component.UIData;
import javax.faces.component.UIForm;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.el.ValueBinding;
import javax.faces.render.Renderer;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
*
* <p>Description: modified from an example in the core jsf book</p>
* <p>Copyright: Copyright (c) 2004 Sakai</p>
* <p>Usage:
* <samigo:pager
* controlId="controlerIdOfPagerButtonControl" dataTableId="idOfDataTable" showpages="999"
* styleClass="aStyle" selectedStyleClass="anotherStyle"/>
* </p>
* @author Lydia Li
* @author Ed Smiley
* @version $Id: PagerRenderer.java 106463 2012-04-02 12:20:09Z david.horwitz@uct.ac.za $
*/
public class PagerRenderer
extends Renderer
{
private static Log log = LogFactory.getLog(PagerRenderer.class);
public void encodeBegin(FacesContext context,
UIComponent component) throws IOException
{
String id = component.getClientId(context);
UIComponent parent = component;
while (! (parent instanceof UIForm))
{
parent = parent.getParent();
}
String formId = parent.getClientId(context);
ResponseWriter writer = context.getResponseWriter();
String styleClass = (String) get(context, component, "styleClass");
String selectedStyleClass = (String) get(context, component,
"selectedStyleClass");
String dataTableId = (String) get(context, component, "dataTableId");
String controlId = (String) get(context, component, "controlId");
Integer a = (Integer) get(context, component, "showpages");
int showpages = a == null ? 0 : a.intValue();
// find the component with the given ID
UIData data = (UIData) findComponent(context.getViewRoot(),
getId(dataTableId, id), context);
int first = data.getFirst();
int itemcount = data.getRowCount();
int pagesize = data.getRows();
if (pagesize <= 0)
{
pagesize = itemcount;
}
int pages;
int currentPage;
if (pagesize != 0)
{
pages = itemcount / pagesize;
currentPage = first / pagesize;
if (itemcount % pagesize != 0)
{
pages++;
}
}
else
{
pages = 1;
currentPage = 1;
}
if (first >= itemcount - pagesize)
{
currentPage = pages - 1;
}
int startPage = 0;
int endPage = pages;
if (showpages > 0)
{
startPage = (currentPage / showpages) * showpages;
endPage = Math.min(startPage + showpages, pages);
}
boolean showLinks = true;
Boolean showThem = (Boolean) get(context, component, "showLinks");
if (showThem != null)
{
showLinks = showThem.booleanValue();
}
// links << < # # # > >>
if (showLinks)
{
if (currentPage > 0)
{
writeLink(writer, component, formId, controlId, "<", styleClass);
}
if (startPage > 0)
{
writeLink(writer, component, formId, controlId, "<<", styleClass);
}
for (int i = startPage; i < endPage; i++)
{
writeLink(writer, component, formId, controlId, "" + (i + 1),
i == currentPage ? selectedStyleClass : styleClass);
}
if (endPage < pages)
{
writeLink(writer, component, formId, controlId, ">>", styleClass);
}
if (first < itemcount - pagesize)
{
writeLink(writer, component, formId, controlId, ">", styleClass);
}
}
// hidden field to hold result
writeHiddenField(writer, component, controlId, id);
}
/**
*
* @param writer ResponseWriter
* @param component UIComponent
* @param formId String
* @param id String
* @param value String
* @param styleClass String
* @throws IOException
*/
private void writeLink(ResponseWriter writer, UIComponent component,
String formId, String id, String value,
String styleClass) throws IOException
{
writer.writeText(" ", null);
writer.startElement("a", component);
writer.writeAttribute("href", "#", null);
writer.writeAttribute("onclick", onclickCode(formId, id, value), null);
if (styleClass != null)
{
writer.writeAttribute("class", styleClass, "styleClass");
}
writer.writeText(value, null);
writer.endElement("a");
}
/**
*
* @param formId String
* @param id String
* @param value String
* @return String
*/
private String onclickCode(String formId, String id, String value)
{
StringBuilder buffer = new StringBuilder();
buffer.append("document.forms[");
buffer.append("'");
buffer.append(formId);
buffer.append("'");
buffer.append("]['");
buffer.append(id);
buffer.append("'].value='");
buffer.append(value);
buffer.append("';");
buffer.append(" document.forms[");
buffer.append("'");
buffer.append(formId);
buffer.append("'");
buffer.append("].submit()");
buffer.append("; return false;");
return buffer.toString();
}
/**
*
* @param writer ResponseWriter
* @param component UIComponent
* @param controlId String
* @param id String
* @throws IOException
*/
private void writeHiddenField(ResponseWriter writer,
UIComponent component,
String controlId, String id) throws IOException
{
writer.startElement("input", component);
writer.writeAttribute("type", "hidden", null);
writer.writeAttribute("name", id, null);
writer.writeAttribute("id", controlId, null);
writer.endElement("input");
}
public void decode(FacesContext context, UIComponent component)
{
String id = component.getClientId(context);
Map parameters = context.getExternalContext()
.getRequestParameterMap();
String response = (String) parameters.get(id);
String dataTableId = (String) get(context, component, "dataTableId");
Integer a = (Integer) get(context, component, "showpages");
int showpages = a == null ? 0 : a.intValue();
UIData data = (UIData) findComponent(context.getViewRoot(),
getId(dataTableId, id), context);
int first = data.getFirst();
int itemcount = data.getRowCount();
int pagesize = data.getRows();
if (pagesize <= 0)
{
pagesize = itemcount;
}
if (response == null)
{
first = 0;
}
else if ("<".equals(response))
{
first -= pagesize;
}
else if (">".equals(response))
{
first += pagesize;
}
else if ("<<".equals(response))
{
first -= pagesize * showpages;
}
else if (">>".equals(response))
{
first += pagesize * showpages;
}
else
{
int page = 0; // default if cannot be parsed
try
{
page = Integer.parseInt(response);
}
catch (NumberFormatException ex)
{
// do nothing, leave at zero
log.debug("do nothing, leave at zero");
}
first = (page - 1) * pagesize;
}
if (first + pagesize > itemcount)
{
first = itemcount - pagesize;
}
if (first < 0)
{
first = 0;
}
data.setFirst(first);
}
/**
*
* @param context FacesContext
* @param component UIComponent
* @param name String
* @return Object
*/
private static Object get(FacesContext context, UIComponent component,
String name)
{
ValueBinding binding = component.getValueBinding(name);
if (binding != null)
{
return binding.getValue(context);
}
else
{
return component.getAttributes().get(name);
}
}
/**
*
* @param component UIComponent
* @param id String
* @param context FacesContext
* @return UIComponent
*/
private static UIComponent findComponent(UIComponent component,
String id,
FacesContext context)
{
String componentId = component.getClientId(context);
if (componentId.equals(id))
{
return component;
}
Iterator kids = component.getChildren().iterator();
while (kids.hasNext())
{
UIComponent kid = (UIComponent) kids.next();
UIComponent found = findComponent(kid, id, context);
if (found != null)
{
return found;
}
}
return null;
}
/**
*
* @param id String
* @param baseId String
* @return String
*/
private static String getId(String id, String baseId)
{
String separator = "" + NamingContainer.SEPARATOR_CHAR;
String[] idSplit = id.split(separator);
String[] baseIdSplit = baseId.split(separator);
StringBuilder buffer = new StringBuilder();
for (int i = 0; i < baseIdSplit.length - idSplit.length; i++)
{
buffer.append(baseIdSplit[i]);
buffer.append(separator);
}
buffer.append(id);
return buffer.toString();
}
}