package org.apache.slide.projector.processor.table;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.slide.projector.ConfigurationException;
import org.apache.slide.projector.Context;
import org.apache.slide.projector.Result;
import org.apache.slide.projector.Store;
import org.apache.slide.projector.descriptor.BooleanValueDescriptor;
import org.apache.slide.projector.descriptor.MapValueDescriptor;
import org.apache.slide.projector.descriptor.NumberValueDescriptor;
import org.apache.slide.projector.descriptor.ParameterDescriptor;
import org.apache.slide.projector.descriptor.StateDescriptor;
import org.apache.slide.projector.descriptor.StringValueDescriptor;
import org.apache.slide.projector.engine.ProcessorManager;
import org.apache.slide.projector.i18n.ParameterMessage;
import org.apache.slide.projector.processor.TemplateRenderer;
import org.apache.slide.projector.util.StoreHelper;
import org.apache.slide.projector.value.BooleanValue;
import org.apache.slide.projector.value.MapValue;
import org.apache.slide.projector.value.NumberValue;
import org.apache.slide.projector.value.PrintableValue;
import org.apache.slide.projector.value.StreamableValue;
import org.apache.slide.projector.value.StringValue;
/**
* @version $Revision: 1.5 $
*/
public class TablePager extends TemplateRenderer {
public final static String SHOW_RANGE = "showRange";
public final static String RANGE = "range";
public final static String PARAMETER = "parameter";
final private static String HANDLER = "handler";
public final static String TOTAL_PAGES = "totalPages";
public final static String CURRENT_PAGE = "currentPage";
public final static String FIRST_ITEM = "firstItem";
public final static String LAST_ITEM = "lastItem";
public final static String CURRENT_ITEM_NUMBER = "currentItem";
public final static String FAILED = "failed";
protected final static String PRE_FRAGMENT = "pre";
protected final static String POST_FRAGMENT = "post";
protected final static String FIRST_FRAGMENT = "first";
protected final static String FIRST_SELECTED_FRAGMENT = "first selected";
protected final static String LAST_FRAGMENT = "last";
protected final static String LAST_SELECTED_FRAGMENT = "last selected";
protected final static String PREVIOUS_FRAGMENT = "previous";
protected final static String PREVIOUS_DISABLED_FRAGMENT = "previous disabled";
protected final static String NEXT_FRAGMENT = "next";
protected final static String NEXT_DISABLED_FRAGMENT = "next disabled";
protected final static String PAGE_FRAGMENT = "page";
protected final static String SELECTED_PAGE_FRAGMENT = "page selected";
protected final static String PAGE_SEPARATOR_FRAGMENT = "page separator";
protected final static String ETC_FRAGMENT = "etc...";
final private static int IN = 0;
final private static int OUT = 1;
final private static int BORDER = 2;
private Template pre, post, first, firstSelected, last, lastSelected;
private Template previous, previousDisabled, next, nextDisabled, page, selectedPage, pageSeparator, etc;
private ParameterDescriptor []parameterDescriptors;
public TablePager() {
setOptionalFragments(new String[] { PRE_FRAGMENT, POST_FRAGMENT, FIRST_FRAGMENT, FIRST_SELECTED_FRAGMENT, LAST_FRAGMENT, LAST_SELECTED_FRAGMENT, PREVIOUS_FRAGMENT, PREVIOUS_DISABLED_FRAGMENT, NEXT_FRAGMENT, NEXT_DISABLED_FRAGMENT,
PAGE_FRAGMENT, PAGE_SEPARATOR_FRAGMENT, SELECTED_PAGE_FRAGMENT, ETC_FRAGMENT });
}
public Result process(Map parameters, Context context) throws Exception {
Map parameter = ((MapValue)parameters.get(PARAMETER)).getMap();
boolean showRange = ((BooleanValue)parameters.get(SHOW_RANGE)).booleanValue();
int range = ((NumberValue)parameters.get(RANGE)).getNumber().intValue();
String handlerUrl = ProcessorManager.getInstance().process(ProcessorManager.URL, TableHandler.URL, context).toString();
String id = parameters.get(TableHandler.ID).toString();
String storeName = parameters.get(TableHandler.STORE).toString();
Store store = context.getStore(StoreHelper.getStoreByName(storeName));
MapValue idResource = (MapValue)store.get(id);
if ( idResource == null ) return new Result(FAILED);
Map state = idResource.getMap();
int itemsPerPage = ((NumberValue)state.get(TableMapRenderer.ITEMS_PER_PAGE)).getNumber().intValue();
if (itemsPerPage <= 0) {
return new Result(FAILED);
}
Result result = new Result(StateDescriptor.OK);
NumberValue firstItem = ((NumberValue)state.get(TableHandler.CURRENT_POSITION));
int currentPosition = firstItem.getNumber().intValue();
int currentPage = currentPosition / itemsPerPage;
int length = ((NumberValue)state.get(TableMapRenderer.LENGTH)).getNumber().intValue();
int totalPages = (int)Math.floor((double)length / ((double)itemsPerPage) + 1);
int lastItem = Math.min(currentPosition + itemsPerPage, length);
result.addResultEntry(FIRST_ITEM, firstItem);
result.addResultEntry(LAST_ITEM, new NumberValue(new Integer(lastItem)));
result.addResultEntry(CURRENT_PAGE, new NumberValue(new Integer(currentPage)));
result.addResultEntry(TOTAL_PAGES, new NumberValue(new Integer(totalPages)));
boolean hasNext = false, hasPrevious = false;
if (itemsPerPage > 0) {
hasNext = (currentPosition + itemsPerPage < length);
hasPrevious = (currentPosition > 0);
}
StringBuffer buffer = new StringBuffer();
if (pre != null) pre.evaluate(buffer, parameters);
createHandler(0, itemsPerPage, handlerUrl, storeName, id, parameters, parameter);
if ( firstSelected != null && !hasPrevious ) {
firstSelected.evaluate(buffer, parameters);
} else if ( first != null) {
first.evaluate(buffer, parameters);
}
createHandler(Math.max(0, currentPosition - itemsPerPage), itemsPerPage, handlerUrl, storeName, id, parameters, parameter);
if (hasPrevious) {
if ( previous != null) previous.evaluate(buffer, parameters);
} else {
if ( previousDisabled != null) previousDisabled.evaluate(buffer, parameters);
}
int step = itemsPerPage > 0 ? itemsPerPage : 1;
boolean first = true;
lastItem = 0;
int itemsInRange = range * step;
int lowerBorder = currentPosition - itemsInRange;
int upperBorder = currentPosition + itemsInRange;
int i = 0;
for (; i < length; i += step) {
lastItem = i;
parameters.put(CURRENT_PAGE, new NumberValue(new Integer(i / itemsPerPage + 1)));
createHandler(i, Math.min(i+itemsPerPage, length), handlerUrl, storeName, id, parameters, parameter);
int rangeState = IN;
if (showRange && (i < lowerBorder || i > upperBorder)) rangeState = OUT;
if (showRange && (i == lowerBorder || i == upperBorder)) rangeState = BORDER;
boolean pagingTemplate = false;
Template templateToUse = null;
if (i == currentPosition && selectedPage != null) {
pagingTemplate = true;
templateToUse = selectedPage;
} else if (rangeState == IN && page != null) {
pagingTemplate = true;
templateToUse = page;
} else if (rangeState == IN) {
pagingTemplate = true;
templateToUse = page;
} else if (rangeState == BORDER) {
templateToUse = etc;
}
if (templateToUse != null ) {
if (pagingTemplate) {
if (!first) {
if (pageSeparator != null) pageSeparator.evaluate(buffer, parameters);
}
first = false;
}
templateToUse.evaluate(buffer, parameters);
}
}
createHandler(currentPosition + itemsPerPage, itemsPerPage, handlerUrl, storeName, id, parameters, parameter);
if (hasNext) {
if ( next != null) next.evaluate(buffer, parameters);
} else {
if ( nextDisabled != null) nextDisabled.evaluate(buffer, parameters);
}
createHandler(i-itemsPerPage, length, handlerUrl, storeName, id, parameters, parameter);
if ( lastSelected != null && !hasNext ) {
lastSelected.evaluate(buffer, parameters);
} else if ( last != null) {
last.evaluate(buffer, parameters);
}
if ( post != null) post.evaluate(buffer, parameters);
result.addResultEntry(OUTPUT, new StringValue(buffer.toString()));
return result;
}
protected void createHandler(int i, int lastItem, String handlerUrl, String storeName, String id, Map parameters, Map parameter) throws IOException {
parameters.put(TableHandler.TARGET_POSITION, new NumberValue(new Integer(i)));
StringBuffer handlerBuffer = new StringBuffer(128);
handlerBuffer.append(handlerUrl).append('?').append(TableHandler.TARGET_POSITION).append('=').append(i).
append('&').append(TableHandler.STORE).append('=').append(storeName).append('&').append(TableHandler.ID).append('=').append(id);
for ( Iterator j = parameter.entrySet().iterator(); j.hasNext(); ) {
Map.Entry entry = (Map.Entry)j.next();
if ( entry.getValue() instanceof PrintableValue ) {
handlerBuffer.append('&').append(entry.getKey()).append('=');
((PrintableValue)entry.getValue()).print(handlerBuffer);
}
}
parameters.put(HANDLER, new StringValue(handlerBuffer.toString()));
parameters.put(FIRST_ITEM, new NumberValue(new Integer(i+1)));
parameters.put(LAST_ITEM, new NumberValue(new Integer(lastItem)));
}
public void configure(StreamableValue config) throws ConfigurationException {
super.configure(config);
// remove fragment parameter
List parameterList = new ArrayList();
parameterList.add(new ParameterDescriptor(PARAMETER, new ParameterMessage("tablePager/parameter"), MapValueDescriptor.ANY, new MapValue(new HashMap())));
parameterList.add(new ParameterDescriptor(SHOW_RANGE, new ParameterMessage("tablePager/showRange"), new BooleanValueDescriptor(), BooleanValue.FALSE));
parameterList.add(new ParameterDescriptor(RANGE, new ParameterMessage("tablePager/range"), new NumberValueDescriptor(), new NumberValue(new Integer(0))));
parameterList.add(new ParameterDescriptor(TableHandler.ID, new ParameterMessage("tableRenderer/id"), new StringValueDescriptor(), new StringValue("table")));
parameterList.add(new ParameterDescriptor(TableHandler.STORE, new ParameterMessage("tableRenderer/store"), new StringValueDescriptor(Store.stores), new StringValue(Store.stores[Store.SESSION])));
parameterDescriptors = (ParameterDescriptor[])parameterList.toArray(new ParameterDescriptor[parameterList.size()]);
pre = getOptionalFragment(PRE_FRAGMENT);
post = getOptionalFragment(POST_FRAGMENT);
first = getOptionalFragment(FIRST_FRAGMENT);
firstSelected = getOptionalFragment(FIRST_SELECTED_FRAGMENT);
last = getOptionalFragment(LAST_FRAGMENT);
lastSelected = getOptionalFragment(LAST_SELECTED_FRAGMENT);
previous = getOptionalFragment(PREVIOUS_FRAGMENT);
previousDisabled = getOptionalFragment(PREVIOUS_DISABLED_FRAGMENT);
next = getOptionalFragment(NEXT_FRAGMENT);
nextDisabled = getOptionalFragment(NEXT_DISABLED_FRAGMENT);
page = getOptionalFragment(PAGE_FRAGMENT);
pageSeparator = getOptionalFragment(PAGE_SEPARATOR_FRAGMENT);
selectedPage = getOptionalFragment(SELECTED_PAGE_FRAGMENT);
etc = getOptionalFragment(ETC_FRAGMENT);
}
public ParameterDescriptor[] getParameterDescriptors() {
return parameterDescriptors;
}
}