Hi<br><br><div class="gmail_quote">2010/11/3 Ed Burns <span dir="ltr">&lt;<a href="mailto:edward.burns@oracle.com">edward.burns@oracle.com</a>&gt;</span><br><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
&gt;&gt;&gt;&gt;&gt; On Tue, 19 Oct 2010 12:35:05 -0400, Andy Schwartz &lt;<a href="mailto:andy.schwartz@oracle.com">andy.schwartz@oracle.com</a>&gt; said:<br>
<br>
EB&gt; When the markInitialState() method is called, save the state of the<br>
EB&gt; direct children<br>
<br>
AS&gt; Is it just the direct children?  Don&#39;t we need to save the state for<br>
AS&gt; non-direct descendents as well?<br>
<br>
I see what you mean.  Yes, we should, and I&#39;ve updated the spec language.<br>
<br>
AS&gt; Should we mention that non-iterated facets of UIData are excluded<br>
AS&gt; from this?<br>
<br>
I have mentioned that.<br>
<br>
EB&gt; without a dependency on any particular row value. For discussion, this<br>
EB&gt; rolled up state is called the &quot;initial rolled up state&quot;.<br>
<br>
AS&gt; Minor issue, but for some reason the term &quot;rolled up state&quot; doesn&#39;t seem<br>
AS&gt; to be clicking for me.  I think of this as the &quot;full initial state&quot; -<br>
AS&gt; ie. we are doing a full state save to capture the initial state of these<br>
AS&gt; components so that we can get back to this later.<br>
<br>
I&#39;m going to stick with rolled up state.  The word &quot;initial&quot; is used so<br>
frequently in this sort of discussion that I don&#39;t want to use it any more.<br>
<br>
EB&gt; When setRowIndex(int) is called, the following additional actions must<br>
EB&gt; be taken before the usual call to setRowIndex(int).<br>
<br>
AS&gt; Instead of &quot;before the usual call to setRowIndex()&quot;, maybe &quot;before any<br>
AS&gt; other work is performed&quot;?  It isn&#39;t clear what &quot;the usual call&quot; means.<br>
<br>
EB&gt; Traverse the children as done with markInitialState(), saving the<br>
EB&gt; state of each child. Because the<br>
EB&gt; saveState(javax.faces.context.FacesContext) calls during this pass<br>
EB&gt; happen after the call to markInitialState(), the state saved is the so<br>
EB&gt; called &quot;delta&quot; state of each component.<br>
<br>
AS&gt; What happens is partial state saving is disabled?  Do we still implement<br>
AS&gt; this behavior and just save/restore the full state, or do we bail on the<br>
AS&gt; preserveRowComponentState behavior?<br>
<br>
I have clarified that the preserveRowComponentState is not impacted by<br>
the application partial state saving behavior.<br>
<br>
AS&gt; BTW, we don&#39;t need to perform this traversal if the current row index<br>
AS&gt; (the row index at the point in time when setRowIndex() is called) is -1.<br>
<br>
EB&gt; Because this traversal happens during a per-row operation (in this<br>
EB&gt; case, setRowIndex(int)) the rolled up state<br>
<br>
AS&gt; Okay, so I guess &quot;rolled up&quot; state != &quot;full initial state&quot; - more like<br>
AS&gt; the per-row saved state.<br>
<br>
<br>
EB&gt; must be saved in a row-aware data structure. One implementation choice<br>
EB&gt; would be to save the state from this pass in a Map keyed by the return<br>
EB&gt; from UIComponent.getContainerClientId(javax.faces.context.FacesContext).<br>
<br>
AS&gt; Though this might not work well if we need to save state for subtrees as<br>
AS&gt; opposed to only direct children - ie. might be better to use the full<br>
AS&gt; client id.  Perhaps we should leave this implementation suggestion out?<br>
<br>
I have done so.<br>
<br>
EB&gt; It is permissible for the rolled up state to be null or empty.<br>
EB&gt;<br>
EB&gt; If the current row index is not -1, traverse the children as in the<br>
EB&gt; previous step,<br>
<br>
AS&gt; Do we need to perform two separate traversals?  Woudn&#39;t it be more<br>
AS&gt; efficient to consolidate these into a single traversal?<br>
<br>
Perhaps, but that&#39;s how Leonardo first implemented it and I am not<br>
inclined to try to optimize it here.<br>
<br></blockquote><div><br>Yes, it is possible. On the first implementation, I wanted to keep things simple<br>and understandable, so I keep them on different methods, but now the algorithm <br>is well understood.<br> <br>
</div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
EB&gt; but, instead of calling saveState(javax.faces.context.FacesContext),<br>
EB&gt; call UIComponent.saveTransientState(javax.faces.context.FacesContext).<br>
EB&gt; Save the rolled up state in a separate row-aware data structure from<br>
EB&gt; the one used in the preciding<br>
<br>
AS&gt; preceding (sp)<br>
<br>
Thanks.<br>
<br>
EB&gt; step.<br>
EB&gt;<br>
EB&gt; Call DataModel.setRowIndex(int) on the model, as normal. Store the row<br>
EB&gt; data as request scope attributes, as normal.<br>
EB&gt;<br>
EB&gt; If the rolled up state saved during the call to markInitialState() is<br>
EB&gt; not null or empty,<br>
<br>
AS&gt; Since this is the &quot;initial rolled up state&quot; - ie. the full state,<br>
AS&gt; wouldn&#39;t this be non-null?<br>
<br>
I&#39;m not sure of the answer to this one.  Leonardo?<br>
<br></blockquote><div><br>In theory, if UIData.markInitialState is called correctly, the &quot;initial rolled up<br>state&quot; is not null, so the check could be skipped. In the first versions of the<br>algorithm, the check was used to fallback to the previous algorithm, but now<br>
this is done using a check for the property ( isPreserveRowComponentState() ).<br><br></div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">

