teamdev.jsf.component.datatable
Class QUIData
java.lang.Object
UIData
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:
- MOD-1: Added the notion of unavailableRowIndexes, for which the processDecodes, processValidations, and processUpdates phases are not performed
- MOD-2: Renamed the "value" property to "uiDataValue" in order make another "value" property in an ancestor
- MOD-3: Changed mechanism for rendered column iteration to account for AbstractTable.columnsOrder attribute:
The list of column is now retrieved using the new getColumnsForProcessing method instead of using the getChildren
- MOD-4: Include custom cell contents into phase processing (JSFC-3087)
- MOD-5: Execute all pre-rendering phases for dynamic columns created with so that each
dynamic column was decoded with correct column-specific parameters.
- MOD-6: Extended QUIData from UIData to overcome JBossSeam compatibility problem of s:link not
having access to the current row data variable. See JSFC-2585.
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:
- submittedValue
- value (where no EL binding is used)
- valid
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.
|
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 |
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
QUIData
public QUIData()
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.