Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   /*
    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    *
    * Copyright (c) 1997-2012 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 javax.faces.component;
  
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
  
  
  
  
  // ------------------------------------------------------------- Private Classes
  // Private class to represent saved state information
  

UIData is a UIComponent that supports data binding to a collection of data objects represented by a javax.faces.model.DataModel instance, which is the current value of this component itself (typically established via a javax.el.ValueExpression). During iterative processing over the rows of data in the data model, the object for the current row is exposed as a request attribute under the key specified by the var property.

Only children of type UIColumn should be processed by renderers associated with this component.

By default, the rendererType property is set to javax.faces.Table. This value can be changed by calling the setRendererType() method.

  
  
 public class UIData extends UIComponentBase
       implements NamingContainerUniqueIdVendor {
 
     // ------------------------------------------------------ Manifest Constants
 

    

The standard component type for this component.

 
     public static final String COMPONENT_TYPE = "javax.faces.Data";


    

The standard component family for this component.

 
     public static final String COMPONENT_FAMILY = "javax.faces.Data";
 
     // ------------------------------------------------------------ Constructors
 

    

Create a new UIData instance with default property values.

 
     public UIData() {
 
         super();
         setRendererType("javax.faces.Table");
 
     }
 
     // ------------------------------------------------------ Instance Variables
 

    
Properties that are tracked by state saving.
 
     enum PropertyKeys {
        

The first row number (zero-relative) to be displayed.

 
         first,

        

The zero-relative index of the current row number, or -1 for no current row association.

 
         rowIndex,

        

The number of rows to display, or zero for all remaining rows in the table.

 
         rows,

        

This map contains SavedState instances for each descendant component, keyed by the client identifier of the descendant. Because descendant client identifiers will contain the rowIndex value of the parent, per-row state information is actually preserved.

 
         saved,

        

The local value of this UIComponent.

 
         value,

        

The request scope attribute under which the data object for the current row will be exposed when iterating.

 
         var,

        
 
         lastId,
     
        
 
         rowStatePreserved
     }


    

The javax.faces.model.DataModel associated with this component, lazily instantiated if requested. This object is not part of the saved and restored state of the component.

 
     private DataModel model = null;


    

During iteration through the rows of this table, This ivar is used to store the previous "var" value for this instance. When the row iteration is complete, this value is restored to the request map.

 
     private Object oldVar;


    

Holds the base client ID that will be used to generate per-row client IDs (this will be null if this UIData is nested within another).

This is not part of the component state.

 
     private String baseClientId = null;


    

Length of the cached baseClientId plus one for the UINamingContainer.getSeparatorChar(javax.faces.context.FacesContext).

This is not part of the component state.

 
     private int baseClientIdLength;


    

StringBuilder used to build per-row client IDs.

This is not part of the component state.

 
     private StringBuilder clientIdBuilder = null;


    

Flag indicating whether or not this UIData instance is nested within another UIData instance

This is not part of the component state.

 
     private Boolean isNested = null;
 
     private Map<StringObject_rowDeltaStates = new HashMap<StringObject>();
     private Map<StringObject_rowTransientStates = new HashMap<StringObject>();
     
     private Object _initialDescendantFullComponentState = null;
 
     // -------------------------------------------------------------- Properties
 
 
     public String getFamily() {
 
         return ();
 
     }


    

Return the zero-relative row number of the first row to be displayed.

 
     public int getFirst() {
 
         return (IntegergetStateHelper().eval(., 0);
 
     }


    

Set the zero-relative row number of the first row to be displayed.

Parameters:
first New first row number
Throws:
java.lang.IllegalArgumentException if first is negative
 
     public void setFirst(int first) {
 
         if (first < 0) {
             throw new IllegalArgumentException(String.valueOf(first));
         }
         getStateHelper().put(.first);
 
     }


    

Return the footer facet of this component (if any). A convenience method for getFacet("footer").

 
     public UIComponent getFooter() {
 
         return getFacet("footer");
 
     }


    

Set the footer facet of this component. A convenience method for getFacets().put("footer", footer).

Parameters:
footer the new footer facet
Throws:
java.lang.NullPointerException if footer is null
 
     public void setFooter(UIComponent footer) {
 
         getFacets().put("footer"footer);
 
     }


    

Return the header facet of this component (if any). A convenience method for getFacet("header").

 
     public UIComponent getHeader() {
 
         return getFacet("header");
 
     }


    

Set the header facet of this component. A convenience method for getFacets().put("header", header).

Parameters:
header the new header facet
Throws:
java.lang.NullPointerException if header is null
 
     public void setHeader(UIComponent header) {
 
         getFacets().put("header"header);
 
     }


    

Return a flag indicating whether there is rowData available at the current rowIndex. If no wrappedData is available, return false.

Throws:
javax.faces.FacesException if an error occurs getting the row availability
 
     public boolean isRowAvailable() {
 
         return (getDataModel().isRowAvailable());
 
     }


    

Return the number of rows in the underlying data model. If the number of available rows is unknown, return -1.

Throws:
javax.faces.FacesException if an error occurs getting the row count
 
     public int getRowCount() {
 
         return (getDataModel().getRowCount());
 
     }


    

Return the data object representing the data for the currently selected row index, if any.

Throws:
javax.faces.FacesException if an error occurs getting the row data
java.lang.IllegalArgumentException if now row data is available at the currently specified row index
 
     public Object getRowData() {
 
         return (getDataModel().getRowData());
 
     }


    

Return the zero-relative index of the currently selected row. If we are not currently positioned on a row, return -1. This property is not enabled for value binding expressions.

Throws:
javax.faces.FacesException if an error occurs getting the row index
 
     public int getRowIndex() {
 
         return (IntegergetStateHelper().eval(., -1);
 
     }


    

Set the zero relative index of the current row, or -1 to indicate that no row is currently selected, by implementing the following algorithm. It is possible to set the row index at a value for which the underlying data collection does not contain any row data. Therefore, callers may use the isRowAvailable() method to detect whether row data will be available for use by the getRowData() method.

To support transient state among descendents, please consult the specification for setRowStatePreserved(boolean), which details the requirements for setRowIndex() when the rowStatePreserved JavaBeans property is set to true.

  • Save current state information for all descendant components (as described below).
  • Store the new row index, and pass it on to the javax.faces.model.DataModel associated with this UIData instance.
  • If the new rowIndex value is -1:
    • If the var property is not null, remove the corresponding request scope attribute (if any).
    • Reset the state information for all descendant components (as described below).
  • If the new rowIndex value is not -1:
    • If the var property is not null, call getRowData() and expose the resulting data object as a request scope attribute whose key is the var property value.
    • Reset the state information for all descendant components (as described below).

To save current state information for all descendant components, UIData must maintain per-row information for each descendant as follows:

  • If the descendant is an instance of EditableValueHolder, save the state of its localValue property.
  • If the descendant is an instance of EditableValueHolder, save the state of the localValueSet property.
  • If the descendant is an instance of EditableValueHolder, save the state of the valid property.
  • If the descendant is an instance of EditableValueHolder, save the state of the submittedValue property.

To restore current state information for all descendant components, UIData must reference its previously stored information for the current rowIndex and call setters for each descendant as follows:

  • If the descendant is an instance of EditableValueHolder, restore the value property.
  • If the descendant is an instance of EditableValueHolder, restore the state of the localValueSet property.
  • If the descendant is an instance of EditableValueHolder, restore the state of the valid property.
  • If the descendant is an instance of EditableValueHolder, restore the state of the submittedValue property.

Parameters:
rowIndex The new row index value, or -1 for no associated row
Throws:
javax.faces.FacesException if an error occurs setting the row index
java.lang.IllegalArgumentException if rowIndex is less than -1
 
     public void setRowIndex(int rowIndex)
     {
         if (isRowStatePreserved())
         {
             setRowIndexRowStatePreserved(rowIndex);
         }
         else
         {
             setRowIndexWithoutRowStatePreserved(rowIndex);
         }
     }
 
     private void setRowIndexWithoutRowStatePreserved(int rowIndex){
         // Save current state for the previous row index
         saveDescendantState();
 
         // Update to the new row index        
         //this.rowIndex = rowIndex;
         getStateHelper().put(.rowIndex);
         DataModel localModel = getDataModel();
         localModel.setRowIndex(rowIndex);
         
         // if rowIndex is -1, clear the cache
         if (rowIndex == -1) {
             setDataModel(null);
         }
         
         // Clear or expose the current row data as a request scope attribute
         String var = (StringgetStateHelper().get(.);
         if (var != null) {
             Map<StringObjectrequestMap =
                   getFacesContext().getExternalContext().getRequestMap();
             if (rowIndex == -1) {
                  = requestMap.remove(var);
             } else if (isRowAvailable()) {
                 requestMap.put(vargetRowData());
             } else {
                 requestMap.remove(var);
                 if (null != ) {
                     requestMap.put(var);
                      = null;
                 }
             }
         }
 
         // Reset current state information for the new row index
         restoreDescendantState();
 
     }
     
     private void setRowIndexRowStatePreserved(int rowIndex)
     {
         if (rowIndex < -1)
         {
             throw new IllegalArgumentException("rowIndex is less than -1");
         }
 
         if (getRowIndex() == rowIndex)
         {
             return;
         }
 
         FacesContext facesContext = getFacesContext();
 
         if ( != null)
         {
             //Just save the row
             Map<StringObjectsm = saveFullDescendantComponentStates(facesContextnullgetChildren().iterator(), false);
             if (sm != null && !sm.isEmpty())
             {
                 .put(getContainerClientId(facesContext), sm);
             }
             if (getRowIndex() != -1)
             {
                 .put(getContainerClientId(facesContext), saveTransientDescendantComponentStates(facesContextnullgetChildren().iterator(), false));
             }
         }
 
         // Update to the new row index        
         //this.rowIndex = rowIndex;
         getStateHelper().put(.rowIndex);
         DataModel localModel = getDataModel();
         localModel.setRowIndex(rowIndex);
         
         // if rowIndex is -1, clear the cache
         if (rowIndex == -1) {
             setDataModel(null);
         }
         
         // Clear or expose the current row data as a request scope attribute
         String var = (StringgetStateHelper().get(.);
         if (var != null) {
             Map<StringObjectrequestMap =
                   getFacesContext().getExternalContext().getRequestMap();
             if (rowIndex == -1) {
                  = requestMap.remove(var);
             } else if (isRowAvailable()) {
                 requestMap.put(vargetRowData());
             } else {
                 requestMap.remove(var);
                 if (null != ) {
                     requestMap.put(var);
                      = null;
                 }
             }
         }
 
         if ( != null)
         {
             Object rowState = .get(getContainerClientId(facesContext));
             if (rowState == null)
             {
                 //Restore as original
                 restoreFullDescendantComponentStates(facesContextgetChildren().iterator(), false);
             }
             else
             {
                 //Restore first original and then delta
                 restoreFullDescendantComponentDeltaStates(facesContextgetChildren().iterator(), rowStatefalse);
             }
             if (getRowIndex() == -1)
             {
                 restoreTransientDescendantComponentStates(facesContextgetChildren().iterator(), nullfalse);
             }
             else
             {
                 rowState = .get(getContainerClientId(facesContext));
                 if (rowState == null)
                 {
                     restoreTransientDescendantComponentStates(facesContextgetChildren().iterator(), nullfalse);
                 }
                 else
                 {
                     restoreTransientDescendantComponentStates(facesContextgetChildren().iterator(), (Map<StringObject>) rowStatefalse);
                 }
             }
         }
     }

    

Return the number of rows to be displayed, or zero for all remaining rows in the table. The default value of this property is zero.

 
     public int getRows() {
 
 
         return (IntegergetStateHelper().eval(., 0);
 
     }


    

Set the number of rows to be displayed, or zero for all remaining rows in the table.

Parameters:
rows New number of rows
Throws:
java.lang.IllegalArgumentException if rows is negative
 
     public void setRows(int rows) {
 
         if (rows < 0) {
             throw new IllegalArgumentException(String.valueOf(rows));
         }
         getStateHelper().put(.rows);
 
     }


    

Return the request-scope attribute under which the data object for the current row will be exposed when iterating. This property is not enabled for value binding expressions.

 
     public String getVar() {
 
         return (StringgetStateHelper().get(.);
 
     }


    

Set the request-scope attribute under which the data object for the current row wil be exposed when iterating.

Parameters:
var The new request-scope attribute name
 
     public void setVar(String var) {
 
         getStateHelper().put(.var);
 
     }
    
    

Return the value of the rowStatePreserved JavaBeans property. See setRowStatePreserved(boolean).

Since:
2.1
 
 
     public boolean isRowStatePreserved()
     {
         return b == null ? false : b.booleanValue(); 
     }

    

If this property is set to true, the UIData must take steps to ensure that modifications to its iterated children will be preserved on a per-row basis. This allows applications to modify component properties, such as the style-class, for a specific row, rather than having such modifications apply to all rows.

To accomplish this, UIData must call StateHolder.saveState(javax.faces.context.FacesContext) and TransientStateHolder.saveTransientState(javax.faces.context.FacesContext) on its children to capture their state on exiting each row. When re-entering the row, StateHolder.restoreState(javax.faces.context.FacesContext,java.lang.Object) and TransientStateHolder.restoreTransientState(javax.faces.context.FacesContext,java.lang.Object) must be called in order to reinitialize the children to the correct state for the new row. All of this action must take place during the processing of setRowIndex(int).

Users should consider enabling this feature for cases where it is necessary to modify properties of UIData's children in a row-specific way. Note, however, that row-level state saving/restoring does add overhead. As such, this feature should be used judiciously.

Since:
2.1
 
     
     public void setRowStatePreserved(boolean preserveComponentState)
     {
         getStateHelper().put(.preserveComponentState);
     }
 
 
     // ----------------------------------------------------- StateHolder Methods
 



    

Return the value of the UIData. This value must either be be of type javax.faces.model.DataModel, or a type that can be adapted into a javax.faces.model.DataModel. UIData will automatically adapt the following types:

  • Arrays
  • java.util.List
  • java.sql.ResultSet
  • javax.servlet.jsp.jstl.sql.Result

All other types will be adapted using the javax.faces.model.ScalarDataModel class, which will treat the object as a single row of data.

 
     public Object getValue() {
 
         return getStateHelper().eval(.);
 
     }


    

Set the value of the UIData. This value must either be be of type javax.faces.model.DataModel, or a type that can be adapted into a javax.faces.model.DataModel.

Parameters:
value the new value
 
     public void setValue(Object value) {
         setDataModel(null);
         getStateHelper().put(.value);
 
     }
 
     // ----------------------------------------------------- UIComponent Methods
 

    

If "name" is something other than "value", "var", or "rowIndex", rely on the superclass conversion from ValueBinding to ValueExpression.

Deprecated:
This has been replaced by setValueExpression(java.lang.String,javax.el.ValueExpression).
Parameters:
name Name of the attribute or property for which to set a javax.faces.el.ValueBinding
binding The javax.faces.el.ValueBinding to set, or null to remove any currently set javax.faces.el.ValueBinding
Throws:
java.lang.IllegalArgumentException if name is one of id, parent, var, or rowIndex
java.lang.NullPointerException if name is null
 
     public void setValueBinding(String nameValueBinding binding) {
 
         if ("value".equals(name)) {
             setDataModel(null);
         } else if ("var".equals(name) || "rowIndex".equals(name)) {
             throw new IllegalArgumentException();
         }
         super.setValueBinding(namebinding);
 
     }

    

Set the javax.el.ValueExpression used to calculate the value for the specified attribute or property name, if any. In addition, if a javax.el.ValueExpression is set for the value property, remove any synthesized javax.faces.model.DataModel for the data previously bound to this component.

Parameters:
name Name of the attribute or property for which to set a javax.el.ValueExpression
binding The javax.el.ValueExpression to set, or null to remove any currently set javax.el.ValueExpression
Throws:
java.lang.IllegalArgumentException if name is one of id, parent, var, or rowIndex
java.lang.NullPointerException if name is null
Since:
1.2
 
     public void setValueExpression(String nameValueExpression binding) {
 
         if ("value".equals(name)) {
             this. = null;
         } else if ("var".equals(name) || "rowIndex".equals(name)) {
             throw new IllegalArgumentException();
         }
         super.setValueExpression(namebinding);
 
     }

    

Return a client identifier for this component that includes the current value of the rowIndex property, if it is not set to -1. This implies that multiple calls to getClientId() may return different results, but ensures that child components can themselves generate row-specific client identifiers (since UIData is a NamingContainer).

Throws:
java.lang.NullPointerException if context is null
 
     public String getClientId(FacesContext context) {
 
         if (context == null) {
             throw new NullPointerException();
         }
 
         // If baseClientId and clientIdBuilder are both null, this is the
         // first time that getClientId() has been called.
         // If we're not nested within another UIData, then:
         //   - create a new StringBuilder assigned to clientIdBuilder containing
         //   our client ID.
         //   - toString() the builder - this result will be our baseClientId
         //     for the duration of the component
         //   - append UINamingContainer.getSeparatorChar() to the builder
         //  If we are nested within another UIData, then:
         //   - create an empty StringBuilder that will be used to build
         //     this instance's ID
         if ( == null &&  == null) {
             if (!isNestedWithinIterator()) {
                  = new StringBuilder(super.getClientId(context));
                  = .toString();
                  = (.length() + 1);
                 .append(UINamingContainer.getSeparatorChar(context));
                 .setLength();
             } else {
                  = new StringBuilder();
             }
         }
         int rowIndex = getRowIndex();
         if (rowIndex >= 0) {
             String cid;
             if (!isNestedWithinIterator()) {
                 // we're not nested, so the clientIdBuilder is already
                 // primed with clientID +
                 // UINamingContainer.getSeparatorChar().  Append the
                 // current rowIndex, and toString() the builder.  reset
                 // the builder to it's primed state.
                 cid = .append(rowIndex).toString();
                 .setLength();
             } else {
                 // we're nested, so we have to build the ID from scratch
                 // each time.  Reuse the same clientIdBuilder instance
                 // for each call by resetting the length to 0 after
                 // the ID has been computed.
                 cid = .append(super.getClientId(context))
                       .append(UINamingContainer.getSeparatorChar(context)).append(rowIndex)
                       .toString();
                 .setLength(0);
             }
             return (cid);
         } else {
             if (!isNestedWithinIterator()) {
                 // Not nested and no row available, so just return our baseClientId
                 return ();
             } else {
                 // nested and no row available, return the result of getClientId().
                 // this is necessary as the client ID will reflect the row that
                 // this table represents
                 return super.getClientId(context);
             }
         }
 
     }

    

Override behavior from UIComponentBase.invokeOnComponent(javax.faces.context.FacesContext,java.lang.String,javax.faces.component.ContextCallback) to provide special care for positioning the data properly before finding the component and invoking the callback on it. If the argument clientId is equal to this.getClientId() simply invoke the contextCallback, passing the context argument and this as arguments, and return true. If the argument clientId is not equal to this.getClientId(), inspect each of the facet children of this UIData instance and for each one, compare its clientId with the argument clientId. If there is a match, invoke the contextCallback, passing the context argument and this as arguments, and return true. Otherwise, attempt to extract a rowIndex from the clientId. For example, if the argument clientId was form:data:3:customerHeader the rowIndex would be 3. Let this value be called newIndex. The current rowIndex of this instance must be saved aside and restored before returning in all cases, regardless of the outcome of the search or if any exceptions are thrown in the process.

The implementation of this method must never return true if setting the rowIndex of this instance to be equal to newIndex causes this instance to return false from isRowAvailable().

Throws:
java.lang.NullPointerException
javax.faces.FacesException Also throws FacesException if any exception is thrown when deriving the rowIndex from the argument clientId.
Since:
1.2
 
     public boolean invokeOnComponent(FacesContext contextString clientId,
                                      ContextCallback callback)
           throws FacesException {
         if (null == context || null == clientId || null == callback) {
             throw new NullPointerException();
         }
 
         String myId = super.getClientId(context);
         boolean found = false;
         if (clientId.equals(myId)) {
             try {
                 this.pushComponentToEL(context);
                 callback.invokeContextCallback(contextthis);
                 return true;
             }
             catch (Exception e) {
                 throw new FacesException(e);
             }
             finally {
                 this.popComponentFromEL(context);
             }
         }
 
         // check the facets, if any, of UIData
         if (this.getFacetCount() > 0) {
             for (UIComponent c : this.getFacets().values()) {
                 if (clientId.equals(c.getClientId(context))) {
                     callback.invokeContextCallback(contextc);
                     return true;
                 }
             }
         }
 
         // check column level facets, if any
         if (this.getChildCount() > 0) {
             for (UIComponent column : this.getChildren()) {
                 if (column instanceof UIColumn) {
                     if (column.getFacetCount() > 0) {
                         for (UIComponent facet : column.getFacets().values()) {
                             if (facet.invokeOnComponent(contextclientIdcallback)) {
                                 return true;
                             }
                         }
                     }
                 }
             }
         }
 
         /*
          * Check if we are looking for a component that is part of the 
          * actual skeleton.
          */
         if (this.getChildCount() > 0) {
             for (UIComponent column : this.getChildren()) {
                 if (column instanceof UIColumn) {
                     if (column.invokeOnComponent(contextclientIdcallback)) {
                         return true;
                     }
                 }
             }
         }
 
         int lastSepnewRowsavedRowIndex = this.getRowIndex();
         try {
             char sepChar = UINamingContainer.getSeparatorChar(context);
             // If we need to strip out the rowIndex from our id
             // PENDING(edburns): is this safe with respect to I18N?
             if (myId.endsWith(sepChar + Integer.toString(savedRowIndex, 10))) {
                 lastSep = myId.lastIndexOf(sepChar);
                 assert (-1 != lastSep);
                 myId = myId.substring(0, lastSep);
             }
 
             // myId will be something like form:outerData for a non-nested table,
             // and form:outerData:3:data for a nested table.
             // clientId will be something like form:outerData:3:outerColumn
             // for a non-nested table.  clientId will be something like
             // outerData:3:data:3:input for a nested table.
             if (clientId.startsWith(myId)) {
                 int preRowIndexSeppostRowIndexSep;
 
                 if (-1 != (preRowIndexSep =
                       clientId.indexOf(sepChar,
                                       myId.length()))) {
                    // Check the length
                    if (++preRowIndexSep < clientId.length()) {
                        if (-1 != (postRowIndexSep =
                              clientId.indexOf(sepChar,
                                               preRowIndexSep + 1))) {
                            try {
                                newRow = Integer
                                      .valueOf(clientId.substring(preRowIndexSep,
                                                                  postRowIndexSep))
                                      .intValue();
                            } catch (NumberFormatException ex) {
                                // PENDING(edburns): I18N
                                String message =
                                      "Trying to extract rowIndex from clientId \'"
                                      +
                                      clientId
                                      + "\' "
                                      + ex.getMessage();
                                throw new NumberFormatException(message);
                            }
                            this.setRowIndex(newRow);
                            if (this.isRowAvailable()) {
                                found = super.invokeOnComponent(context,
                                                                clientId,
                                                                callback);
                            }
                        }
                    }
                }
            }
        }
        catch (FacesException fe) {
            throw fe;
        }
        catch (Exception e) {
            throw new FacesException(e);
        }
        finally {
            this.setRowIndex(savedRowIndex);
        }
        return found;
    }


    

