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.ProcessException;
import org.apache.slide.projector.Processor;
import org.apache.slide.projector.Result;
import org.apache.slide.projector.Store;
import org.apache.slide.projector.URI;
import org.apache.slide.projector.descriptor.AnyValueDescriptor;
import org.apache.slide.projector.descriptor.ArrayValueDescriptor;
import org.apache.slide.projector.descriptor.BooleanValueDescriptor;
import org.apache.slide.projector.descriptor.MapValueDescriptor;
import org.apache.slide.projector.descriptor.ParameterDescriptor;
import org.apache.slide.projector.descriptor.StringValueDescriptor;
import org.apache.slide.projector.descriptor.URIValueDescriptor;
import org.apache.slide.projector.engine.ProcessorManager;
import org.apache.slide.projector.i18n.ErrorMessage;
import org.apache.slide.projector.i18n.ParameterMessage;
import org.apache.slide.projector.processor.SimpleProcessor;
import org.apache.slide.projector.util.StoreHelper;
import org.apache.slide.projector.value.ArrayValue;
import org.apache.slide.projector.value.BooleanValue;
import org.apache.slide.projector.value.MapValue;
import org.apache.slide.projector.value.NullValue;
import org.apache.slide.projector.value.PrintableValue;
import org.apache.slide.projector.value.StreamableValue;
import org.apache.slide.projector.value.StringValue;
import org.apache.slide.projector.value.Value;
/**
* @version $Revision: 1.4 $
*/
public class TableGenerator extends TableMapRenderer {
final static String PARAMETER = "parameter";
final private static String COLUMN_FRAGMENT = "column";
final private static String HEADER_COLUMN_FRAGMENT = "header column";
final private static String COLLAPSED_COLUMN_FRAGMENT = "collapsed column";
final private static String COLLAPSED_HEADER_COLUMN_FRAGMENT = "collapsed header column";
final private static String ASCENDING_HEADER_COLUMN_FRAGMENT = "ascending header column";
final private static String DESCENDING_HEADER_COLUMN_FRAGMENT = "descending header column";
final private static String COLUMNS_PARAMETER = "columns";
final private static String RESIZABLE = "resizable";
final private static String SORTABLE = "sortable";
final private static String HEADER = "header";
final private static String KEY = "key";
final private static String VALUE = "value";
final private static String NAME = "name";
final private static String PROCESSOR = "processor";
final private static String PARAMETERS = "parameters";
final private static String RESULT = "result";
final private static String REPLACE_COLUMN = "replaceColumn";
final private static String HEADERS = "headers";
final private static String COLUMNS = "columns";
final private static String SORTABLE_HANDLER = "sortableHandler";
final private static String RESIZABLE_HANDLER = "resizableHandler";
private Template columnTemplate, collapsedColumnTemplate, headerColumnTemplate, collapsedHeaderColumnTemplate;
private Template ascendingHeaderColumnTemplate, descendingHeaderColumnTemplate;
private ParameterDescriptor []parameterDescriptors;
public TableGenerator() {
setRequiredFragments(new String[] { DEFAULT_FRAGMENT, COLUMN_FRAGMENT, HEADER_COLUMN_FRAGMENT });
setOptionalFragments(new String[] { COLLAPSED_HEADER_COLUMN_FRAGMENT, COLLAPSED_COLUMN_FRAGMENT, ASCENDING_HEADER_COLUMN_FRAGMENT, DESCENDING_HEADER_COLUMN_FRAGMENT, EMPTY_FRAGMENT, HEADER_FRAGMENT, FOOTER_FRAGMENT, FIRST_FRAGMENT, LAST_FRAGMENT, EVEN_FRAGMENT });
setRepeatedFragments(new String[] { FIRST_FRAGMENT, LAST_FRAGMENT, DEFAULT_FRAGMENT, EVEN_FRAGMENT });
ignoreUndefinedFragments(false);
}
public void configure(StreamableValue config) throws ConfigurationException {
super.configure(config);
ParameterDescriptor []parentParameterDescriptors = super.getParameterDescriptors();
// remove fragment parameter
List parameterDescriptorList = new ArrayList();
for ( int i = 0; i < parentParameterDescriptors.length; i++ ) {
parameterDescriptorList.add(parentParameterDescriptors[i]);
}
List headerParameterDescriptors = getTemplateParameterDescriptor(new String[] { HEADER_COLUMN_FRAGMENT, COLLAPSED_HEADER_COLUMN_FRAGMENT });
headerParameterDescriptors.add(new ParameterDescriptor(HEADER, new ParameterMessage("tableGenerator/parameter/columns/header"), new StringValueDescriptor(), StringValue.EMPTY));
headerParameterDescriptors.add(new ParameterDescriptor(VALUE, new ParameterMessage("tableGenerator/parameter/columns/value"), new AnyValueDescriptor(), NullValue.NULL));
headerParameterDescriptors.add(new ParameterDescriptor(KEY, new ParameterMessage("tableGenerator/parameter/columns/key"), new StringValueDescriptor()));
headerParameterDescriptors.add(new ParameterDescriptor(NAME, new ParameterMessage("tableGenerator/parameter/columns/name"), new StringValueDescriptor(), new StringValue(VALUE)));
headerParameterDescriptors.add(new ParameterDescriptor(REPLACE_COLUMN, new ParameterMessage("tableGenerator/parameter/columns/replaceColumn"), new BooleanValueDescriptor(), BooleanValue.FALSE));
headerParameterDescriptors.add(new ParameterDescriptor(RESIZABLE, new ParameterMessage("tableGenerator/parameter/columns/resizable"), new BooleanValueDescriptor(), BooleanValue.FALSE));
headerParameterDescriptors.add(new ParameterDescriptor(SORTABLE, new ParameterMessage("tableGenerator/parameter/columns/sortable"), new BooleanValueDescriptor(), BooleanValue.FALSE));
headerParameterDescriptors.add(new ParameterDescriptor(PROCESSOR, new ParameterMessage("tableGenerator/parameter/columns/processor"), new URIValueDescriptor(), NullValue.NULL));
headerParameterDescriptors.add(new ParameterDescriptor(PARAMETERS, new ParameterMessage("tableGenerator/parameter/columns/parameters"), MapValueDescriptor.ANY, NullValue.NULL));
headerParameterDescriptors.add(new ParameterDescriptor(RESULT, new ParameterMessage("tableGenerator/parameter/columns/result"), new StringValueDescriptor(), NullValue.NULL));
parameterDescriptorList.add(new ParameterDescriptor(COLUMNS_PARAMETER, new ParameterMessage("tableGenerator/parameter/columns"),
new ArrayValueDescriptor(new MapValueDescriptor((ParameterDescriptor [])headerParameterDescriptors.toArray(new ParameterDescriptor[headerParameterDescriptors.size()])))));
parameterDescriptorList.add(new ParameterDescriptor(PARAMETER, new ParameterMessage("tableGenerator/parameter/parameter"), MapValueDescriptor.ANY, new MapValue(new HashMap())));
parameterDescriptors = (ParameterDescriptor[] )parameterDescriptorList.toArray(new ParameterDescriptor[parameterDescriptorList.size()]);
collapsedColumnTemplate = getOptionalFragment(COLLAPSED_COLUMN_FRAGMENT);
collapsedHeaderColumnTemplate = getOptionalFragment(COLLAPSED_HEADER_COLUMN_FRAGMENT);
ascendingHeaderColumnTemplate = getOptionalFragment(ASCENDING_HEADER_COLUMN_FRAGMENT);
descendingHeaderColumnTemplate = getOptionalFragment(DESCENDING_HEADER_COLUMN_FRAGMENT);
try {
columnTemplate = getRequiredFragment(COLUMN_FRAGMENT);
headerColumnTemplate = getRequiredFragment(HEADER_COLUMN_FRAGMENT);
} catch ( ProcessException exception ) {
throw new ConfigurationException(new ErrorMessage("tableRenderer/fragmentsMissing"), exception);
}
}
public Result process(Map parameter, Context context) throws Exception {
Map parameters = ((MapValue)parameter.get(PARAMETER)).getMap();
String handlerUrl = ProcessorManager.getInstance().process(ProcessorManager.URL, TableHandler.URL, context).toString();
String id = parameter.get(TableHandler.ID).toString();
String storeName = parameter.get(TableHandler.STORE).toString();
Store store = context.getStore(StoreHelper.getStoreByName(storeName));
Map tableMap;
MapValue idResource = (MapValue)store.get(id);
String sortedBy = null, order = null;
Map size = null;
if ( idResource == null) {
tableMap = new HashMap();
MapValue tableState = new MapValue(tableMap);
store.put(id, tableState);
} else {
tableMap = idResource.getMap();
Value sortedByValue = (Value)idResource.getMap().get(TableHandler.SORTED_BY);
if ( sortedByValue != null && sortedByValue != NullValue.NULL ) sortedBy = sortedByValue.toString();
Value orderValue = (Value)idResource.getMap().get(TableHandler.ORDER);
if ( orderValue != null && orderValue != NullValue.NULL ) order = orderValue.toString();
Value sizeValue = (Value)idResource.getMap().get(TableHandler.SIZE);
if ( sizeValue != null && sizeValue != NullValue.NULL ) size = ((MapValue)sizeValue).getMap();
}
// create headers and columns and call super...
StringBuffer headersBuffer = new StringBuffer(1024);
Value []columns = ((ArrayValue)parameter.get(COLUMNS_PARAMETER)).getArray();
for ( int i = 0; i < columns.length; i++ ) {
Map columnMap = ((MapValue)columns[i]).getMap();
boolean sortable = ((BooleanValue)columnMap.get(SORTABLE)).booleanValue();
if ( ascendingHeaderColumnTemplate == null || descendingHeaderColumnTemplate == null ) sortable = false;
boolean resizable = ((BooleanValue)columnMap.get(RESIZABLE)).booleanValue();
Value header = (Value)columnMap.get(HEADER);
Map columnHeaderParameters = new HashMap();
columnHeaderParameters.putAll(parameter);
columnHeaderParameters.putAll(columnMap);
Template template = headerColumnTemplate;
String key = columnMap.get(KEY).toString();
template = headerColumnTemplate;
if ( resizable && collapsedColumnTemplate != null && collapsedHeaderColumnTemplate != null ) {
if ( size != null && TableHandler.COLLAPSED.equals(size.get(key))) {
createResizableHandler(key, TableHandler.EXPAND, handlerUrl, storeName, id, columnHeaderParameters, parameters);
template = collapsedHeaderColumnTemplate;
} else {
createResizableHandler(key, TableHandler.COLLAPSE, handlerUrl, storeName, id, columnHeaderParameters, parameters);
}
}
if ( sortable && template != collapsedHeaderColumnTemplate ) {
String requestedOrder = TableHandler.ASCENDING;
if ( sortedBy != null && sortedBy.equals(key) ) {
if ( order.equals(TableHandler.ASCENDING) ) {
template = ascendingHeaderColumnTemplate;
requestedOrder = TableHandler.DESCENDING;
} else {
template = descendingHeaderColumnTemplate;
requestedOrder = TableHandler.ASCENDING;
}
}
createSortableHandler(key, requestedOrder, handlerUrl, storeName, id, columnHeaderParameters, parameters);
}
template.evaluate(headersBuffer, columnHeaderParameters);
}
parameter.put(HEADERS, new StringValue(headersBuffer.toString()));
Value []input = ((ArrayValue)parameter.get(SimpleProcessor.INPUT)).getArray();
for ( int i = 0; i < input.length; i++ ) {
StringBuffer columnsBuffer = new StringBuffer(1024);
Map inputParameter = ((MapValue)input[i]).getMap();
for ( int j = 0; j < columns.length; j++ ) {
Map columnMap = ((MapValue)columns[j]).getMap();
boolean replaceColumn = ((BooleanValue)columnMap.get(REPLACE_COLUMN)).booleanValue();
Value processorUri = (Value)columnMap.get(PROCESSOR);
Map columnParameters = new HashMap();
columnParameters.putAll(parameter);
String key = columnMap.get(KEY).toString();
String name = columnMap.get(NAME).toString();
Object value = columnMap.get(VALUE);
if ( value == null || value == NullValue.NULL ) {
value = inputParameter.get(key);
}
columnParameters.put(name, value);
if ( processorUri != NullValue.NULL ) {
Processor processor = ProcessorManager.getInstance().getProcessor((URI)processorUri);
Value processorParameters = (Value)columnMap.get(PARAMETERS);
if ( processorParameters instanceof MapValue ) {
columnParameters.putAll(((MapValue)processorParameters).getMap());
}
Result processorResult = ProcessorManager.process(processor, columnParameters, context);
String resultKey = columnMap.get(RESULT).toString();
Value resultEntry = (Value)processorResult.getResultEntries().get(resultKey);
if ( resultEntry instanceof PrintableValue ) {
if ( replaceColumn ) {
((PrintableValue)resultEntry).print(columnsBuffer);
} else {
StringBuffer resultBuffer = new StringBuffer();
((PrintableValue)resultEntry).print(resultBuffer);
columnParameters.put(VALUE, new StringValue(resultBuffer.toString()));
}
}
}
if ( !replaceColumn ) {
Template template = columnTemplate;
if ( size != null && TableHandler.COLLAPSED.equals(size.get(key))) {
template = collapsedColumnTemplate;
}
template.evaluate(columnsBuffer, columnParameters);
}
}
inputParameter.put(COLUMNS, new StringValue(columnsBuffer.toString()));
}
return super.process(parameter, context);
}
public ParameterDescriptor[] getParameterDescriptors() {
return parameterDescriptors;
}
protected void createSortableHandler(String column, String requestedOrder, String handlerUrl, String storeName, String id, Map parameters, Map parameter) throws IOException {
StringBuffer handlerBuffer = new StringBuffer(128);
handlerBuffer.append(handlerUrl).append('?').append(TableHandler.STORE).append('=').append(storeName).append('&').append(TableHandler.ID).append('=').append(id).
append('&').append(TableHandler.SORTED_BY).append('=').append(column).append('&').append(TableHandler.ORDER).append('=').append(requestedOrder);
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(SORTABLE_HANDLER, new StringValue(handlerBuffer.toString()));
}
protected void createResizableHandler(String column, String requestedSize, String handlerUrl, String storeName, String id, Map parameters, Map parameter) throws IOException {
StringBuffer handlerBuffer = new StringBuffer(128);
handlerBuffer.append(handlerUrl).append('?').append(TableHandler.STORE).append('=').append(storeName).append('&').append(TableHandler.ID).append('=').append(id).
append('&').append(requestedSize).append('=').append(column);
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(RESIZABLE_HANDLER, new StringValue(handlerBuffer.toString()));
}
}