teamdev.jsf.component.datatable
Class QUIData

java.lang.Object
  extended by UIData
      extended by teamdev.jsf.component.datatable.QUIData
Direct Known Subclasses:
AbstractTable

public class QUIData
extends UIData

This is a modified version of the UIData class copied from MyFaces 1.1.1. Here's a list of modifications from the original version:

Represents a component which has multiple "rows" of data.

The children of this component are expected to be UIColumn components.

Note that the same set of child components are reused to implement each row of the table in turn during such phases as apply-request-values and render-response. Altering any of the members of these components therefore affects the attribute for every row, except for the following members:

This reuse of the child components also means that it is not possible to save a reference to a component during table processing, then access it later and expect it to still represent the same row of the table.

Implementation Notes

Each of the UIColumn children of this component has a few component children of its own to render the contents of the table cell. However there can be a very large number of rows in a table, so it isn't efficient for the UIColumn and all its child objects to be duplicated for each row in the table. Instead the "flyweight" pattern is used where a serialized state is held for each row. When setRowIndex is invoked, the UIColumn objects and their children serialize their current state then reinitialise themselves from the appropriate saved state. This allows a single set of real objects to represent multiple objects which have the same types but potentially different internal state. When a row is selected for the first time, its state is set to a clean "initial" state. Transient components (including any read-only component) do not save their state; they are just reinitialised as required. The state saved/restored when changing rows is not the complete component state, just the fields that are expected to vary between rows: "submittedValue", "value", "isValid".

Note that a table is a "naming container", so that components within the table have their ids prefixed with the id of the table. Actually, when setRowIndex has been called on a table with id of "zzz" the table pretends to its children that its ID is "zzz_n" where n is the row index. This means that renderers for child components which call component.getClientId automatically get ids of form "zzz_n:childId" thus ensuring that components in different rows of the table get different ids.

When decoding a submitted page, this class iterates over all its possible rowIndex values, restoring the appropriate serialized row state then calling processDecodes on the child components. Because the child components (or their renderers) use getClientId to get the request key to look for parameter data, and because this object pretends to have a different id per row ("zzz_n") a single child component can decode data from each table row in turn without being aware that it is within a table. The table's data model is updated before each call to child.processDecodes, so the child decode method can assume that the data model's rowData points to the model object associated with the row currently being decoded. Exactly the same process applies for the later validation and updateModel phases.

When the data model for the table is bound to a backing bean property, and no validation errors have occured during processing of a postback, the data model is refetched at the start of the rendering phase (ie after the update model phase) so that the contents of the data model can be changed as a result of the latest form submission. Because the saved row state must correspond to the elements within the data model, the row state must be discarded whenever a new data model is fetched; not doing this would cause all sorts of inconsistency issues. This does imply that changing the state of any of the members "submittedValue", "value" or "valid" of a component within the table during the invokeApplication phase has no effect on the rendering of the table. When a validation error has occurred, a new DataModel is not fetched, and the saved state of the child components is not discarded.

see Javadoc of JSF Specification for more.


Field Summary
static java.lang.String COMPONENT_FAMILY
           
static java.lang.String COMPONENT_TYPE
           
 
Constructor Summary
QUIData()
           
 
Method Summary
 void broadcast(FacesEvent event)
          Ensure that before the event's listeners are invoked this UIData component's "current row" is set to the row associated with the event.
 void encodeBegin(FacesContext context)
          Perform necessary actions when rendering of this component starts, before delegating to the inherited implementation which calls the associated renderer's encodeBegin method.
 void encodeEnd(FacesContext context)
           
 java.lang.String getClientId(FacesContext context)
           
 java.lang.String getFamily()
           
 int getFirst()
           
 UIComponent getFooter()
           
 UIComponent getHeader()
           
 int getRowCount()
           
 java.lang.Object getRowData()
           
 int getRowIndex()
           
 int getRows()
           
 java.lang.Object getUiDataValue()
           
 java.lang.String getVar()
           
 boolean isRowAvailable()
           
 boolean isRowAvailableAfterRestoring(int rowIndex)
           
 void processDecodes(FacesContext context)
           
 void processUpdates(FacesContext context)
           
 void processValidators(FacesContext context)
           
 void queueEvent(FacesEvent event)
          Modify events queued for any child components so that the UIData state will be correctly configured before the event's listeners are executed.
static void restoreDescendantComponentStates(java.util.Iterator childIterator, java.lang.Object state, boolean restoreChildFacets)
          Overwrite the state of the child components of this component with data previously saved by method saveDescendantComponentStates.
 void restoreState(FacesContext context, java.lang.Object state)
           
