tabletag.java
来自「displaytag-1.0修正版」· Java 代码 · 共 1,827 行 · 第 1/4 页
JAVA
1,827 行
public void setLength(int value)
{
this.length = value;
}
/**
* sets the index of the default sorted column.
* @param value index of the column to sort
*/
public void setDefaultsort(int value)
{
// subtract one (internal index is 0 based)
this.defaultSortedColumn = value - 1;
}
/**
* sets the number of items that should be displayed for a single page.
* @param value number of items that should be displayed for a single page
*/
public void setPagesize(int value)
{
this.pagesize = value;
}
/**
* Setter for the list offset attribute.
* @param value String
*/
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;
}
}
/**
* Sets the unique id used to identify for this table.
* @param value String
*/
public void setUid(String value)
{
if (getHtmlId() == null)
{
setHtmlId(value); // by default id is actually used for the html id attribute, if no htmlId is added
}
this.uid = value;
}
/**
* Returns the unique id used to identify for this table.
* @return id for this table
*/
public String getUid()
{
return this.uid;
}
/**
* It's a getter.
* @return the this.pageContext
*/
public PageContext getPageContext()
{
return this.pageContext;
}
/**
* Returns the properties.
* @return TableProperties
*/
protected TableProperties getProperties()
{
return this.properties;
}
/**
* Returns the base href with parameters. This is the instance used for links, need to be cloned before being
* modified.
* @return base Href with parameters
*/
protected Href getBaseHref()
{
return this.baseHref;
}
/**
* 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.
* @param column an internal tag describing a column in this tableview
*/
public void addColumn(HeaderCell column)
{
if (log.isDebugEnabled())
{
log.debug("[" + getUid() + "] addColumn " + column);
}
this.tableModel.addColumnHeader(column);
}
/**
* Adds a cell to the current row. This method is usually called by a contained ColumnTag
* @param cell Cell to add to the current row
*/
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)
{
this.currentRow.addCell(cell);
}
}
/**
* Is this the first iteration?
* @return boolean <code>true</code> if this is the first iteration
*/
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;
}
/**
* 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.
* @return int
* @throws JspException generic exception
* @see javax.servlet.jsp.tagext.Tag#doStartTag()
*/
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());
// copying id to the table model for logging
this.tableModel.setId(getUid());
initParameters();
Object previousMediaType = this.pageContext.getAttribute(PAGE_ATTRIBUTE_MEDIA);
// set the PAGE_ATTRIBUTE_MEDIA attribute in the page scope
if (this.currentMediaType != null
&& (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;
}
/**
* @see javax.servlet.jsp.tagext.BodyTag#doAfterBody()
*/
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();
}
/**
* Utility method that is used by both doStartTag() and doAfterBody() to perform an iteration.
* @return <code>int</code> either EVAL_BODY_TAG or SKIP_BODY depending on whether another iteration is desired.
*/
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);
// new iteration
// using int to avoid deprecation error in compilation using j2ee 1.3
return 2;
}
if (log.isDebugEnabled())
{
log.debug("[" + getUid() + "] doIteration() - iterator ended after " + (this.rowNumber - 1) + " rows");
}
// end iteration
return SKIP_BODY;
}
/**
* Reads parameters from the request and initialize all the needed table model attributes.
* @throws ObjectLookupException for problems in evaluating the expression in the "name" attribute
* @throws FactoryInstantiationException for problems in instantiating a RequestHelperFactory
*/
private void initParameters() throws ObjectLookupException, FactoryInstantiationException
{
if (rhf == null)
{
// first time initialization
rhf = this.properties.getRequestHelperFactoryInstance();
}
RequestHelper requestHelper = rhf.getRequestHelperInstance(this.pageContext);
initHref(requestHelper);
Integer pageNumberParameter = requestHelper.getIntParameter(encodeParameter(TableTagParameters.PARAMETER_PAGE));
this.pageNumber = (pageNumberParameter == null) ? 1 : pageNumberParameter.intValue();
Integer sortColumnParameter = requestHelper.getIntParameter(encodeParameter(TableTagParameters.PARAMETER_SORT));
int sortColumn = (sortColumnParameter == null) ? this.defaultSortedColumn : sortColumnParameter.intValue();
this.tableModel.setSortedColumnNumber(sortColumn);
// default value
boolean finalSortFull = this.properties.getSortFullList();
// user value for this single table
if (this.sortFullTable != null)
{
finalSortFull = this.sortFullTable.booleanValue();
}
this.tableModel.setSortFullTable(finalSortFull);
SortOrderEnum paramOrder = SortOrderEnum.fromCode(requestHelper
.getIntParameter(encodeParameter(TableTagParameters.PARAMETER_ORDER)));
// if no order parameter is set use default
if (paramOrder == null)
{
paramOrder = this.defaultSortOrder;
}
boolean order = SortOrderEnum.DESCENDING != paramOrder;
this.tableModel.setSortOrderAscending(order);
Integer exportTypeParameter = requestHelper
.getIntParameter(encodeParameter(TableTagParameters.PARAMETER_EXPORTTYPE));
this.currentMediaType = MediaTypeEnum.fromCode(exportTypeParameter);
if (this.currentMediaType == null)
{
this.currentMediaType = MediaTypeEnum.HTML;
}
String fullName = getFullObjectName();
// only evaluate if needed, else use list attribute
if (fullName != null)
{
this.list = evaluateExpression(fullName);
}
else if (this.list == null)
{
// needed to allow removing the collection of objects if not set directly
this.list = this.listAttribute;
}
// do we really need to skip any row?
boolean wishOptimizedIteration = (this.pagesize > 0 // we are paging
|| this.offset > 0 // or we are skipping some records using offset
|| this.length > 0 // or we are limiting the records using length
);
// can we actually skip any row?
if (wishOptimizedIteration && (this.list instanceof Collection) // we need to know the size
&& ((sortColumn == -1 // and we are not sorting
|| !finalSortFull // or we are sorting with the "page" behaviour
) && (this.currentMediaType == MediaTypeEnum.HTML // and we are not exporting
|| !this.properties.getExportFullList()) // or we are exporting a single page
))
{
int start = 0;
int end = 0;
if (this.offset > 0)
{
start = this.offset;
}
if (length > 0)
{
end = start + this.length;
}
if (this.pagesize > 0)
{
int fullSize = ((Collection) this.list).size();
start = (this.pageNumber - 1) * this.pagesize;
// invalid page requested, go back to page one
if (start > fullSize)
{
start = 0;
}
end = start + this.pagesize;
}
// rowNumber starts from 1
filteredRows = new LongRange(start + 1, end);
}
else
{
filteredRows = new LongRange(1, Long.MAX_VALUE);
}
this.tableIterator = IteratorUtils.getIterator(this.list);
}
/**
* Is the current row included in the "to-be-evaluated" range? Called by nested ColumnTags. If <code>false</code>
* column body is skipped.
* @return <code>true</code> if the current row must be evaluated because is included in output or because is
* included in sorting.
*/
protected boolean isIncludedRow()
{
return ((Range) filteredRows).containsLong(this.rowNumber);
}
/**
* Create a complete string for compatibility with previous version before expression evaluation. This approach is
* optimized for new expressions, not for previous property/scope parameters.
* @return Expression composed by scope + name + property
*/
private String getFullObjectName()
{
// only evaluate if needed, else preserve original list
if (this.name == null)
{
return null;
}
StringBuffer fullName = new StringBuffer(30);
// append scope
if (StringUtils.isNotBlank(this.scope))
{
fullName.append(this.scope).append("Scope."); //$NON-NLS-1$
}
// base bean name
fullName.append(this.name);
// append property
if (StringUtils.isNotBlank(this.property))
{
fullName.append('.').append(this.property);
}
return fullName.toString();
}
/**
* init the href object used to generate all the links for pagination, sorting, exporting.
* @param requestHelper request helper used to extract the base Href
*/
protected void initHref(RequestHelper requestHelper)
{
// get the href for this request
Href normalHref = 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 = normalHref.getParameterMap().keySet().iterator();
while (paramsIterator.hasNext())
{
String key = (String) paramsIterator.next();
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?