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

com.sun.webui.jsf.renderkit.html.TableRowGroupRenderer Maven / Gradle / Ivy

There is a newer version: 4.4.0.1
Show newest version
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 2007-2018 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://oss.oracle.com/licenses/CDDL+GPL-1.1
 * or 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 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.webui.jsf.renderkit.html;

import com.sun.faces.annotation.Renderer;
import com.sun.data.provider.RowKey;
import com.sun.webui.jsf.component.Table;
import com.sun.webui.jsf.component.TableColumn;
import com.sun.webui.jsf.component.TableRowGroup;
import com.sun.webui.theme.Theme;
import com.sun.webui.jsf.theme.ThemeStyles;
import com.sun.webui.jsf.util.LogUtil;
import com.sun.webui.jsf.util.RenderingUtilities;
import com.sun.webui.jsf.util.ThemeUtilities;
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 javax.faces.component.NamingContainer;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;

/**
 * This class renders TableRowGroup components.
 * 

* The TableRowGroup component provides a layout mechanism for displaying rows * of data. UI guidelines describe specific behavior that can applied to the * rows and columns of data such as sorting, filtering, pagination, selection, * and custom user actions. In addition, UI guidelines also define sections of * the table that can be used for titles, row group headers, and placement of * pre-defined and user defined actions. *

* Note: Column headers and footers are rendered by TableRowGroupRenderer. Table * column footers are rendered by TableRenderer. *

* Note: To see the messages logged by this class, set the following global * defaults in your JDK's "jre/lib/logging.properties" file. *

 * java.util.logging.ConsoleHandler.level = FINE
 * com.sun.webui.jsf.renderkit.html.TableRowGroupRenderer.level = FINE
 * 

* See TLD docs for more information. *

*/ @Renderer(@Renderer.Renders(componentFamily = "com.sun.webui.jsf.TableRowGroup")) public class TableRowGroupRenderer extends javax.faces.render.Renderer { /** * The set of String pass-through attributes to be rendered. *

* Note: The BGCOLOR attribute is deprecated (in the HTML 4.0 spec) in favor * of style sheets. In addition, the DIR and LANG attributes are not * cuurently supported. *

*/ private static final String stringAttributes[] = { "align", //NOI18N "bgColor", //NOI18N "char", //NOI18N "charOff", //NOI18N "dir", //NOI18N "lang", //NOI18N "onClick", //NOI18N "onDblClick", //NOI18N "onKeyDown", //NOI18N "onKeyPress", //NOI18N "onKeyUp", //NOI18N "onMouseDown", //NOI18N "onMouseUp", //NOI18N "onMouseMove", //NOI18N "onMouseOut", //NOI18N "onMouseOver", //NOI18N "style", //NOI18N "valign"}; //NOI18N // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Renderer methods // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /** * Render the beginning of the specified UIComponent to the output stream or * writer associated with the response we are creating. * * @param context FacesContext for the current request. * @param component UIComponent to be rendered. * * @exception IOException if an input/output error occurs. * @exception NullPointerException if context or component is null. */ @Override public void encodeBegin(FacesContext context, UIComponent component) throws IOException { if (context == null || component == null) { log("encodeBegin", //NOI18N "Cannot render, FacesContext or UIComponent is null"); //NOI18N throw new NullPointerException(); } if (!component.isRendered()) { log("encodeBegin", "Component not rendered, nothing to display"); //NOI18N return; } TableRowGroup group = (TableRowGroup) component; ResponseWriter writer = context.getResponseWriter(); // Render group and column headers. if (group.isAboveColumnHeader()) { renderGroupHeader(context, group, writer); renderColumnHeaders(context, group, writer); } else { renderColumnHeaders(context, group, writer); renderGroupHeader(context, group, writer); } group.setRowKey(null); // Clean up. } /** * Render the children of the specified UIComponent to the output stream or * writer associated with the response we are creating. * * @param context FacesContext for the current request. * @param component UIComponent to be decoded. * * @exception IOException if an input/output error occurs. * @exception NullPointerException if context or component is null. */ @Override public void encodeChildren(FacesContext context, UIComponent component) throws IOException { if (context == null || component == null) { log("encodeChildren", //NOI18N "Cannot render, FacesContext or UIComponent is null"); //NOI18N throw new NullPointerException(); } if (!component.isRendered()) { log("encodeChildren", "Component not rendered, nothing to display"); //NOI18N return; } TableRowGroup group = (TableRowGroup) component; ResponseWriter writer = context.getResponseWriter(); // Render empty data message. if (group.getRowCount() == 0) { log("encodeChildren", "Cannot render data, row count is zero"); //NOI18N renderEmptyDataColumn(context, group, writer); return; } // Get rendered row keys. RowKey[] rowKeys = group.getRenderedRowKeys(); if (rowKeys == null) { log("encodeChildren", "Cannot render data, RowKey array is null"); //NOI18N return; } // Iterate over the rendered RowKey objects. for (int i = 0; i < rowKeys.length; i++) { group.setRowKey(rowKeys[i]); if (!group.isRowAvailable()) { log("encodeChildren", "Cannot render data, row not available"); //NOI18N break; } // Render row. renderEnclosingTagStart(context, group, writer, i); // Render children. Iterator kids = group.getTableColumnChildren(); while (kids.hasNext()) { TableColumn col = (TableColumn) kids.next(); if (!col.isRendered()) { log("encodeChildren", //NOI18N "TableColumn not rendered, nothing to display"); //NOI18N continue; } // Render column. RenderingUtilities.renderComponent(col, context); } renderEnclosingTagEnd(writer); } group.setRowKey(null); // Clean up. } /** * Render the ending of the specified UIComponent to the output stream or * writer associated with the response we are creating. * * @param context FacesContext for the current request. * @param component UIComponent to be rendered. * * @exception IOException if an input/output error occurs. * @exception NullPointerException if context or component is null. */ @Override public void encodeEnd(FacesContext context, UIComponent component) throws IOException { if (context == null || component == null) { log("encodeEnd", //NOI18N "Cannot render, FacesContext or UIComponent is null"); //NOI18N throw new NullPointerException(); } if (!component.isRendered()) { log("encodeEnd", "Component not rendered, nothing to display"); //NOI18N return; } TableRowGroup group = (TableRowGroup) component; ResponseWriter writer = context.getResponseWriter(); // Do not render footers for an empty table. if (group.getRowCount() == 0) { log("encodeEnd", //NOI18N "Column, group, and table footers not rendered, row count is zero"); //NOI18N return; } // Render group and column footers. if (group.isAboveColumnFooter()) { renderGroupFooter(context, group, writer); renderColumnFooters(context, group, writer); } else { renderColumnFooters(context, group, writer); renderGroupFooter(context, group, writer); } // Do not render table footers for an empty table. Table table = group.getTableAncestor(); if (table.getRowCount() > 0) { renderTableColumnFooters(context, group, writer); } else { log("encodeEnd", //NOI18N "Table column footers not rendered, row count is zero"); //NOI18N } group.setRowKey(null); // Clean up. } /** * Return a flag indicating whether this Renderer is responsible * for rendering the children the component it is asked to render. * The default implementation returns false. */ @Override public boolean getRendersChildren() { return true; } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Empty data methods // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /** * Render empty data message for TableRowGroup components. * * @param context FacesContext for the current request. * @param component TableRowGroup to be rendered. * @param writer ResponseWriter to which the component should be rendered. * * @exception IOException if an input/output error occurs. */ protected void renderEmptyDataColumn(FacesContext context, TableRowGroup component, ResponseWriter writer) throws IOException { if (component == null) { log("renderEmptyDataColumn", //NOI18N "Cannot render empty data column, TableRowGroup is null"); //NOI18N return; } // Render row start. renderEnclosingTagStart(context, component, writer, -1); // Render empty data column. writer.writeText("\n", null); //NOI18N RenderingUtilities.renderComponent(component.getEmptyDataColumn(), context); renderEnclosingTagEnd(writer); } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Column methods // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /** * Render column footers for TableRowGroup components. *

* Note: Although not currently a requirement, nested TableColumn children * could render column footers that look like: *

     *
     * |   | 1 | 2 |   | 3 | 4 | 5 | 6 |   |
     * | A |   B   | C |       D       | E |
     *
     * 

* In this case, components would be rendered on separate rows. For example, * the HTML would look like: *

     *
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
A12C3456E
BD
* *

* However, the current implementation will render only the first row, which * would look like: *

     *
     * | A | 1 | 2 | C | 3 | 4 | 5 | 6 | E |
     *
     * 
* @param context FacesContext for the current request. * @param component TableRowGroup to be rendered. * @param writer ResponseWriter to which the component should be rendered. * * @exception IOException if an input/output error occurs. */ protected void renderColumnFooters(FacesContext context, TableRowGroup component, ResponseWriter writer) throws IOException { if (component == null) { log("renderColumnFooters", //NOI18N "Cannot render column footers, TableRowGroup is null"); //NOI18N return; } // Get Map of List objects containing nested TableColumn children. Map map = getColumnFooterMap(component); // Render nested TableColumn children on separate rows. Theme theme = getTheme(); Table table = component.getTableAncestor(); for (int c = 0; c < map.size(); c++) { // The default is to show one level only. if (c > 0 && !component.isMultipleColumnFooters()) { log("renderColumnFooters", //NOI18N "Multiple column footers not rendered, nothing to display"); //NOI18N break; } // Flag to keep from rendering empty tag when no headers are displayed. boolean renderStartElement = true; // Get List of nested TableColumn children. List list = (List) map.get(new Integer(c)); for (int i = 0; i < list.size(); i++) { TableColumn col = (TableColumn) list.get(i); if (!col.isRendered()) { log("renderColumnFooters", //NOI18N "TableColumn not rendered, nothing to display"); //NOI18N continue; } // Get group footer. UIComponent footer = col.getColumnFooter(); if (!(footer != null && footer.isRendered())) { log("renderColumnFooters", //NOI18N "Column footer not rendered, nothing to display"); //NOI18N continue; } // Render start element. if (renderStartElement) { renderStartElement = false; writer.writeText("\n", null); //NOI18N writer.startElement("tr", component); //NOI18N writer.writeAttribute("id", getId(component, //NOI18N TableRowGroup.COLUMN_FOOTER_BAR_ID + NamingContainer.SEPARATOR_CHAR + c), null); // Render style class. if (component.isCollapsed()) { writer.writeAttribute("class", //NOI18N theme.getStyleClass(ThemeStyles.HIDDEN), null); //NOI18N } } // Render footer. RenderingUtilities.renderComponent(footer, context); } // If start element was rendered, this value will be false. if (!renderStartElement) { writer.endElement("tr"); //NOI18N } } } /** * Render column headers for TableRowGroup components. *

* Note: Although not typical, nested TableColumn children may render column * headers that look like: *

     *
     * | A |   B   | C |       D       | E |
     * |   | 1 | 2 |   | 3 | 4 | 5 | 6 |   |
     *
     * 

* In this case, components would be rendered on separate rows. For example, * the HTML would look like: *

     *
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
ABCDE
123456
* *
* @param context FacesContext for the current request. * @param component TableRowGroup to be rendered. * @param writer ResponseWriter to which the component should be rendered. * * @exception IOException if an input/output error occurs. */ protected void renderColumnHeaders(FacesContext context, TableRowGroup component, ResponseWriter writer) throws IOException { if (component == null) { log("renderColumnHeaders", //NOI18N "Cannot render column headers, TableRowGroup is null"); //NOI18N return; } // Get Map of List objects containing nested TableColumn children. Map map = getColumnHeaderMap(component); // Render nested TableColumn children on separate rows. Theme theme = getTheme(); Table table = component.getTableAncestor(); for (int c = 0; c < map.size(); c++) { // Flag to keep from rendering empty tag when no headers are displayed. boolean renderStartElement = true; // Get List of nested TableColumn children. List list = (List) map.get(new Integer(c)); for (int i = 0; i < list.size(); i++) { TableColumn col = (TableColumn) list.get(i); if (!col.isRendered()) { log("renderColumnHeaders", //NOI18N "TableColumn not rendered, nothing to display"); //NOI18N continue; } // Get group header. UIComponent header = col.getColumnHeader(); if (!(header != null && header.isRendered())) { log("renderColumnHeaders", //NOI18N "Column header not rendered, nothing to display"); //NOI18N continue; } // Render start element. if (renderStartElement) { renderStartElement = false; writer.writeText("\n", null); //NOI18N writer.startElement("tr", component); //NOI18N writer.writeAttribute("id", getId(component, //NOI18N TableRowGroup.COLUMN_HEADER_BAR_ID + NamingContainer.SEPARATOR_CHAR + c), null); // Render style class. // // Note: We must determine if column headers are available for // all or individual TableRowGroup components. That is, there // could be a single column header for all row groups or one for // each group. Thus, headers may only be hidden when there is // more than one column header. if (component.isCollapsed() && table != null && table.getColumnHeadersCount() > 1) { writer.writeAttribute("class", //NOI18N theme.getStyleClass(ThemeStyles.HIDDEN), null); //NOI18N } } // Render header. RenderingUtilities.renderComponent(header, context); } // If start element was rendered, this value will be false. if (!renderStartElement) { writer.endElement("tr"); //NOI18N } } } /** * Render table column footers for TableRowGroup components. *

* Note: Although not currently a requirement, nested TableColumn children * could render column footers that look like: *

     *
     * |   | 1 | 2 |   | 3 | 4 | 5 | 6 |   |
     * | A |   B   | C |       D       | E |
     *
     * 

* In this case, components would be rendered on separate rows. For example, * the HTML would look like: *

     *
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
A12C3456E
BD
* *

* However, the current implementation will render only the first row, which * would look like: *

     *
     * | A | 1 | 2 | C | 3 | 4 | 5 | 6 | E |
     *
     * 
* @param context FacesContext for the current request. * @param component TableRowGroup to be rendered. * @param writer ResponseWriter to which the component should be rendered. * * @exception IOException if an input/output error occurs. */ protected void renderTableColumnFooters(FacesContext context, TableRowGroup component, ResponseWriter writer) throws IOException { if (component == null) { log("renderTableColumnFooters", //NOI18N "Cannot render table column footers, TableRowGroup is null"); //NOI18N return; } // Get Map of List objects containing nested TableColumn children. Map map = getColumnFooterMap(component); // Render nested TableColumn children on separate rows. Theme theme = getTheme(); Table table = component.getTableAncestor(); for (int c = 0; c < map.size(); c++) { // The default is to show one level only. if (c > 0 && table != null && !component.isMultipleTableColumnFooters()) { log("renderTableColumnFooters", //NOI18N "Multiple table column footers not rendered, nothing to display"); //NOI18N break; } // Flag to keep from rendering empty tag when no headers are displayed. boolean renderStartElement = true; // Get List of nested TableColumn children. List list = (List) map.get(new Integer(c)); for (int i = 0; i < list.size(); i++) { TableColumn col = (TableColumn) list.get(i); if (!col.isRendered()) { log("renderTableColumnFooters", //NOI18N "TableColumn not rendered, nothing to display"); //NOI18N continue; } // Get group footer. UIComponent footer = col.getTableColumnFooter(); if (!(footer != null && footer.isRendered())) { log("renderTableColumnFooters", //NOI18N "Table column footer not rendered, nothing to display"); //NOI18N continue; } // Render start element. if (renderStartElement) { renderStartElement = false; writer.writeText("\n", null); //NOI18N writer.startElement("tr", component); //NOI18N writer.writeAttribute("id", getId(component, //NOI18N TableRowGroup.TABLE_COLUMN_FOOTER_BAR_ID + NamingContainer.SEPARATOR_CHAR + c), null); // Render style class. // // Note: We must determine if column footers are available // for all or individual TableRowGroup components. That is, // there could be a single column footer for all row groups // or one for each group. Thus, footers may only be hidden // when there is more than one column footer. if (component.isCollapsed() && table.getColumnHeadersCount() > 1) { writer.writeAttribute("class", //NOI18N theme.getStyleClass(ThemeStyles.HIDDEN), null); //NOI18N } } // Render header. RenderingUtilities.renderComponent(footer, context); } // If start element was rendered, this value will be false. if (!renderStartElement) { writer.endElement("tr"); //NOI18N } } } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Group methods // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /** * Render group footer for TableRowGroup components. * * @param context FacesContext for the current request. * @param component TableRowGroup to be rendered. * @param writer ResponseWriter to which the component should be rendered. * * @exception IOException if an input/output error occurs. */ protected void renderGroupFooter(FacesContext context, TableRowGroup component, ResponseWriter writer) throws IOException { if (component == null) { log("renderGroupFooter", //NOI18N "Cannot render group footer, TableRowGroup is null"); //NOI18N return; } // Get group footer. UIComponent footer = component.getGroupFooter(); if (!(footer != null && footer.isRendered())) { log("renderGroupFooter", //NOI18N "Group footer not rendered, nothing to display"); //NOI18N return; } Theme theme = getTheme(); writer.writeText("\n", null); //NOI18N writer.startElement("tr", component); //NOI18N writer.writeAttribute("id", getId(component, //NOI18N TableRowGroup.GROUP_FOOTER_BAR_ID), null); // Render style class. if (component.isCollapsed()) { writer.writeAttribute("class", //NOI18N theme.getStyleClass(ThemeStyles.HIDDEN), null); //NOI18N } // Render footer. RenderingUtilities.renderComponent(footer, context); writer.endElement("tr"); //NOI18N } /** * Render group header for TableRowGroup components. * * @param context FacesContext for the current request. * @param component TableRowGroup to be rendered. * @param writer ResponseWriter to which the component should be rendered. * * @exception IOException if an input/output error occurs. */ protected void renderGroupHeader(FacesContext context, TableRowGroup component, ResponseWriter writer) throws IOException { if (component == null) { log("renderGroupHeader", //NOI18N "Cannot render group header, TableRowGroup is null"); //NOI18N return; } // Get group header. UIComponent header = component.getGroupHeader(); if (!(header != null && header.isRendered())) { log("renderGroupHeader", //NOI18N "Group header not rendered, nothing to display"); //NOI18N return; } Theme theme = getTheme(); writer.writeText("\n", null); //NOI18N writer.startElement("tr", component); //NOI18N writer.writeAttribute("id", getId(component, //NOI18N TableRowGroup.GROUP_HEADER_BAR_ID), null); // Render header. RenderingUtilities.renderComponent(header, context); writer.endElement("tr"); //NOI18N } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Enclosing tag methods // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /** * Render enclosing tag for TableRowGroup components. * * @param context FacesContext for the current request. * @param component TableRowGroup to be rendered. * @param writer ResponseWriter to which the component should be rendered. * @param index The current row index. * * @exception IOException if an input/output error occurs. */ protected void renderEnclosingTagStart(FacesContext context, TableRowGroup component, ResponseWriter writer, int index) throws IOException { if (component == null) { log("renderEnclosingTagStart", //NOI18N "Cannot render enclosing tag, TableRowGroup is null"); //NOI18N return; } Theme theme = getTheme(); writer.writeText("\n", null); //NOI18N writer.startElement("tr", component); //NOI18N writer.writeAttribute("id", component.getClientId(context), null); //NOI18N // Get style class for nonempty table. String styleClasses[] = getRowStyleClasses(component); String styleClass = (index > -1 && styleClasses.length > 0) ? styleClasses[index % styleClasses.length] : null; // Get selected style class. if (component.isSelected()) { String s = theme.getStyleClass(ThemeStyles.TABLE_SELECT_ROW); styleClass = (styleClass != null) ? styleClass + " " + s : s; //NOI18N } // Get collapsed style class. if (component.isCollapsed()) { String s = theme.getStyleClass(ThemeStyles.HIDDEN); styleClass = (styleClass != null) ? styleClass + " " + s : s; //NOI18N } // Render style class. RenderingUtilities.renderStyleClass(context, writer, component, styleClass); // Render tooltip. if (component.getToolTip() != null) { writer.writeAttribute("title", component.getToolTip(), "toolTip"); //NOI18N } // Render pass through attributes. RenderingUtilities.writeStringAttributes(component, writer, stringAttributes); } /** * Render enclosing tag for TableRowGroup components. * * @param writer ResponseWriter to which the component should be rendered. * * @exception IOException if an input/output error occurs. */ protected void renderEnclosingTagEnd(ResponseWriter writer) throws IOException { writer.endElement("tr"); //NOI18N } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Private methods // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /** * Helper method to get Map of List objects containing nested TableColumn * children. *

* Note: Although not currently a requirement, nested TableColumn children * could render column footers that look like: *

     *
     * |   | 1 | 2 |   | 3 | 4 | 5 | 6 |   |
     * | A |   B   | C |       D       | E |
     *
     * 

* In this case, components would be rendered on separate rows. Thus, we * need a map that contains List objects like so: *

     * 
     * Key (row) 0: A, 1, 2, C, 3, 4, 5, 6, E
     * Key (row) 1: B, D
     * 
     * 

* Obtaining the List for key 0 tells the renderer that A, 1, 2, C, 3, 4, 5, * 6, and E should be rendered for the first row. Obtaining the List for key * 1, tells the renderer that B and D should be rendered for the next row. * And so on... *

* @param component TableRowGroup to be rendered. * @return A Map of nested TableColumn children. */ private Map getColumnFooterMap(TableRowGroup component) { Map map = getColumnHeaderMap(component); // Start with header map. if (map.size() == 0) { log("getColumnFooterMap", "Cannot obtain column footer map"); //NOI18N return map; } // Invert map. HashMap newMap = new HashMap(); for (int i = 0; i < map.size(); i++) { newMap.put(new Integer(i), map.get(new Integer(map.size() - i - 1))); } // Move all non-nested components to the top row. List newList = (List) newMap.get(new Integer(0)); for (int c = 1; c < newMap.size(); c++) { // Top row is set already. List list = (List) newMap.get(new Integer(c)); for (int i = list.size() - 1; i >= 0; i--) { // Start with last component. TableColumn col = (TableColumn) list.get(i); if (col.getTableColumnChildren().hasNext()) { // Do not move TableColumn components with nested children. continue; } // Get colspan of all previous components. int colspan = 0; for (int k = i - 1; k >= 0; k--) { TableColumn prevCol = (TableColumn) list.get(k); if (prevCol.getTableColumnChildren().hasNext()) { // Count only nested TableColumn components. Other // components have not been moved to the to row, yet. colspan += prevCol.getColumnCount(); } } // Set new position in the top row. newList.add(colspan, col); list.remove(i); } } return newMap; } /** * Helper method to get Map of List objects containing nested TableColumn * children. *

* Note: Nested TableColumn children may be rendered on separate rows. For * example, to render column footers that look like the following: *

     *
     * | A |   B   | C |       D       | E |
     * |   | 1 | 2 |   | 3 | 4 | 5 | 6 |   |
     *
     * 

* In this case, components would be rendered on separate rows. Thus, we * need a map that contains List objects like so: *

     * 
     * Key (row) 0: A, B, C, D, E
     * Key (row) 1: 1, 2, 3, 4, 5, 6 
     * 
     * 

* Obtaining the List for key 0 tells the renderer that A, B, C, D, and E * should be rendered for the first row. Obtaining the List for key 1, tells * the renderer that 1, 2, 3, 4, 5, and 6 should be rendered for the next * row. And so on... *

* @param component TableRowGroup to be rendered. * @return A Map of nested TableColumn children. */ private Map getColumnHeaderMap(TableRowGroup component) { HashMap map = new HashMap(); if (component == null) { log("getColumnHeaderMap", //NOI18N "Cannot obtain column header map, TableRowGroup is null"); //NOI18N return map; } Iterator kids = component.getTableColumnChildren(); while (kids.hasNext()) { TableColumn col = (TableColumn) kids.next(); initColumnHeaderMap(col, map, 0); } return map; } /** * Get component id. * * @param component The parent UIComponent component. * @param id The id of the the component to be rendered. */ private String getId(UIComponent component, String id) { String clientId = component.getClientId(FacesContext.getCurrentInstance()); return clientId + NamingContainer.SEPARATOR_CHAR + id; } /** Helper method to get Theme objects. */ private Theme getTheme() { return ThemeUtilities.getTheme(FacesContext.getCurrentInstance()); } /** * Helper method to get an array of stylesheet classes to be applied to each * row, in the order specified. *

* Note: This is a comma-delimited list of CSS style classes that will be * applied to the rows of this table. A space separated list of classes may * also be specified for any individual row. These styles are applied, in * turn, to each row in the table. For example, if the list has two * elements, the first style class in the list is applied to the first row, * the second to the second row, the first to the third row, the second to * the fourth row, etc. In other words, we keep iterating through the list * until we reach the end, and then we start at the beginning again. *

* @param component TableRowGroup component being rendered. * @return An array of stylesheet classes. */ private String[] getRowStyleClasses(TableRowGroup component) { String values = (component != null) ? (String) component.getStyleClasses() : null; if (values == null) { return new String[0]; } values = values.trim(); ArrayList list = new ArrayList(); while (values.length() > 0) { int comma = values.indexOf(","); //NOI18N if (comma >= 0) { list.add(values.substring(0, comma).trim()); values = values.substring(comma + 1); } else { list.add(values.trim()); values = ""; //NOI18N } } String results[] = new String[list.size()]; return ((String[]) list.toArray(results)); } /** * Helper method to initialize Map of List objects containing nested * TableColumn children. * * @param component TableColumn to be rendered. * @param map Map to save component List. * @param level The current level of the component tree. */ private void initColumnHeaderMap(TableColumn component, Map map, int level) { if (component == null) { log("initColumnHeaderMap", //NOI18N "Cannot initialize column header map, TableColumn is null"); //NOI18N return; } // Get new List for nested TableColumn children. Iterator kids = component.getTableColumnChildren(); if (kids.hasNext()) { ArrayList newList = new ArrayList(); while (kids.hasNext()) { TableColumn col = (TableColumn) kids.next(); if (!col.isRendered()) { continue; } initColumnHeaderMap(col, map, level + 1); } } // Create a new List if needed. Integer key = new Integer(level); List list = (List) map.get(key); if (list == null) { list = new ArrayList(); } list.add(component); // Save component in List. map.put(key, list); // Save List in map. } /** * Log fine messages. */ private void log(String method, String message) { // Get class. Class clazz = this.getClass(); if (LogUtil.fineEnabled(clazz)) { // Log method name and message. LogUtil.fine(clazz, clazz.getName() + "." + method + ": " + message); //NOI18N } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy