All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.faces.renderkit.html_basic.BaseTableRenderer Maven / Gradle / Ivy

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */

package com.sun.faces.renderkit.html_basic;

import java.io.IOException;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Map;

import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.component.UIComponent;
import javax.faces.component.UIColumn;
import javax.faces.component.UIData;

import com.sun.faces.renderkit.Attribute;
import com.sun.faces.renderkit.RenderKitUtils;
import com.sun.faces.util.Util;

/**
 * Base class for concrete Grid and Table renderers.
 */
public abstract class BaseTableRenderer extends HtmlBasicRenderer {


    // ------------------------------------------------------- Protected Methods

    /**
     * Called to render the opening/closing thead elements
     * and any content nested between.
     * @param context the FacesContext for the current request
     * @param table the table that's being rendered
     * @param writer the current writer
     * @throws IOException if content cannot be written
     */
    protected abstract void renderHeader(FacesContext context,
                                         UIComponent table,
                                         ResponseWriter writer)
    throws IOException;


    /**
     * Called to render the opening/closing tfoot elements
     * and any content nested between.
     * @param context the FacesContext for the current request
     * @param table the table that's being rendered
     * @param writer the current writer
     * @throws IOException if content cannot be written
     */
    protected abstract void renderFooter(FacesContext context,
                                         UIComponent table,
                                         ResponseWriter writer)
    throws IOException;


    /**
     * Call to render the content that should be included between opening
     * and closing tr elements.
     * @param context the FacesContext for the current request
     * @param table the table that's being rendered
     * @param row the current row (if any - an implmenetation may not need this)
     * @param writer the current writer
     * @throws IOException if content cannot be written
     */
    protected abstract void renderRow(FacesContext context,
                                      UIComponent table,
                                      UIComponent row,
                                      ResponseWriter writer)
    throws IOException;


    /**
     * Renders the start of a table and applies the value of
     * styleClass if available and renders any
     * pass through attributes that may be specified.
     * @param context the FacesContext for the current request
     * @param table the table that's being rendered
     * @param writer the current writer
     * @param attributes pass-through attributes that the component
     *  supports
     * @throws IOException if content cannot be written
     */
    protected void renderTableStart(FacesContext context,
                                    UIComponent table,
                                    ResponseWriter writer,
                                    Attribute[] attributes)
    throws IOException {

        writer.startElement("table", table);
        writeIdAttributeIfNecessary(context, writer, table);
        String styleClass = (String) table.getAttributes().get("styleClass");
        if (styleClass != null) {
            writer.writeAttribute("class", styleClass, "styleClass");
        }
        RenderKitUtils.renderPassThruAttributes(context,
                                                writer,
                                                table,
                                                attributes);
        writer.writeText("\n", table, null);

    }


    /**
     * Renders the closing table element.
     * @param context the FacesContext for the current request
     * @param table the table that's being rendered
     * @param writer the current writer
     * @throws IOException if content cannot be written
     */
    @SuppressWarnings({"UnusedDeclaration"})
    protected void renderTableEnd(FacesContext context,
                                  UIComponent table,
                                  ResponseWriter writer)
    throws IOException {

        writer.endElement("table");
        writer.writeText("\n", table, null);

    }


    /**
     * Renders the caption of the table applying the values of
     * captionClass as the class and captionStyle
     * as the style if either are present.
     * @param context the FacesContext for the current request
     * @param table the table that's being rendered
     * @param writer the current writer
     * @throws IOException if content cannot be written
     */
    protected void renderCaption(FacesContext context,
                                 UIComponent table,
                                 ResponseWriter writer) throws IOException {

        UIComponent caption = getFacet(table, "caption");
        if (caption != null) {
            String captionClass =
                  (String) table.getAttributes().get("captionClass");
            String captionStyle = (String)
                  table.getAttributes().get("captionStyle");
            writer.startElement("caption", table);
            if (captionClass != null) {
                writer.writeAttribute("class", captionClass, "captionClass");
            }
            if (captionStyle != null) {
                writer.writeAttribute("style", captionStyle, "captionStyle");
            }
            encodeRecursive(context, caption);
            writer.endElement("caption");
        }
        
    }