static java.lang.Object saveDescendantComponentStates(java.util.Iterator childIterator, boolean saveChildFacets)
          Walk the tree of child components of this UIData, saving the parts of their state that can vary between rows.
 java.lang.Object saveState(FacesContext context)
           
 void setFirst(int first)
           
 void setFooter(UIComponent footer)
           
 void setHeader(UIComponent header)
           
 void setRowIndex(int rowIndex)
          Set the current row index that methods like getRowData use.
 void setRows(int rows)
          Set the maximum number of rows displayed in the table.
 void setUiDataValue(java.lang.Object value)
           
 void setValueBinding(java.lang.String name, ValueBinding binding)
           
 void setVar(java.lang.String var)
          Set the name of the temporary variable that will be exposed to child components of the table to tell them what the "rowData" object for the current row is.
 
Methods inherited from class java.lang.Object
equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

COMPONENT_TYPE

public static final java.lang.String COMPONENT_TYPE
See Also:
Constant Field Values

COMPONENT_FAMILY

public static final java.lang.String COMPONENT_FAMILY
See Also:
Constant Field Values
Constructor Detail

QUIData

public QUIData()
Method Detail

setFooter

public void setFooter(UIComponent footer)

getFooter

public UIComponent getFooter()

setHeader

public void setHeader(UIComponent header)

getHeader

public UIComponent getHeader()

isRowAvailable

public boolean isRowAvailable()

getRowCount

public int getRowCount()

getRowData

public java.lang.Object getRowData()

getRowIndex

public int getRowIndex()

setRowIndex

public void setRowIndex(int rowIndex)
Set the current row index that methods like getRowData use.

Param rowIndex can be -1, meaning "no row".

Parameters:
rowIndex -

restoreDescendantComponentStates

public static void restoreDescendantComponentStates(java.util.Iterator childIterator,
                                                    java.lang.Object state,
                                                    boolean restoreChildFacets)
Overwrite the state of the child components of this component with data previously saved by method saveDescendantComponentStates.

The saved state info only covers those fields that are expected to vary between rows of a table. Other fields are not modified.


saveDescendantComponentStates

public static java.lang.Object saveDescendantComponentStates(java.util.Iterator childIterator,
                                                             boolean saveChildFacets)
Walk the tree of child components of this UIData, saving the parts of their state that can vary between rows.

This is very similar to the process that occurs for normal components when the view is serialized. Transient components are skipped (no state is saved for them).

If there are no children then null is returned. If there are one or more children, and all children are transient then an empty collection is returned; this will happen whenever a table contains only read-only components.

Otherwise a collection is returned which contains an object for every non-transient child component; that object may itself contain a collection of the state of that child's child components.


setRows

public void setRows(int rows)
Set the maximum number of rows displayed in the table.


setVar

public void setVar(java.lang.String var)
Set the name of the temporary variable that will be exposed to child components of the table to tell them what the "rowData" object for the current row is. This value must be a literal string (EL expression not permitted).


getVar

public java.lang.String getVar()

setValueBinding

public void setValueBinding(java.lang.String name,
                            ValueBinding binding)

getClientId

public java.lang.String getClientId(FacesContext context)

queueEvent

public void queueEvent(FacesEvent event)
Modify events queued for any child components so that the UIData state will be correctly configured before the event's listeners are executed.

Child components or their renderers may register events against those child components. When the listener for that event is eventually invoked, it may expect the uidata's rowData and rowIndex to be referring to the same object that caused the event to fire.

The original queueEvent call against the child component has been forwarded up the chain of ancestors in the standard way, making it possible here to wrap the event in a new event whose source is this component, not the original one. When the event finally is executed, this component's broadcast method is invoked, which ensures that the UIData is set to be at the correct row before executing the original event.


broadcast

public void broadcast(FacesEvent event)
               throws AbortProcessingException
Ensure that before the event's listeners are invoked this UIData component's "current row" is set to the row associated with the event.

See queueEvent for more details.

Throws:
AbortProcessingException

encodeBegin

public void encodeBegin(FacesContext context)
                 throws java.io.IOException
Perform necessary actions when rendering of this component starts, before delegating to the inherited implementation which calls the associated renderer's encodeBegin method.

Throws:
java.io.IOException

encodeEnd

public void encodeEnd(FacesContext context)
               throws java.io.IOException
Throws:
java.io.IOException
See Also:
javax.faces.component.UIComponentBase#encodeEnd(javax.faces.context.FacesContext)

processDecodes

public void processDecodes(FacesContext context)

processValidators

public void processValidators(FacesContext context)

processUpdates

public void processUpdates(FacesContext context)

setUiDataValue

public void setUiDataValue(java.lang.Object value)

saveState

public java.lang.Object saveState(FacesContext context)

restoreState

public void restoreState(FacesContext context,
                         java.lang.Object state)

getFamily

public java.lang.String getFamily()

setFirst

public void setFirst(int first)

getFirst

public int getFirst()

getRows

public int getRows()

getUiDataValue

public java.lang.Object getUiDataValue()

isRowAvailableAfterRestoring

public boolean isRowAvailableAfterRestoring(int rowIndex)


Copyright © 1998-2009 TeamDev Ltd. All Rights Reserved.