A delta enabled state holder implementing the StateHolder Interface.
Components implementing the PartalStateHolder interface have an initial state and delta states, the initial state is the one holding all root values and deltas store differences to the initial states
For components not implementing partial state saving only the initial states are of importance, everything is stored and restored continously there
The state helper seems to have three internal storage mechanisms: one being a list which stores plain values, one being a key value pair which stores key values in maps add serves the plain list type while put serves the key value type, the third is the value which has to be stored plainly as is!
In other words, this map can be seen as a composite map. It has two maps: initial state map and delta map.
If delta map is used (method component.initialStateMarked() ), base or initial state map cannot be changed, since all changes should be tracked on delta map.
The intention of this class is just hold property values and do a clean separation between initial state and delta.
The code from this class comes from a refactor of org.apache.myfaces.trinidad.bean.util.PropertyHashMap
The context from this class comes and that should be taken into account is this:
First request:
- A new template is created (using javax.faces.view.ViewDeclarationLanguage.buildView method) and component.markInitialState is called from its related TagHandler classes (see javax.faces.view.facelets.ComponentHandler ). When this method is executed, the component tree was populated from the values set in the facelet abstract syntax tree (or in other words composition of facelets templates).
- From this point all updates on the variables are considered "delta".
- SaveState, if initialStateMarked is true, only delta is saved.
Second request (and next ones)
- A new template is created and component.markInitialState is called from its related TagHandler classes again. In this way, components like c:forEach or c:if, that add or remove components could notify about this and handle them properly (see javax.faces.view.StateManagementStrategy). Note that a component restored using this method is no different as the same component at the first request at the same time.
- A call for restoreState is done, passing the delta as object value. If no delta, the state is complete and no call is triggered.
- Lifecycle occur, changing the necessary stuff.
- SaveState, if initialStateMarked is true, only delta is saved.
From the previous analysis, the following conclusions arise:
- This class only needs to keep track of delta changes, so when restoreState/saveState is called, the right objects are passed.
- UIComponent.clearInitialState is used to reset the partial state holder to a non delta state, so the state to be saved by saveState is no longer a delta instead is a full state. If a call to clearInitialState occur it is not expected a call for UIComponent.markInitialState occur on the current request.
- The state is handled in the same way on UIData, so components inside UIData share its state on all rows. There is no way to save delta per row.
- The map backed by method put(Serializable,String,Object) is a replacement of UIComponentBase.attributesMap and UIComponent.bindings map. Note that on jsf 1.2, instances saved on attributesMap should not be StateHolder, but on jsf 2.0 it is possible to have it. PartialStateHolder instances are not handled in this map, or in other words delta state is not handled in this classes (markInitialState and clearInitialState is not propagated).
- The list backed by method add(Serializable,Object) should be (is not) a replacement of UIComponentBase.facesListeners, but note that StateHelper does not implement PartialStateHolder, and facesListener could have instances of that class that needs to be notified when UIComponent.markInitialState or UIComponent.clearInitialState is called, or in other words facesListeners should deal with PartialStateHolder instances.
- The list backed by method add(Serializable,Object) is a replacement of UIViewRoot.phaseListeners list. Note that instances of PhaseListener are not expected to implement StateHolder or PartialStateHolder.
NOTE: The current implementation of StateHelper on RI does not handle stateHolder values internally. To prevent problems when developers create custom components we should do this too. But anyway, the code that handle this case should be let here as comment, if some day this feature is provided. Note than stateHolder aware properties like converter, validator or listeners should deal with StateHolder or PartialStateHolder on component classes.
@author Werner Punz
@author Leonardo Uribe (latest modification by $Author: struberg $)
@version $Rev: 1188235 $ $Date: 2011-10-24 12:09:33 -0500 (Mon, 24 Oct 2011) $