    /**
     * Renders the starting tbody element.
     * @param context the FacesContext for the current request
     * @param table the table that's being rendered
     * @param writer the current writer
     * @throws IOException if content cannot be written
     */
    @SuppressWarnings({"UnusedDeclaration"})
    protected void renderTableBodyStart(FacesContext context,
                                        UIComponent table,
                                        ResponseWriter writer)
    throws IOException {

            writer.startElement("tbody", table);
            writer.writeText("\n", table, null);

    }


    /**
     * Renders the closing tbody element.
     * @param context the FacesContext for the current request
     * @param table the table that's being rendered
     * @param writer the current writer
     * @throws IOException if content cannot be written
     */
    @SuppressWarnings({"UnusedDeclaration"})
    protected void renderTableBodyEnd(FacesContext context,
                                      UIComponent table,
                                      ResponseWriter writer)
    throws IOException {

        writer.endElement("tbody");
        writer.writeText("\n", table, null);

    }


    /**
     * Renders the starting tr element applying any values
     * from the rowClasses attribute.
     * @param context the FacesContext for the current request
     * @param table the table that's being rendered
     * @param writer the current writer
     * @throws IOException if content cannot be written
     */
    protected void renderRowStart(FacesContext context,
                                  UIComponent table,
                                  ResponseWriter writer)
          throws IOException {

        TableMetaInfo info = getMetaInfo(context, table);
        writer.startElement("tr", table);
        if (info.rowClasses.length > 0) {
            writer.writeAttribute("class", info.getCurrentRowClass(),
                                  "rowClasses");
        }
        writer.writeText("\n", table, null);

    }


    /**
     * Renders the closing rt element.
     * @param context the FacesContext for the current request
     * @param table the table that's being rendered
     * @param writer the current writer
     * @throws IOException if content cannot be written
     */
    @SuppressWarnings({"UnusedDeclaration"})
    protected void renderRowEnd(FacesContext context,
                                UIComponent table,
                                ResponseWriter writer)
    throws IOException {

        writer.endElement("tr");
        writer.writeText("\n", table, null);

    }


    /**
     * Returns a TableMetaInfo object containing details such
     * as row and column classes, columns, and a mechanism for scrolling through
     * the row/column classes.
     * @param context the FacesContext for the current request
     * @param table the table that's being rendered
     * @return the TableMetaInfo for provided table
     */
    protected TableRenderer.TableMetaInfo getMetaInfo(FacesContext context,
                                                      UIComponent table) {

        String key = createKey(table);
        Map attributes = context.getAttributes();
        TableRenderer.TableMetaInfo info = (TableRenderer.TableMetaInfo)
              attributes.get(key);
        if (info == null) {
            info = new TableRenderer.TableMetaInfo(table);
            attributes.put(key, info);
        }
        return info;

    }


    /**
     * Removes the cached TableMetaInfo from the specified component.
     * @param context the FacesContext for the current request
     * @param table the table from which the TableMetaInfo will be removed
     */
    protected void clearMetaInfo(FacesContext context, UIComponent table) {

        context.getAttributes().remove(createKey(table));

    }


    /**
     * Creates a unique key based on the provided UIComponent with
     *  which the TableMetaInfo can be looked up.
     *
     * @param table the table that's being rendered
     * @return a unique key to store the metadata in the request and still have
     *  it associated with a specific component.
     */
    protected String createKey(UIComponent table) {

        return TableMetaInfo.KEY + '_' + table.hashCode();

    }


    // ----------------------------------------------------------- Inner Classes


    protected static class TableMetaInfo {

        private static final UIColumn PLACE_HOLDER_COLUMN = new UIColumn();
        private static final String[] EMPTY_STRING_ARRAY = new String[0];
        public static final String KEY = TableMetaInfo.class.getName();