EB&gt; perform the reverse of the two save operations, as described next.<br>
EB&gt; This is necessary to indicate that transient state from the previous<br>
EB&gt; row must be discarded, in order to not pollute the state of the<br>
EB&gt; current row.<br>
<br>
EB&gt; If the per-row state saved in step a. above is null, traverse the<br>
EB&gt; children and restore the child state using the initial rolled up state.<br>
<br>
AS&gt; Does the &quot;per-row state saved in step a. above&quot; refer to the stave saved<br>
AS&gt; for the row that we are leaving?  Or for the state that we saved the<br>
AS&gt; last time that visited the current row?<br>
<br>
AS&gt; That is, if we are on row 1 and setRowIndex(2) is called, does the<br>
AS&gt; &quot;per-row state saved in step a&quot; mean the state produced for row 1 before<br>
AS&gt; we adjusted the index, or the state that we previously saved away the<br>
AS&gt; last time we visited row 2?<br>
<br>
AS&gt; This is important to specify clearly.<br>
<br>
It&#39;s the state before we adjusted the row index.  I&#39;ve clarified that.<br>
<br>
EB&gt; If the per-row state saved in step a. above is not null, traverse the<br>
EB&gt; children and restore the child state using the state saved during step<br>
EB&gt; a., using the initial rolled up state only as a backup in the case<br>
EB&gt; that per-row state is not available.<br>
<br>
AS&gt; Okay, so I guess that &quot;per-row state saved in step a. above&quot; refers to<br>
AS&gt; the previously saved state for the current row.<br>
<br>
No, it&#39;s the state before we adjusted the row index.  Leonardo, it is<br>
vitally important that you and Andy and I agree on this.<br>
<br></blockquote><div><br>The &quot;per-row state saved in step a. above&quot; in other words means the &quot;delta&quot;<br>state from the row that will be changed. If we are on row 1, to change to row 2<br>we need to restore the state of row 2, and check if it is null or not, If it is null<br>
we use only the initial rolled up state, but if is not, we use both the initial<br>rolled up state and the &quot;per-row state saved&quot;.<br> </div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">