Override the default UIComponentBase.queueEvent(javax.faces.event.FacesEvent) processing to wrap any queued events in a wrapper so that we can reset the current row index in broadcast().

Parameters:
event javax.faces.event.FacesEvent to be queued
Throws:
java.lang.IllegalStateException if this component is not a descendant of a UIViewRoot
java.lang.NullPointerException if event is null
    public void queueEvent(FacesEvent event) {
        super.queueEvent(new WrapperEvent(this, event, getRowIndex()));
    }


    

Override the default UIComponentBase.broadcast(javax.faces.event.FacesEvent) processing to unwrap any wrapped javax.faces.event.FacesEvent and reset the current row index, before the event is actually broadcast. For events that we did not wrap (in queueEvent()), default processing will occur.

Parameters:
event The javax.faces.event.FacesEvent to be broadcast
Throws:
javax.faces.event.AbortProcessingException Signal the JavaServer Faces implementation that no further processing on the current event should be performed
java.lang.IllegalArgumentException if the implementation class of this javax.faces.event.FacesEvent is not supported by this component
java.lang.NullPointerException if event is null
    public void broadcast(FacesEvent event)
          throws AbortProcessingException {
        if (!(event instanceof WrapperEvent)) {
            super.broadcast(event);
            return;
        }
        FacesContext context = FacesContext.getCurrentInstance();
        // Set up the correct context and fire our wrapped event
        WrapperEvent revent = (WrapperEventevent;
        if (isNestedWithinIterator()) {
            setDataModel(null);
        }
        int oldRowIndex = getRowIndex();
        setRowIndex(revent.getRowIndex());
        FacesEvent rowEvent = revent.getFacesEvent();
        UIComponent source = rowEvent.getComponent();
        UIComponent compositeParent = null;
        try {
            if (!UIComponent.isCompositeComponent(source)) {
                compositeParent = UIComponent.getCompositeComponentParent(source);
            }
            if (compositeParent != null) {
                compositeParent.pushComponentToEL(contextnull);
            }
            source.pushComponentToEL(contextnull);
            source.broadcast(rowEvent);
        } finally {
            source.popComponentFromEL(context);
            if (compositeParent != null) {
                compositeParent.popComponentFromEL(context);
            }
        }
        setRowIndex(oldRowIndex);
    }

    

In addition to the default behavior, ensure that any saved per-row state for our child input components is discarded unless it is needed to rerender the current page with errors.

Parameters:
context FacesContext for the current request
Throws:
java.io.IOException if an input/output error occurs while rendering
java.lang.NullPointerException if context is null
    public void encodeBegin(FacesContext contextthrows IOException {
        preEncode(context);
        super.encodeBegin(context);
    }


    

Override the default UIComponentBase.processDecodes(javax.faces.context.FacesContext) processing to perform the following steps.

  • If the rendered property of this UIComponent is false, skip further processing.
  • Set the current rowIndex to -1.
  • Call the processDecodes() method of all facets of this UIData, in the order determined by a call to getFacets().keySet().iterator().
  • Call the processDecodes() method of all facets of the UIColumn children of this UIData.
  • Iterate over the set of rows that were included when this component was rendered (i.e. those defined by the first and rows properties), performing the following processing for each row:
    • Set the current rowIndex to the appropriate value for this row.
    • If isRowAvailable() returns true, iterate over the children components of each UIColumn child of this UIData component, calling the processDecodes() method for each such child.
  • Set the current rowIndex to -1.
  • Call the decode() method of this component.
  • If a RuntimeException is thrown during decode processing, call javax.faces.context.FacesContext.renderResponse() and re-throw the exception.

Parameters:
context javax.faces.context.FacesContext for the current request
Throws:
java.lang.NullPointerException if context is null
    public void processDecodes(FacesContext context) {
        if (context == null) {
            throw new NullPointerException();
        }
        if (!isRendered()) {
            return;
        }
        pushComponentToEL(contextthis);
        preDecode(context);
        iterate(context.);
        decode(context);
        popComponentFromEL(context);
    }


    

Override the default UIComponentBase.processValidators(javax.faces.context.FacesContext) processing to perform the following steps.

  • If the rendered property of this UIComponent is false, skip further processing.
  • Set the current rowIndex to -1.
  • Call the processValidators() method of all facets of this UIData, in the order determined by a call to getFacets().keySet().iterator().
  • Call the processValidators() method of all facets of the UIColumn children of this UIData.
  • Iterate over the set of rows that were included when this component was rendered (i.e. those defined by the first and rows properties), performing the following processing for each row:
    • Set the current rowIndex to the appropriate value for this row.
    • If isRowAvailable() returns true, iterate over the children components of each UIColumn child of this UIData component, calling the processValidators() method for each such child.
  • Set the current rowIndex to -1.

Parameters:
context javax.faces.context.FacesContext for the current request
Throws:
java.lang.NullPointerException if context is null
    public void processValidators(FacesContext context) {
        if (context == null) {
            throw new NullPointerException();
        }
        if (!isRendered()) {
            return;
        }
        pushComponentToEL(contextthis);
        Application app = context.getApplication();
        app.publishEvent(contextPreValidateEvent.classthis);
        preValidate(context);
        iterate(context.);
        app.publishEvent(contextPostValidateEvent.classthis);
        popComponentFromEL(context);
    }


    

Override the default UIComponentBase.processUpdates(javax.faces.context.FacesContext) processing to perform the following steps.

  • If the rendered property of this UIComponent is false, skip further processing.
  • Set the current rowIndex to -1.
  • Call the processUpdates() method of all facets of this UIData, in the order determined by a call to getFacets().keySet().iterator().
  • Call the processUpdates() method of all facets of the UIColumn children of this UIData.
  • Iterate over the set of rows that were included when this component was rendered (i.e. those defined by the first and rows properties), performing the following processing for each row:
    • Set the current rowIndex to the appropriate value for this row.
    • If isRowAvailable() returns true, iterate over the children components of each UIColumn child of this UIData component, calling the processUpdates() method for each such child.
  • Set the current rowIndex to -1.

Parameters:
context javax.faces.context.FacesContext for the current request
Throws:
java.lang.NullPointerException if context is null
    public void processUpdates(FacesContext context) {
        if (context == null) {
            throw new NullPointerException();
        }
        if (!isRendered()) {
            return;
        }
        pushComponentToEL(contextthis);
        preUpdate(context);
        iterate(context.);
        popComponentFromEL(context);
        // This is not a EditableValueHolder, so no further processing is required
    }
    public String createUniqueId(FacesContext contextString seed) {
        int lastId = ((i != null) ? i : 0);
        getStateHelper().put(.,  ++lastId);
        return . + (seed == null ? lastId : seed);
    }

    

Override the behavior in UIComponent.visitTree(javax.faces.component.visit.VisitContext,javax.faces.component.visit.VisitCallback) to handle iteration correctly.

If the UIComponent.isVisitable(javax.faces.component.visit.VisitContext) method of this instance returns false, take no action and return.

Call UIComponent.pushComponentToEL(javax.faces.context.FacesContext,javax.faces.component.UIComponent) and invoke the visit callback on this UIData instance as described in UIComponent.visitTree(javax.faces.component.visit.VisitContext,javax.faces.component.visit.VisitCallback). Let the result of the invoctaion be visitResult. If visitResult is javax.faces.component.visit.VisitResult.COMPLETE, take no further action and return true. Otherwise, determine if we need to visit our children. The default implementation calls javax.faces.component.visit.VisitContext.getSubtreeIdsToVisit(javax.faces.component.UIComponent) passing this as the argument. If the result of that call is non-empty, let doVisitChildren be true. If doVisitChildren is true and visitResult is javax.faces.component.visit.VisitResult.ACCEPT, take the following action.

Call UIComponent.popComponentFromEL(javax.faces.context.FacesContext) and restore the saved row index with a call to setRowIndex(int).

Return false to allow the visiting to continue.

Parameters:
context the VisitContext that provides context for performing the visit.
callback the callback to be invoked for each node encountered in the visit.
Throws:
java.lang.NullPointerException if any of the parameters are null.
    @Override
    public boolean visitTree(VisitContext context
                             VisitCallback callback) {
        // First check to see whether we are visitable.  If not
        // short-circuit out of this subtree, though allow the
        // visit to proceed through to other subtrees.
        if (!isVisitable(context))
            return false;
        FacesContext facesContext = context.getFacesContext();
        // NOTE: that the visitRows local will be obsolete once the
        //       appropriate visit hints have been added to the API
        boolean visitRows = requiresRowIteration(context);
        // Clear out the row index is one is set so that
        // we start from a clean slate.
        int oldRowIndex = -1;
        if (visitRows) {
            oldRowIndex = getRowIndex();
            setRowIndex(-1);
        }
        // Push ourselves to EL
        pushComponentToEL(facesContextnull);
        try {
            // Visit ourselves.  Note that we delegate to the 
            // VisitContext to actually perform the visit.
            VisitResult result = context.invokeVisitCallback(thiscallback);
            // If the visit is complete, short-circuit out and end the visit
            if (result == .)
                return true;
            // Visit children, short-circuiting as necessary
            // NOTE: that the visitRows parameter will be obsolete once the
            //       appropriate visit hints have been added to the API
            if ((result == .) && doVisitChildren(contextvisitRows)) {
                // First visit facets
                // NOTE: that the visitRows parameter will be obsolete once the
                //       appropriate visit hints have been added to the API
                if (visitFacets(contextcallbackvisitRows))
                    return true;
                // Next column facets
                // NOTE: that the visitRows parameter will be obsolete once the
                //       appropriate visit hints have been added to the API
                if (visitColumnsAndColumnFacets(contextcallbackvisitRows))
                    return true;
                // And finally, visit rows
                // NOTE: that the visitRows parameter will be obsolete once the
                //       appropriate visit hints have been added to the API
                if (visitRows(contextcallbackvisitRows))
                    return true;
            }
        }
        finally {
            // Clean up - pop EL and restore old row index
            popComponentFromEL(facesContext);
            if (visitRows) {
                setRowIndex(oldRowIndex);
            }
        }
        // Return false to allow the visit to continue
        return false;
    }

    

Override the base class method to take special action if the method is being invoked when javax.faces.application.StateManager.IS_BUILDING_INITIAL_STATE is true and the rowStatePreserved JavaBeans property for this instance is true.

The additional action taken is to traverse the descendents and save their state without regard to any particular row value.

Since:
2.1
    @Override
    public void markInitialState()
    {
        if (isRowStatePreserved())
        {
            {
            }
        }
        super.markInitialState();
    }
    private void restoreFullDescendantComponentStates(FacesContext facesContext,
            Iterator<UIComponentchildIteratorObject state,
            boolean restoreChildFacets)
    {
        Iterator<? extends Object[]> descendantStateIterator = null;
        while (childIterator.hasNext())
        {
            if (descendantStateIterator == null && state != null)
            {
                descendantStateIterator = ((Collection<? extends Object[]>) state)
                        .iterator();
            }
            UIComponent component = childIterator.next();
            // reset the client id (see spec 3.1.6)
            component.setId(component.getId());
            if (!component.isTransient())
            {
                Object childState = null;
                Object descendantState = null;
                if (descendantStateIterator != null
                        && descendantStateIterator.hasNext())
                {
                    Object[] object = descendantStateIterator.next();
                    childState = object[0];
                    descendantState = object[1];
                }
                
                component.clearInitialState();
                component.restoreState(facesContextchildState);
                component.markInitialState();
                
                Iterator<UIComponentchildsIterator;
                if (restoreChildFacets)
                {
                    childsIterator = component.getFacetsAndChildren();
                }
                else
                {
                    childsIterator = component.getChildren().iterator();
                }
                restoreFullDescendantComponentStates(facesContextchildsIterator,
                        descendantStatetrue);
            }
        }
    }
            Iterator<UIComponentchildIteratorboolean saveChildFacets)
    {
        Collection<Object[]> childStates = null;
        while (childIterator.hasNext())
        {
            if (childStates == null)
            {
                childStates = new ArrayList<Object[]>();
            }
            UIComponent child = childIterator.next();
            if (!child.isTransient())
            {
                // Add an entry to the collection, being an array of two
                // elements. The first element is the state of the children
                // of this component; the second is the state of the current
                // child itself.
                Iterator<UIComponentchildsIterator;
                if (saveChildFacets)
                {
                    childsIterator = child.getFacetsAndChildren();
                }
                else
                {
                    childsIterator = child.getChildren().iterator();
                }
                Object descendantState = saveDescendantInitialComponentStates(
                        facesContextchildsIteratortrue);
                Object state = child.saveState(facesContext);
                childStates.add(new Object[] { statedescendantState });
            }
        }
        return childStates;
    }
    
    private Map<String,ObjectsaveFullDescendantComponentStates(FacesContext facesContextMap<String,ObjectstateMap,
            Iterator<UIComponentchildIteratorboolean saveChildFacets)
    {
        while (childIterator.hasNext())
        {
            UIComponent child = childIterator.next();
            if (!child.isTransient())
            {
                Iterator<UIComponentchildsIterator;
                if (saveChildFacets)
                {
                    childsIterator = child.getFacetsAndChildren();
                }
                else
                {
                    childsIterator = child.getChildren().iterator();
                }
                stateMap = saveFullDescendantComponentStates(facesContextstateMap,
                        childsIteratortrue);
                Object state = child.saveState(facesContext);
                if (state != null)
                {
                    if (stateMap == null)
                    {
                        stateMap = new HashMap<String,Object>();
                    }
                    stateMap.put(child.getClientId(facesContext), state);
                }
            }
        }
        return stateMap;
    }
    
    private void restoreFullDescendantComponentDeltaStates(FacesContext facesContext,
            Iterator<UIComponentchildIteratorObject stateObject initialState,
            boolean restoreChildFacets)
    {
        Map<String,ObjectdescendantStateIterator = null;
        Iterator<? extends Object[]> descendantFullStateIterator = null;
        while (childIterator.hasNext())
        {
            if (descendantStateIterator == null && state != null)
            {
                descendantStateIterator = (Map<String,Object>) state;
            }
            if (descendantFullStateIterator == null && initialState != null)
            {
                descendantFullStateIterator = ((Collection<? extends Object[]>) initialState).iterator();
            }
            UIComponent component = childIterator.next();
            // reset the client id (see spec 3.1.6)
            component.setId(component.getId());
            if (!component.isTransient())
            {
                Object childInitialState = null;
                Object descendantInitialState = null;
                Object childState = null;
                if (descendantStateIterator != null
                        && descendantStateIterator.containsKey(component.getClientId(facesContext)))
                {
                    //Object[] object = (Object[]) descendantStateIterator.get(component.getClientId(facesContext));
                    //childState = object[0];
                    childState = descendantStateIterator.get(component.getClientId(facesContext));
                }
                if (descendantFullStateIterator != null
                        && descendantFullStateIterator.hasNext())
                {
                    Object[] object = (Object[]) descendantFullStateIterator.next();
                    childInitialState = object[0];
                    descendantInitialState = object[1];
                }
                
                component.clearInitialState();
                if (childInitialState != null)
                {
                    component.restoreState(facesContextchildInitialState);
                    component.markInitialState();
                    component.restoreState(facesContextchildState);
                }
                else
                {
                    component.restoreState(facesContextchildState);
                    component.markInitialState();
                }
                
                Iterator<UIComponentchildsIterator;
                if (restoreChildFacets)
                {
                    childsIterator = component.getFacetsAndChildren();
                }
                else
                {
                    childsIterator = component.getChildren().iterator();
                }
                restoreFullDescendantComponentDeltaStates(facesContextchildsIterator,
                        statedescendantInitialState , true);
            }
        }
    }
    private void restoreTransientDescendantComponentStates(FacesContext facesContextIterator<UIComponentchildIteratorMap<StringObjectstate,
            boolean restoreChildFacets)
    {
        while (childIterator.hasNext())
        {
            UIComponent component = childIterator.next();
            // reset the client id (see spec 3.1.6)
            component.