        public final String[] rowClasses;
        public final String[] columnClasses;
        public final List columns;
        public final boolean hasHeaderFacets;
        public final boolean hasFooterFacets;
        public final int columnCount;
        public int columnStyleCounter;
        public int rowStyleCounter;


        // -------------------------------------------------------- Constructors


        public TableMetaInfo(UIComponent table) {
            rowClasses = getRowClasses(table);
            columnClasses = getColumnClasses(table);
            columns = getColumns(table);
            columnCount = columns.size();
            hasHeaderFacets = hasFacet("header", columns);
            hasFooterFacets = hasFacet("footer", columns);
        }


        // ------------------------------------------------------ Public Methods


        /**
         * Reset the counter used to apply column styles.
         */
        public void newRow() {

            columnStyleCounter = 0;

        }


        /**
         * Obtain the column class based on the current counter.  Calling this
         * method automatically moves the pointer to the next style.  If the
         * counter is larger than the number of total classes, the counter will
         * be reset.
         * @return the current style
         */
        public String getCurrentColumnClass() {

            String style = null;
            if (columnStyleCounter < columnClasses.length
                 && columnStyleCounter <= columnCount) {
                style = columnClasses[columnStyleCounter++];
            }
            return ((style != null && style.length() > 0) ? style : null);

        }


        /**
         * Obtain the row class based on the current counter.  Calling this
         * method automatically moves the pointer to the next style.  If the
         * counter is larger than the number of total classes, the counter will
         * be reset.
         * @return the current style
         */
        public String getCurrentRowClass() {
            String style = rowClasses[rowStyleCounter++];
            if (rowStyleCounter >= rowClasses.length) {
                rowStyleCounter = 0;
            }
            return style;
        }


        // ----------------------------------------------------- Private Methods


        /**
         * 

Return an array of stylesheet classes to be applied to each column in * the table in the order specified. Every column may or may not have a * stylesheet.

* * @param table {@link javax.faces.component.UIComponent} component being rendered * * @return an array of column classes */ private static String[] getColumnClasses(UIComponent table) { String values = (String) table.getAttributes().get("columnClasses"); if (values == null) { return EMPTY_STRING_ARRAY; } return Util.split(values.trim(), ","); } /** *

Return an Iterator over the UIColumn children of the * specified UIData that have a rendered property * of true.

* * @param table the table from which to extract children * * @return the List of all UIColumn children */ private static List getColumns(UIComponent table) { if (table instanceof UIData) { int childCount = table.getChildCount(); if (childCount > 0) { List results = new ArrayList(childCount); for (UIComponent kid : table.getChildren()) { if ((kid instanceof UIColumn) && kid.isRendered()) { results.add((UIColumn) kid); } } return results; } else { return Collections.emptyList(); } } else { int count; Object value = table.getAttributes().get("columns"); if ((value != null) && (value instanceof Integer)) { count = ((Integer) value); } else { count = 2; } if (count < 1) { count = 1; } List result = new ArrayList(count); for (int i = 0; i < count; i++) { result.add(PLACE_HOLDER_COLUMN); } return result; } } /** *

Return the number of child UIColumn components nested in * the specified UIData that have a facet with the specified * name.

* * @param name Name of the facet being analyzed * @param columns the columns to search * * @return the number of columns associated with the specified Facet name */ private static boolean hasFacet(String name, List columns) { if (!columns.isEmpty()) { for (UIColumn column : columns) { if (column.getFacetCount() > 0) { if (column.getFacets().containsKey(name)) { return true; } } } } return false; } /** *

Return an array of stylesheet classes to be applied to each row in the * table, in the order specified. Every row may or may not have a * stylesheet.

* * @param table {@link javax.faces.component.UIComponent} component being rendered * * @return an array of row classes */ private static String[] getRowClasses(UIComponent table) { String values = (String) table.getAttributes().get("rowClasses"); if (values == null) { return (EMPTY_STRING_ARRAY); } return Util.split(values.trim(), ","); } } // END UIDataMetaInfo }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy