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 + -
显示快捷键?