AS&gt; However, since this is delta state, before we apply this isn&#39;t it<br>
AS&gt; necessary to first restore the components to their initial state by<br>
AS&gt; restoring the full initial saved state?  If we don&#39;t restore the<br>
AS&gt; components to their initial state before applying the delta state,<br>
AS&gt; won&#39;t we run the risk that state from the previous row might bleed<br>
AS&gt; over into the current row?  (In the case where the state from the<br>
AS&gt; previous from was null, this won&#39;t be an issue.)<br>
<br>
AS&gt; Also, at some point is it necessary to tell the StateHelper that it<br>
AS&gt; needs to clear out any previously saved deltas so that it can start<br>
AS&gt; tracking deltas for the currently active row?  Or does that happen<br>
AS&gt; implicitly at some point, eg. when we restore the row state?<br>
<br>
EB&gt; If the current row index is -1, traverse the children and pass null to<br>
EB&gt; UIComponent.restoreTransientState(javax.faces.context.FacesContext,<br>
EB&gt; java.lang.Object).<br>
<br>
AS&gt; Hopefully we can consolidate the restore-related traversals as well.<br>
<br>
EB&gt; If the current row index is not -1, take the following actions.<br>
<br>
EB&gt; If the per-row state saved in step b. above is null, traverse the<br>
EB&gt; children and restore the transient state by passing null to each<br>
EB&gt; child&#39;s<br>
EB&gt; UIComponent.restoreTransientState(javax.faces.context.FacesContext,<br>
EB&gt; java.lang.Object) method<br>
EB&gt;<br>
EB&gt; If the per-row state saved in step b. above is not null, traverse the<br>
EB&gt; children and restore the transient state from the state saved in step<br>
EB&gt; b. above, calling<br>
EB&gt; UIComponent.restoreTransientState(javax.faces.context.FacesContext,<br>
EB&gt; java.lang.Object) on each child, and passing the appropriate state.<br>
<br>
AS&gt; Sounds like we are doing the same thing whether or not the transient<br>
AS&gt; state is null, so perhaps we can simplify the wording.<br>
<br>
Perhaps, but I&#39;m concerned with getting it wrong.  The current text was<br>
approved by Leonardo so I&#39;m inclined to go with it.<br>
<br></blockquote><div><br>In few words, it just say how to restore the &quot;transient state&quot;. It is possible in this<br>part I just forget to simplify things. <br><br>The time I wrote that part I was thinking if there was some kind of manipulation <br>
on transient state properties before build view time, those values should be <br>&quot;propagated&quot; to child rows, but the intention of this state is to have a very <br>short life time (vdl build time or render time). If a value is necessary <br>
to be stored more than the current request, use StateHelper. After thinking about<br>it carefully, the conclusion was that is not necessary, so we can just assume a<br>&quot;null&quot; or &quot;empty&quot; state for the transient map. <br>
 </div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
AS&gt; Few other questions:<br>
<br>
AS&gt; 1.  Leonardo raised an issue regarding the timing of when<br>
AS&gt; markInitialState() is called - ie. that markInitialState() needs to be<br>
AS&gt; called on the parent before the children - otherwise UIData won&#39;t be<br>
AS&gt; able to capture the full initial state of its children.  How did we<br>
AS&gt; solve this problem?  Are there spec changes relating to this?  Did we<br>
AS&gt; find a way to do this that doesn&#39;t require introducing yet another full<br>
AS&gt; tree traversal?<br>
<br>
I don&#39;t know.<br>
<br></blockquote><div><br>It is possible to prevent the full tree traversal, but to do that it is necessary to<br>change all code that uses PostAddToViewEvent to relocate components, and that<br>means refactor composite component solution as is. This was done on MyFaces,<br>
so there cc:insertChildren and cc:insertFacet does not use a Listener attached to<br>that event there, but Mojarra uses it.<br><br>Anyway, users could add components on PostAddToViewEvent to the tree, so <br>in theory the call to markInitialState() should be done after that event is handled.<br>
<br></div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
AS&gt; 2.  Regarding the name of the new property...<br>
AS&gt; is/setPreserveRowComponentState() is a bit of a mouthful.  Could we<br>
AS&gt; maybe shorten this to is/setRowStatePreserved()?<br>
<br>
I like that a lot better.<br>
<br>
AS&gt; 3.  Are there cases where it might be useful to enable per-row transient<br>
AS&gt; state saving without also enabling non-transient state saving (which<br>
AS&gt; seems more expensive)?  I wonder whether it should be possible to enable<br>
AS&gt; these independently, in which case we may want to consider using an enum<br>
AS&gt; property instead of a boolean.  Also wondering whether transient row<br>
AS&gt; state saving should just be on by default or possibly always on.<br>
<br>
Leonardo?<br>
<br></blockquote><div><br>It is possible, but shouldn&#39;t that condition just depends on the component child itself ?.<br>For example, UIForm has submitted property that in the future will be stored in transient<br>map, so this component requires transient state be always on.<br>
<br>best regards,<br><br>Leonardo Uribe<br> </div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
Ed<br>
<font color="#888888">--<br>
| <a href="mailto:edward.burns@oracle.com">edward.burns@oracle.com</a> | office: +1 407 458 0017<br>
| homepage:               | <a href="http://ridingthecrest.com/" target="_blank">http://ridingthecrest.com/</a><br>
|  5 work days until German Oracle User&#39;s Group Conference<br>
| 12 work days until GlassFish 3.1 Hard Code Freeze<br>
</font></blockquote></div><br>