javax.faces.component
Class UIData

java.lang.Object
  extended by javax.faces.component.UIComponent
      extended by javax.faces.component.UIComponentBase
          extended by javax.faces.component.UIData
All Implemented Interfaces:
EventListener, NamingContainer, PartialStateHolder, StateHolder, TransientStateHolder, UniqueIdVendor, ComponentSystemEventListener, FacesListener, SystemEventListenerHolder

@JSFComponent(defaultRendererType="javax.faces.Table")
public class UIData
extends UIComponentBase
implements NamingContainer, UniqueIdVendor

Represents an abstraction of 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 the JSF Specification for more information.

Version:
$Revision: 1470769 $ $Date: 2013-04-22 20:07:54 -0500 (Mon, 22 Apr 2013) $
Author:
Manfred Geiler (latest modification by $Author: lu4242 $)

Field Summary
static String COMPONENT_FAMILY
           
static String COMPONENT_TYPE
           
 
Fields inherited from class javax.faces.component.UIComponent
ATTRS_WITH_DECLARED_DEFAULT_VALUES, BEANINFO_KEY, bindings, COMPOSITE_COMPONENT_TYPE_KEY, COMPOSITE_FACET_NAME, CURRENT_COMPONENT, CURRENT_COMPOSITE_COMPONENT, FACETS_KEY, HONOR_CURRENT_COMPONENT_ATTRIBUTES_PARAM_NAME, VIEW_LOCATION_KEY
 
Fields inherited from interface javax.faces.component.NamingContainer
SEPARATOR_CHAR
 
Constructor Summary
UIData()
          Construct an instance of the UIData.
 
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.
 String createUniqueId(FacesContext context, String seed)
          
 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)
           
 String getContainerClientId(FacesContext context)
           
protected  DataModel getDataModel()
          Return the datamodel for this table, potentially fetching the data from a backing bean via a value-binding if this is the first time this method has been called.
 String getFamily()
           
 int getFirst()
          Defines the index of the first row to be displayed, starting from 0.
 UIComponent getFooter()
           
 UIComponent getHeader()
           
 int getRowCount()
           
 Object getRowData()
           
 int getRowIndex()
           
 int getRows()
          Defines the maximum number of rows of data to be displayed.
 Object getValue()
          An EL expression that specifies the data model that backs this table.
 String getVar()
          Defines the name of the request-scope variable that will hold the current row during iteration.
 boolean invokeOnComponent(FacesContext context, String clientId, ContextCallback callback)
          invokeOnComponent must be implemented in UIComponentBase too...
 boolean isRowAvailable()
           
 boolean isRowStatePreserved()
          Indicates whether the state for a component in each row should not be discarded before the datatable is rendered again.
 void markInitialState()
           
 void processDecodes(FacesContext context)
           
 void processUpdates(FacesContext context)
          This isn't an input component, so just pass on the processUpdates call to child components and facets that might be input components.
 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.
 void restoreState(FacesContext context, Object state)
          Invoked in the "restore view" phase, this initialises this object's members from the values saved previously into the provided state object.
 Object saveState(FacesContext context)
          Invoked after the render phase has completed, this method returns an object which can be passed to the restoreState of some other instance of UIComponentBase to reset that object's state to the same values as this object currently has.
protected  void setDataModel(DataModel dataModel)
           
 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 setRowStatePreserved(boolean preserveComponentState)
           
 void setValue(Object value)
           
 void setValueExpression(String name, javax.el.ValueExpression binding)
           
 void setVar(String var)
           
 boolean visitTree(VisitContext context, VisitCallback callback)
          Overrides the behavior in UIComponent.visitTree(javax.faces.component.visit.VisitContext, javax.faces.component.visit.VisitCallback) to handle iteration correctly.
 
Methods inherited from class javax.faces.component.UIComponentBase
addClientBehavior, addFacesListener, clearInitialState, decode, encodeAll, encodeChildren, findComponent, getAttributes, getChildCount, getChildren, getClientBehaviors, getClientId, getDefaultEventName, getEventNames, getFacesContext, getFacesListeners, getFacet, getFacetCount, getFacets, getFacetsAndChildren, getId, getParent, getRenderer, getRendererType, getRendersChildren, getValueBinding, initialStateMarked, isRendered, isTransient, processRestoreState, processSaveState, removeFacesListener, restoreAttachedState, saveAttachedState, setId, setParent, setRendered, setRendererType, setTransient, setValueBinding
 
Methods inherited from class javax.faces.component.UIComponent
getClientId, getCompositeComponentParent, getCurrentComponent, getCurrentCompositeComponent, getListenersForEventClass, getNamingContainer, getResourceBundleMap, getStateHelper, getStateHelper, getTransientStateHelper, getTransientStateHelper, getValueExpression, isCompositeComponent, isInView, isVisitable, popComponentFromEL, processEvent, pushComponentToEL, restoreTransientState, saveTransientState, setInView, subscribeToEvent, unsubscribeFromEvent
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

COMPONENT_FAMILY

public static final String COMPONENT_FAMILY
See Also:
Constant Field Values

COMPONENT_TYPE

public static final String COMPONENT_TYPE
See Also:
Constant Field Values
Constructor Detail

UIData

public UIData()
Construct an instance of the UIData.

Method Detail

invokeOnComponent

public boolean invokeOnComponent(FacesContext context,
                                 String clientId,
                                 ContextCallback callback)
                          throws FacesException
Description copied from class: UIComponentBase
invokeOnComponent must be implemented in UIComponentBase too...

