| Method from org.displaytag.tags.TableTag Detail: |
public void addCell(Cell cell) {
// check if null: could be null if list is empty, we don't need to fill rows
if (this.currentRow != null)
{
int columnNumber = this.currentRow.getCellList().size();
this.currentRow.addCell(cell);
// just be sure that the number of columns has not been altered by conditionally including column tags in
// different rows. This is not supported, but better avoid IndexOutOfBounds...
if (columnNumber < tableModel.getHeaderCellList().size())
{
HeaderCell header = (HeaderCell) tableModel.getHeaderCellList().get(columnNumber);
header.addCell(new Column(header, cell, currentRow));
}
}
}
Adds a cell to the current row. This method is usually called by a contained ColumnTag |
public void addColumn(HeaderCell column) {
if (log.isDebugEnabled())
{
log.debug("[" + getUid() + "] addColumn " + column);
}
if ((this.paginatedList != null) && (column.getSortable()))
{
String sortCriterion = paginatedList.getSortCriterion();
String sortProperty = column.getSortProperty();
if (sortProperty == null)
{
sortProperty = column.getBeanPropertyName();
}
if ((sortCriterion != null) && sortCriterion.equals(sortProperty))
{
this.tableModel.setSortedColumnNumber(this.tableModel.getNumberOfColumns());
column.setAlreadySorted();
}
}
this.tableModel.addColumnHeader(column);
}
Called by interior column tags to help this tag figure out how it is supposed to display the information in the
List it is supposed to display. |
public int doAfterBody() {
// doAfterBody() has been called, body is not empty
this.doAfterBodyExecuted = true;
if (log.isDebugEnabled())
{
log.debug("[" + getUid() + "] doAfterBody called - iterating on row " + this.rowNumber);
}
// increment this.rowNumber
this.rowNumber++;
// Call doIteration() to do the common work
return doIteration();
}
|
public int doEndTag() throws JspException {
if (log.isDebugEnabled())
{
log.debug("[" + getUid() + "] doEndTag called");
}
if (!this.doAfterBodyExecuted)
{
if (log.isDebugEnabled())
{
log.debug("[" + getUid() + "] tag body is empty.");
}
// first row (created in doStartTag)
if (this.currentRow != null)
{
// if yes add to table model and remove
this.tableModel.addRow(this.currentRow);
}
// other rows
while (this.tableIterator.hasNext())
{
Object iteratedObject = this.tableIterator.next();
this.rowNumber++;
// Row object for Cell values
this.currentRow = new Row(iteratedObject, this.rowNumber);
this.tableModel.addRow(this.currentRow);
}
}
// if no rows are defined automatically get all properties from bean
if (this.tableModel.isEmpty())
{
describeEmptyTable();
}
TableDecorator tableDecorator = this.properties.getDecoratorFactoryInstance().
loadTableDecorator(this.pageContext, getConfiguredDecoratorName());
if (tableDecorator != null)
{
tableDecorator.init(this.pageContext, this.list, this.tableModel);
this.tableModel.setTableDecorator(tableDecorator);
}
setupViewableData();
// Figure out how we should sort this data, typically we just sort
// the data being shown, but the programmer can override this behavior
if (this.paginatedList == null && this.tableModel.isLocalSort())
{
if (!this.tableModel.isSortFullTable())
{
this.tableModel.sortPageList();
}
}
// Get the data back in the representation that the user is after, do they want HTML/XML/CSV/EXCEL/etc...
int returnValue = EVAL_PAGE;
// check for nested tables
// Object previousMediaType = this.pageContext.getAttribute(PAGE_ATTRIBUTE_MEDIA);
Object previousMediaType = this.pageContext.getAttribute(PAGE_ATTRIBUTE_MEDIA);
if (MediaTypeEnum.HTML.equals(this.currentMediaType)
&& (previousMediaType == null || MediaTypeEnum.HTML.equals(previousMediaType)))
{
writeHTMLData();
}
else if (!MediaTypeEnum.HTML.equals(this.currentMediaType))
{
if (log.isDebugEnabled())
{
log.debug("[" + getUid() + "] doEndTag - exporting");
}
returnValue = doExport();
}
// do not remove media attribute! if the table is nested in other tables this is still needed
// this.pageContext.removeAttribute(PAGE_ATTRIBUTE_MEDIA);
if (log.isDebugEnabled())
{
log.debug("[" + getUid() + "] doEndTag - end");
}
cleanUp();
return returnValue;
}
Draw the table. This is where everything happens, we figure out what values we are supposed to be showing, we
figure out how we are supposed to be showing them, then we draw them. |
protected int doExport() throws JspException {
boolean exportFullList = this.properties.getExportFullList();
if (log.isDebugEnabled())
{
log.debug("[" + getUid() + "] currentMediaType=" + this.currentMediaType);
}
boolean exportHeader = this.properties.getExportHeader(this.currentMediaType);
boolean exportDecorated = this.properties.getExportDecorated();
ExportView exportView = ExportViewFactory.getInstance().getView(
this.currentMediaType,
this.tableModel,
exportFullList,
exportHeader,
exportDecorated);
try
{
writeExport(exportView);
}
catch (IOException e)
{
throw new WrappedRuntimeException(getClass(), e);
}
return SKIP_PAGE;
}
Called when data are not displayed in a html page but should be exported. |
protected int doIteration() {
if (log.isDebugEnabled())
{
log.debug("[" + getUid() + "] doIteration called");
}
// Row already filled?
if (this.currentRow != null)
{
// if yes add to table model and remove
this.tableModel.addRow(this.currentRow);
this.currentRow = null;
}
if (this.tableIterator.hasNext())
{
Object iteratedObject = this.tableIterator.next();
if (getUid() != null)
{
if ((iteratedObject != null))
{
// set object into this.pageContext
if (log.isDebugEnabled())
{
log.debug("[" + getUid() + "] setting attribute \"" + getUid() + "\" in pageContext");
}
this.pageContext.setAttribute(getUid(), iteratedObject);
}
else
{
// if row is null remove previous object
this.pageContext.removeAttribute(getUid());
}
// set the current row number into this.pageContext
this.pageContext.setAttribute(getUid() + TableTagExtraInfo.ROWNUM_SUFFIX, new Integer(this.rowNumber));
}
// Row object for Cell values
this.currentRow = new Row(iteratedObject, this.rowNumber);
this.lastIteration = !this.tableIterator.hasNext();
// new iteration
// using int to avoid deprecation error in compilation using j2ee 1.3
return 2;
}
this.lastIteration = true;
if (log.isDebugEnabled())
{
log.debug("[" + getUid() + "] doIteration() - iterator ended after " + (this.rowNumber - 1) + " rows");
}
// end iteration
return SKIP_BODY;
}
Utility method that is used by both doStartTag() and doAfterBody() to perform an iteration. |
public int doStartTag() throws JspException {
DependencyChecker.check();
// needed before column processing, elsewhere registered views will not be added
ExportViewFactory.getInstance();
if (log.isDebugEnabled())
{
log.debug("[" + getUid() + "] doStartTag called");
}
this.properties = TableProperties.getInstance((HttpServletRequest) pageContext.getRequest());
this.tableModel = new TableModel(this.properties, pageContext.getResponse().getCharacterEncoding(), pageContext);
// copying id to the table model for logging
this.tableModel.setId(getUid());
initParameters();
this.tableModel.setMedia(this.currentMediaType);
Object previousMediaType = this.pageContext.getAttribute(PAGE_ATTRIBUTE_MEDIA);
// set the PAGE_ATTRIBUTE_MEDIA attribute in the page scope
if (previousMediaType == null || MediaTypeEnum.HTML.equals(previousMediaType))
{
if (log.isDebugEnabled())
{
log.debug("[" + getUid() + "] setting media [" + this.currentMediaType + "] in this.pageContext");
}
this.pageContext.setAttribute(PAGE_ATTRIBUTE_MEDIA, this.currentMediaType);
}
doIteration();
// always return EVAL_BODY_TAG to get column headers also if the table is empty
// using int to avoid deprecation error in compilation using j2ee 1.3
return 2;
}
When the tag starts, we just initialize some of our variables, and do a little bit of error checking to make sure
that the user is not trying to give us parameters that we don't expect. |
protected Href getBaseHref() {
return this.baseHref;
}
Returns the base href with parameters. This is the instance used for links, need to be cloned before being
modified. |
public CaptionTag getCaptionTag() {
return this.captionTag;
}
Obtain the child caption tag. |
protected String getName() {
return this.name;
}
|
protected TableProperties getProperties() {
return this.properties;
}
|
public TableModel getTableModel() {
return this.tableModel;
}
Get the table model for this tag. Sometimes required by local tags that cooperate with DT. USE THIS METHOD WITH
EXTREME CAUTION; IT PROVIDES ACCESS TO THE INTERNALS OF DISPLAYTAG, WHICH ARE NOT TO BE CONSIDERED STABLE PUBLIC
INTERFACES. |
public Map getTotals() {
Map totalsMap = new HashMap();
if (this.varTotals != null)
{
List headers = this.tableModel.getHeaderCellList();
for (Iterator iterator = headers.iterator(); iterator.hasNext();)
{
HeaderCell headerCell = (HeaderCell) iterator.next();
if (headerCell.isTotaled())
{
totalsMap.put("column" + (headerCell.getColumnNumber() + 1), new Double(headerCell.getTotal()));
}
}
}
return totalsMap;
}
Get the column totals Map. If there is no varTotals defined, there are no totals. |
public String getUid() {
return this.uid;
}
Returns the unique id used to identify for this table. |
public String getVarTotals() {
return this.varTotals;
}
Get the name that the totals should be stored under. |
protected void initHref(RequestHelper requestHelper) {
// get the href for this request
this.baseHref = requestHelper.getHref();
if (this.excludedParams != null)
{
String[] splittedExcludedParams = StringUtils.split(this.excludedParams);
// handle * keyword
if (splittedExcludedParams.length == 1 && "*".equals(splittedExcludedParams[0]))
{
// @todo cleanup: paramEncoder initialization should not be done here
if (this.paramEncoder == null)
{
this.paramEncoder = new ParamEncoder(getUid());
}
Iterator paramsIterator = baseHref.getParameterMap().keySet().iterator();
while (paramsIterator.hasNext())
{
String key = (String) paramsIterator.next();
// don't remove parameters added by the table tag
if (!this.paramEncoder.isParameterEncoded(key))
{
baseHref.removeParameter(key);
}
}
}
else
{
for (int j = 0; j < splittedExcludedParams.length; j++)
{
baseHref.removeParameter(splittedExcludedParams[j]);
}
}
}
if (this.requestUri != null)
{
// if user has added a requestURI create a new href
String fullURI = requestUri;
if (!this.dontAppendContext)
{
String contextPath = ((HttpServletRequest) this.pageContext.getRequest()).getContextPath();
// prepend the context path if any.
// actually checks if context path is already there for people which manually add it
if (!StringUtils.isEmpty(contextPath)
&& requestUri != null
&& requestUri.startsWith("/")
&& !requestUri.startsWith(contextPath))
{
fullURI = contextPath + this.requestUri;
}
}
// call encodeURL to preserve session id when cookies are disabled
fullURI = ((HttpServletResponse) this.pageContext.getResponse()).encodeURL(fullURI);
baseHref.setFullUrl(fullURI);
// // ... and copy parameters from the current request
// Map parameterMap = normalHref.getParameterMap();
// this.baseHref.addParameterMap(parameterMap);
}
}
init the href object used to generate all the links for pagination, sorting, exporting. |
protected boolean isEmpty() {
return this.currentRow == null;
}
Is the current row empty? |
protected boolean isFirstIteration() {
if (log.isDebugEnabled())
{
log.debug("["
+ getUid()
+ "] first iteration="
+ (this.rowNumber == 1)
+ " (row number="
+ this.rowNumber
+ ")");
}
// in first iteration this.rowNumber is 1
// (this.rowNumber is incremented in doAfterBody)
return this.rowNumber == 1;
}
Is this the first iteration? |
protected boolean isIncludedRow() {
return ((Range) filteredRows).containsLong(this.rowNumber);
}
Is the current row included in the "to-be-evaluated" range? Called by nested ColumnTags. If false
column body is skipped. |
protected boolean isLastIteration() {
return this.lastIteration;
}
Is this the last iteration? |
public void release() {
if (log.isDebugEnabled())
{
log.debug("[" + getUid() + "] release() called");
}
super.release();
// tag attributes
this.decoratorName = null;
this.defaultSortedColumn = -1;
this.defaultSortOrder = null;
this.export = false;
this.length = 0;
this.listAttribute = null;
this.localSort = true;
this.name = null;
this.offset = 0;
this.pagesize = 0;
this.partialList = false;
this.requestUri = null;
this.dontAppendContext = false;
this.sortFullTable = null;
this.excludedParams = null;
this.filteredRows = null;
this.uid = null;
this.paginatedList = null;
}
|
public void setCaption(String string) {
this.caption = string;
this.tableModel.setCaption(this.caption);
}
Sets the content of the caption. Called by a nested caption tag. |
public void setCaptionTag(CaptionTag captionTag) {
this.captionTag = captionTag;
}
Set the child caption tag. |
public void setDecorator(String decorator) {
this.decoratorName = decorator;
}
Setter for the decorator class name. |
public void setDefaultorder(String value) throws InvalidTagAttributeValueException {
this.defaultSortOrder = SortOrderEnum.fromName(value);
if (this.defaultSortOrder == null)
{
throw new InvalidTagAttributeValueException(getClass(), "defaultorder", value); //$NON-NLS-1$
}
}
sets the sorting order for the sorted column. |
public void setDefaultsort(int value) {
// subtract one (internal index is 0 based)
this.defaultSortedColumn = value - 1;
}
sets the index of the default sorted column. |
public void setExcludedParams(String value) {
this.excludedParams = value;
}
Sets the list of parameter which should not be forwarded during sorting or pagination. |
public void setExport(boolean value) {
this.export = value;
}
|
public void setFooter(String string) {
this.footer = string;
this.tableModel.setFooter(this.footer);
}
Sets the content of the footer. Called by a nested footer tag. |
public void setLength(int value) {
this.length = value;
}
sets the number of items to be displayed in the page. |
public void setList(Object value) {
this.listAttribute = value;
} Deprecated! use - setName() to get the object from the page or request scope instead of setting it directly here
Used to directly set a list (or any object you can iterate on). |
public void setName(Object value) {
if (value instanceof String)
{
// ok, assuming this is the name of the object
this.name = (String) value;
}
else
{
// is this the list?
this.list = value;
}
}
Sets the name of the object to use for iteration. |
public void setNameString(String value) {
this.name = value;
}
Sets the name of the object to use for iteration. This setter is needed for jsp 1.1 container which doesn't
support the String - Object conversion. The bean info class will swith to this setter. |
public void setOffset(int value) {
if (value < 1)
{
// negative values has no meaning, simply treat them as 0
this.offset = 0;
}
else
{
this.offset = value - 1;
}
}
Setter for the list offset attribute. |
public void setPagesize(int value) {
this.pagesize = value;
}
sets the number of items that should be displayed for a single page. |
public void setPartialList(boolean partialList) {
this.partialList = partialList;
}
tells display tag that the values contained in the list are the viewable data only, there may be more results not
given to displaytag |
public void setProperty(String propertyName,
String propertyValue) {
this.properties.setProperty(propertyName, propertyValue);
}
Called by the setProperty tag to override some default behavior or text String. |
public void setRequestURI(String value) {
this.requestUri = value;
}
setter for the "requestURI" attribute. Context path is automatically added to path starting with "/". |
public void setRequestURIcontext(boolean value) {
this.dontAppendContext = !value;
}
Setter for the "requestURIcontext" attribute. |
public void setSize(Object size) {
if (size instanceof String)
{
this.sizeObjectName = (String) size;
}
else
{
this.size = size;
}
}
set the Integer containing the total size of the data displaytag is paginating |
public void setSizeObjectName(String sizeObjectName) {
this.sizeObjectName = sizeObjectName;
}
set the name of the Integer in some scope containing the total size of the data to be paginated |
public void setSort(String value) throws InvalidTagAttributeValueException {
if (TableTagParameters.SORT_AMOUNT_PAGE.equals(value))
{
this.sortFullTable = Boolean.FALSE;
}
else if (TableTagParameters.SORT_AMOUNT_LIST.equals(value))
{
this.sortFullTable = Boolean.TRUE;
}
else if (TableTagParameters.SORT_AMOUNT_EXTERNAL.equals(value))
{
this.localSort = false;
}
else
{
throw new InvalidTagAttributeValueException(getClass(), "sort", value); //$NON-NLS-1$
}
}
setter for the "sort" attribute. |
public void setUid(String value) {
this.uid = value;
}
Sets the unique id used to identify for this table. |
public void setVarTotals(String varTotalsName) {
this.varTotals = varTotalsName;
}
The variable name in which the totals map is stored. |
protected void setupViewableData() {
// If the user has changed the way our default behavior works, then we need to look for it now, and resort
// things if needed before we ask for the viewable part. (this is a bad place for this, this should be
// refactored and moved somewhere else).
if (this.paginatedList == null || this.tableModel.isLocalSort())
{
if (this.tableModel.isSortFullTable())
{
// Sort the total list...
this.tableModel.sortFullList();
}
}
Object originalData = this.tableModel.getRowListFull();
// If they have asked for a subset of the list via the length
// attribute, then only fetch those items out of the master list.
List fullList = CollectionUtil.getListFromObject(originalData, this.offset, this.length);
int pageOffset = this.offset;
// If they have asked for just a page of the data, then use the
// SmartListHelper to figure out what page they are after, etc...
if (this.paginatedList == null && this.pagesize > 0)
{
this.listHelper = new SmartListHelper(fullList, (this.partialList) ? ((Integer) size).intValue() : fullList
.size(), this.pagesize, this.properties, this.partialList);
this.listHelper.setCurrentPage(this.pageNumber);
pageOffset = this.listHelper.getFirstIndexForCurrentPage();
fullList = this.listHelper.getListForCurrentPage();
}
else if (this.paginatedList != null)
{
this.listHelper = new PaginatedListSmartListHelper(this.paginatedList, this.properties);
}
this.tableModel.setRowListPage(fullList);
this.tableModel.setPageOffset(pageOffset);
}
This sets the list of all of the data that will be displayed on the page via the table tag. This might include
just a subset of the total data in the list due to to paging being active, or the user asking us to just show a
subset, etc... |
protected void writeExport(ExportView exportView) throws IOException, JspException {
String filename = properties.getExportFileName(this.currentMediaType);
HttpServletResponse response = (HttpServletResponse) this.pageContext.getResponse();
HttpServletRequest request = (HttpServletRequest) this.pageContext.getRequest();
Map bean = (Map) request.getAttribute(FILTER_CONTENT_OVERRIDE_BODY);
boolean usingFilter = bean != null;
String mimeType = exportView.getMimeType();
// original encoding, be sure to add it back after reset()
String characterEncoding = response.getCharacterEncoding();
if (usingFilter)
{
if (!bean.containsKey(TableTagParameters.BEAN_BUFFER))
{
// We are running under the export filter, call it
log.debug("Exportfilter enabled in unbuffered mode, setting headers");
response.addHeader(TableTagParameters.PARAMETER_EXPORTING, TagConstants.EMPTY_STRING);
}
else
{
// We are running under the export filter in buffered mode
bean.put(TableTagParameters.BEAN_CONTENTTYPE, mimeType);
bean.put(TableTagParameters.BEAN_FILENAME, filename);
if (exportView instanceof TextExportView)
{
StringWriter writer = new StringWriter();
((TextExportView) exportView).doExport(writer);
bean.put(TableTagParameters.BEAN_BODY, writer.toString());
}
else if (exportView instanceof BinaryExportView)
{
ByteArrayOutputStream stream = new ByteArrayOutputStream();
((BinaryExportView) exportView).doExport(stream);
bean.put(TableTagParameters.BEAN_BODY, stream.toByteArray());
}
else
{
throw new JspTagException("Export view "
+ exportView.getClass().getName()
+ " must implement TextExportView or BinaryExportView");
}
return;
}
}
else
{
log.debug("Exportfilter NOT enabled");
// response can't be already committed at this time
if (response.isCommitted())
{
throw new ExportException(getClass());
}
try
{
response.reset();
pageContext.getOut().clearBuffer();
}
catch (Exception e)
{
throw new ExportException(getClass());
}
}
if (!usingFilter && characterEncoding != null && mimeType.indexOf("charset") == -1) //$NON-NLS-1$
{
mimeType += "; charset=" + characterEncoding; //$NON-NLS-1$
}
response.setContentType(mimeType);
if (StringUtils.isNotEmpty(filename))
{
response.setHeader("Content-Disposition", //$NON-NLS-1$
"attachment; filename=\"" + filename + "\""); //$NON-NLS-1$ //$NON-NLS-2$
}
if (exportView instanceof TextExportView)
{
Writer writer;
if (usingFilter)
{
writer = response.getWriter();
}
else
{
writer = pageContext.getOut();
}
((TextExportView) exportView).doExport(writer);
}
else if (exportView instanceof BinaryExportView)
{
// dealing with binary content
// note that this is not assured to work on any application server if the filter is not enabled. According
// to the jsp specs response.getOutputStream() should no be called in jsps.
((BinaryExportView) exportView).doExport(response.getOutputStream());
}
else
{
throw new JspTagException("Export view "
+ exportView.getClass().getName()
+ " must implement TextExportView or BinaryExportView");
}
log.debug("Export completed");
}
Will write the export. The default behavior is to write directly to the response. If the ResponseOverrideFilter
is configured for this request, will instead write the exported content to a map in the Request object. |