Overrides:
invokeOnComponent in class UIComponentBase
Parameters:
context - FacesContext for the current request
clientId - the id of the desired UIComponent clazz
callback - Implementation of the ContextCallback to be called
Returns:
has component been found ?
Throws:
FacesException

setFooter

public void setFooter(UIComponent footer)

getFooter

@JSFFacet
public UIComponent getFooter()

setHeader

public void setHeader(UIComponent header)

getHeader

@JSFFacet
public UIComponent getHeader()

isRowAvailable

public boolean isRowAvailable()

getRowCount

public int getRowCount()

getRowData

public 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 -

markInitialState

public void markInitialState()
Specified by:
markInitialState in interface PartialStateHolder
Overrides:
markInitialState in class UIComponentBase

restoreState

public void restoreState(FacesContext context,
                         Object state)
Description copied from class: UIComponentBase
Invoked in the "restore view" phase, this initialises this object's members from the values saved previously into the provided state object.

Specified by:
restoreState in interface StateHolder
Overrides:
restoreState in class UIComponentBase
state - is an object previously returned by the saveState method of this class.

saveState

public Object saveState(FacesContext context)
Description copied from class: UIComponentBase
Invoked after the render phase has completed, this method returns an object which can be passed to the restoreState of some other instance of UIComponentBase to reset that object's state to the same values as this object currently has.

Specified by:
saveState in interface StateHolder
Overrides:
saveState in class UIComponentBase

setValueExpression

public void setValueExpression(String name,
                               javax.el.ValueExpression binding)
Overrides:
setValueExpression in class UIComponent

getContainerClientId

public String getContainerClientId(FacesContext context)
Overrides:
getContainerClientId in class UIComponent

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.

Overrides:
queueEvent in class UIComponentBase

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.

Overrides:
broadcast in class UIComponentBase
Parameters:
event - must not be null.
Throws:
AbortProcessingException

createUniqueId

public String createUniqueId(FacesContext context,
                             String seed)

Specified by:
createUniqueId in interface UniqueIdVendor
Since:
2.0

encodeBegin

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

Overrides:
encodeBegin in class UIComponentBase
Throws:
IOException

encodeEnd

public void encodeEnd(FacesContext context)
               throws IOException
Overrides:
encodeEnd in class UIComponentBase
Throws:
IOException
See Also:
UIComponentBase.encodeEnd(javax.faces.context.FacesContext)

processDecodes

public void processDecodes(FacesContext context)
Overrides:
processDecodes in class UIComponentBase

processValidators

public void processValidators(FacesContext context)
Overrides:
processValidators in class UIComponentBase

processUpdates

public void processUpdates(FacesContext context)
Description copied from class: UIComponentBase
This isn't an input component, so just pass on the processUpdates call to child components and facets that might be input components.

Components that were never rendered can't possibly be receiving update data (no corresponding fields were ever put into the response) so if this component is not rendered then this method does not invoke processUpdates on its children.

Overrides:
processUpdates in class UIComponentBase

getDataModel

protected DataModel getDataModel()
Return the datamodel for this table, potentially fetching the data from a backing bean via a value-binding if this is the first time this method has been called.

This is complicated by the fact that this table may be nested within another table. In this case a different datamodel should be fetched for each row. When nested within a parent table, the parent reference won't change but parent.getContainerClientId() will, as the suffix changes depending upon the current row index. A map object on this component is therefore used to cache the datamodel for each row of the table. In the normal case where this table is not nested inside a component that changes its id (like a table does) then this map only ever has one entry.


setDataModel

protected void setDataModel(DataModel dataModel)

getValue

@JSFProperty
public Object getValue()
An EL expression that specifies the data model that backs this table.

The value referenced by the EL expression can be of any type.

Note in particular that unordered collections, eg Set are not supported. Therefore if the value expression references such an object then the table will be considered to contain just one element - the collection itself.


setValue

public void setValue(Object value)

getFirst

@JSFProperty
public int getFirst()
Defines the index of the first row to be displayed, starting from 0.


setFirst

public void setFirst(int first)

getRows

@JSFProperty
public int getRows()
Defines the maximum number of rows of data to be displayed.

Specify zero to display all rows from the "first" row to the end of available data.


setRows

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


getVar

@JSFProperty(literalOnly=true)
public String getVar()
Defines the name of the request-scope variable that will hold the current row during iteration.

During rendering of child components of this UIData, the variable with this name can be read to learn what the "rowData" object for the row currently being rendered is.

This value must be a static value, ie an EL expression is not permitted.


visitTree

public boolean visitTree(VisitContext context,
                         VisitCallback callback)
Overrides the behavior in UIComponent.visitTree(javax.faces.component.visit.VisitContext, javax.faces.component.visit.VisitCallback) to handle iteration correctly.

Overrides:
visitTree in class UIComponentBase
Parameters:
context - the visit context which handles the processing details
callback - the callback to be performed
Returns:
false if the processing is not done true if we can shortcut the visiting because we are done with everything
Since:
2.0

setVar

public void setVar(String var)

isRowStatePreserved

@JSFProperty(literalOnly=true,
             faceletsOnly=true)
public boolean isRowStatePreserved()
Indicates whether the state for a component in each row should not be discarded before the datatable is rendered again. This property is similar to tomahawk t:dataTable preserveRowStates This will only work reliable if the datamodel of the datatable did not change either by sorting, removing or adding rows. Default: false

Returns:

setRowStatePreserved

public void setRowStatePreserved(boolean preserveComponentState)

getFamily

public String getFamily()
Specified by:
getFamily in class UIComponent


Copyright © 2014 The Apache Software Foundation. All Rights Reserved.