[gwt-contrib] Re: Issue 7038: CompositeEditor and ListEditor optimizations (issue1664803)

2012-06-01 Thread Thomas Broyer
On Sat, May 19, 2012 at 6:16 PM, Thomas Broyer wrote:

 CheckBox turns 'null' into 'Boolean.FALSE' and TextBox turns 'null' into the
 empty string, and people have complained.
 See http://code.google.com/p/google-web-toolkit/issues/detail?id=5976#c1
 (I'm sure this was discussed, with John or Ray R, and I started working on a
 patch; can't find this though)

Yay! Just stumbled upon it, so for reference:
http://code.google.com/p/google-web-toolkit/issues/detail?id=6713#c8

-- 
http://groups.google.com/group/Google-Web-Toolkit-Contributors


[gwt-contrib] Re: Issue 7038: CompositeEditor and ListEditor optimizations (issue1664803)

2012-05-31 Thread t . broyer

On 2012/05/31 00:18:43, skybrian wrote:

I got this feedback from someone who requested a rollback but decided

to work

around it instead. I wonder how widespread this sort of thing is?



Our use of the editor/driver stuff assumed the editors would be
rebuilt when driver.edit(T) was invoked. This isn't true with this CL,
as the point of the CL was to try and avoid rebuilding the editors
when the same T is put into the same driver/editor framework.



Basically we used the editor/driver thing to show a read-only
version of T and then depended on the sub-editors to be recreated when
the user clicked our Edit button and we pushed the same model object
back into the same top level editor. Our work-around is to push a mock
empty object in first, and then push the real object again, forcing
the sub-editor list to be cleared and recreated.


If you ask me, they have a design issue.
Just like other editors that are not sub-editors of a ListEditor, the
ListEditor sub-editors will have their value updated by the edit() (this
is done by the chain.attach() from ListEditorWrapper#set(), called from
ListEditorWrapper#refresh()); so if the editor needs to be different
between read-only and edit modes (mode which is communicated to the
editors by out-of-band means), their sub-editors should update their
rendering when the mode changes, without even the need for a call to
edit() on the editor driver, or possibly only when their value is
updated.

In other words, it's a mistake to make editors behave differently
depending on out-of-band information IFF they don't update their
behavior themselves when that out-of-band information changes, or when
the value is updated (even if that means implementing ValueAwareEditor
only to be notified of the value changing).

As another workaround, if they're fine recreating their sub-editors,
they could wrap them in simple editors:
class Wrapper implements ValueAwareEditorFoo {
   @Path() Real real;

   @Override
   public void setValue(Foo value) {
  // unconditionally create a new Real editor:
  Real oldReal = real;
  real = new Real();
  replaceOldEditorByNewEditorInParentWidget(oldReal, real);
   }
   // other ValueAwareEditor methods as no-ops.
}
and then use a ListEditorFoo, Wrapper instead of ListEditorFoo,
Real.
Of course, this means the Wrapper here knows how it'll be used (to
implement the replaceOldEditorByNewEditorInParentWidget method); in
other words, there's some cooperation between Wrapper and the
EditorSource (but given Wrapper instances are created by the
EditorSource, that shouldn't really be an issue).

https://gwt-code-reviews.appspot.com/1664803/

--
http://groups.google.com/group/Google-Web-Toolkit-Contributors


[gwt-contrib] Re: Issue 7038: CompositeEditor and ListEditor optimizations (issue1664803)

2012-05-30 Thread skybrian

I got this feedback from someone who requested a rollback but decided to
work around it instead. I wonder how widespread this sort of thing is?

Our use of the editor/driver stuff assumed the editors would be
rebuilt when driver.edit(T) was invoked. This isn't true with this CL,
as the point of the CL was to try and avoid rebuilding the editors
when the same T is put into the same driver/editor framework.

Basically we used the editor/driver thing to show a read-only
version of T and then depended on the sub-editors to be recreated when
the user clicked our Edit button and we pushed the same model object
back into the same top level editor. Our work-around is to push a mock
empty object in first, and then push the real object again, forcing
the sub-editor list to be cleared and recreated.


https://gwt-code-reviews.appspot.com/1664803/

--
http://groups.google.com/group/Google-Web-Toolkit-Contributors


[gwt-contrib] Re: Issue 7038: CompositeEditor and ListEditor optimizations (issue1664803)

2012-05-26 Thread t . broyer

On 2012/05/25 22:53:18, tbroyer wrote:

On 2012/05/25 17:58:21, skybrian wrote:

 In getEditors: The returned
 list will be live until the next call to setValue() and shouldn't be
 used after that.



[...]



 Yeah, #3 is out. Option #2 would make sense if we expected that
 complaining early means that most people would fix the problem

before

 it reaches production. I'm not convinced of that; I think people

won't

 test the corner cases that result in null list fields in their
 AutoBeans (particularly if those corner cases come from the server).



AFAICT, that's already an issue with other editors though: in the

DevGuide for

editors [1], if the address or manager is null, then you'll have

an NPE at

runtime.


Hey, know what? I was wrong!

If the 'address' is 'null', it'll set 'null' to the AddressEditor (if
it's a ValueAwareEditor) and all of its sub-editors.

So #1 (what we do here) is actually exactly what we *should* do!

http://gwt-code-reviews.appspot.com/1664803/

--
http://groups.google.com/group/Google-Web-Toolkit-Contributors


[gwt-contrib] Re: Issue 7038: CompositeEditor and ListEditor optimizations (issue1664803)

2012-05-25 Thread Thomas Broyer
On Fri, May 25, 2012 at 12:48 AM, Brian Slesinsky skybr...@google.com wrote:
 On Sat, May 19, 2012 at 9:16 AM, Thomas Broyer t.bro...@gmail.com wrote:

 So I agree that is
 seems logical that a live view would only last until the next
 flush() or at most until the next setValue(). But this isn't
 well-documented in this class or anywhere else that I've found so far.

 To
 me, https://developers.google.com/web-toolkit/doc/latest/DevGuideUiEditors is
 clear enough. YMMV though.

 It does explain a lot of things but I'm missing the part where it
 explains the lifetime of the view returned by getEditors(). I'd expect
 that to be explained in the javadoc for getEditors itself.

Right. We should add that.

 So maybe we want to do that now? I also wonder if, for consistency, we
 want to make sure the live view goes stale on *every* call to
 setValue(), which would make our optimization a bit trickier; we
 should probably create a new ListValueProvider and copy all the
 subeditors into it.


 ListEditorWrapper could track this in detach() and from then on act as an
 immutable list (throwing exceptions if you try to change it).

 Sure, that seems like a separate issue though.

 Here's my concern: if you call setValue() twice with the same list,
 this patch will make the live view returned by getEditors() last
 longer than before. So I think maybe we shouldn't reuse the
 ListEditorWrapper instance, just the Editors themselves.
 ListEditorWrapper looks cheap to construct, so we might as well be
 consistent and avoid changing behavior.

 On the other hand, maybe you're expecting that the caller *knows* that
 they're calling setValue() twice with the same List, so they expect
 the view to last longer as a result, sort of like if we were returning
 the same list again without wrapping it. If so, maybe this is a change
 in behavior to be closer to what the user expects?

I think the expected use of getEditors() is that users don't keep an
handle on it.
Even if they, if they call getEditors() after each setValue(), then it
doesn't really matter whether the returned value will be the same
instance or a different one.
How about documenting that? (users shouldn't hold a reference on the
returned list, or if they do, they should refresh it after any call
to setValue(); the returned list only guaranteed to be the same
between calls to setValue, and shouldn't be used after a call to
setValue).

 If you ask me, for consistency, I'd
 remove the null-check in ListEditor and let it fail for 'null' values, just
 like it did originally. It might have been added by mistake, I don't know,
 it was added as part of a bigger change and wasn't tracked/documented at
 all, so who knows?

 I'm not sure what you mean. Do you mean that setValue() should just
 throw an exception for null lists? Or does it blow up later? Or do we
 want to avoid blowing up?

Throw on 'null' (it will actually blow up with an NPE in
ListEditorWrapper's constructor, when retrieving its size).
I would just add an 'assert' in setValue as a hint for developers, and
let it blow in ListEditorWrapper in prod mode.

 That's the kind of behavior I'd rather fight against: getValue just after
 setValue should try to preserve the value (null vs. empty string)

 Yes, good point. Except that in this case, there is no getValue()
 method, since this isn't a LeafValueEditor and doesn't implement
 HasValue.

Yes, that's what I meant by Only if it was then flushed into the
edited property (otherwise your changes to the empty list would be
lost) and We could basically merge OptionalFieldEditor functionality
into ListEditor: ListEditor would have to be made a LeafValueEditor
if we wanted to turn nulls into empty lists.

 It looks like all changes get sent to the backing list via flush()?

Yes

This is the general contract of the Editor framework: do not change
the edited object in real-time, instead queue changes and only apply
them on flush(); similarly, LeafValueEditors are not supposed to
modify the object in-place, but return the new value from
getValue(), otherwise they should be ValueAwareEditors with no
sub-editor.
Maybe it should be made clearer in the doc?

 If we call setValue() with a null list, I don't think flush() can do
 anything, because we don't have any reference to a backing model to
 update! Therefore, any changes made in the ListEditor cannot be saved?
 You'd have to use an OptionalFieldEditor if you want to save it.

 So it seems like at most we can display a read-only, empty list.
 There's no point in letting the user edit something they can't save.

Exactly. Unless we change ListEditor to be a LeafValueEditor, which
would be equivalent to merging OptionalFieldEditor functionality into
ListEditor.


To sum up: ListEditor is currently able to display 'null' lists as if
they were empty lists, but then you cannot edit the list's content (as
there's actually no list), and more importantly getEditors() will
throw a misleading exception, and flush() will throw (so 

[gwt-contrib] Re: Issue 7038: CompositeEditor and ListEditor optimizations (issue1664803)

2012-05-25 Thread Brian Slesinsky
On Fri, May 25, 2012 at 1:43 AM, Thomas Broyer t.bro...@gmail.com wrote:

 I think the expected use of getEditors() is that users don't keep an
 handle on it.
 Even if they, if they call getEditors() after each setValue(), then it
 doesn't really matter whether the returned value will be the same
 instance or a different one.
 How about documenting that? (users shouldn't hold a reference on the
 returned list, or if they do, they should refresh it after any call
 to setValue(); the returned list only guaranteed to be the same
 between calls to setValue, and shouldn't be used after a call to
 setValue).

Yes, that seems fine as a specification. In getEditors: The returned
list will be live until the next call to setValue() and shouldn't be
used after that.


 If you ask me, for consistency, I'd
 remove the null-check in ListEditor and let it fail for 'null' values, just
 like it did originally. It might have been added by mistake, I don't know,
 it was added as part of a bigger change and wasn't tracked/documented at
 all, so who knows?

 I'm not sure what you mean. Do you mean that setValue() should just
 throw an exception for null lists? Or does it blow up later? Or do we
 want to avoid blowing up?

 Throw on 'null' (it will actually blow up with an NPE in
 ListEditorWrapper's constructor, when retrieving its size).
 I would just add an 'assert' in setValue as a hint for developers, and
 let it blow in ListEditorWrapper in prod mode.

 That's the kind of behavior I'd rather fight against: getValue just after
 setValue should try to preserve the value (null vs. empty string)

 Yes, good point. Except that in this case, there is no getValue()
 method, since this isn't a LeafValueEditor and doesn't implement
 HasValue.

 Yes, that's what I meant by Only if it was then flushed into the
 edited property (otherwise your changes to the empty list would be
 lost) and We could basically merge OptionalFieldEditor functionality
 into ListEditor: ListEditor would have to be made a LeafValueEditor
 if we wanted to turn nulls into empty lists.

 It looks like all changes get sent to the backing list via flush()?

 Yes

 This is the general contract of the Editor framework: do not change
 the edited object in real-time, instead queue changes and only apply
 them on flush(); similarly, LeafValueEditors are not supposed to
 modify the object in-place, but return the new value from
 getValue(), otherwise they should be ValueAwareEditors with no
 sub-editor.
 Maybe it should be made clearer in the doc?

 If we call setValue() with a null list, I don't think flush() can do
 anything, because we don't have any reference to a backing model to
 update! Therefore, any changes made in the ListEditor cannot be saved?
 You'd have to use an OptionalFieldEditor if you want to save it.

 So it seems like at most we can display a read-only, empty list.
 There's no point in letting the user edit something they can't save.

 Exactly. Unless we change ListEditor to be a LeafValueEditor, which
 would be equivalent to merging OptionalFieldEditor functionality into
 ListEditor.


 To sum up: ListEditor is currently able to display 'null' lists as if
 they were empty lists, but then you cannot edit the list's content (as
 there's actually no list), and more importantly getEditors() will
 throw a misleading exception, and flush() will throw (so ListEditor
 can really only be used with 'null' lists in read-only use cases,
 where you call edit() on the EditorDriver without ever calling
 flush()).
 This is something we should fix IMO. There are three solutions:
 1. make getEditors() return an empty list instead of throwing and
 avoid the NPE in flush(). Breaking change: getEditors() no longer
 throw if you call it before calling setValue() for the first time.
 2. make setValue throw on a 'null' value, mandating the use of an
 OptionalFieldEditor if the list can be 'null'. This is consistent with
 all other editors (most importantly simple Editor-s with sub-editors,
 e.g. all the examples from the doc except LabelDecorator), with the
 exception of LeafValueEditors which are expected to accept nulls (at
 the editor's discretion actually, but all the LeafValueEditors
 provided in gwt-user.jar accept nulls). Breaking change: well, anyone
 using a ListEditor in a read-only scenario where 'null' values are
 expected would have to update his code to add an OptionalFieldEditor
 in from of the ListEditor.
 3. merging OptionalFieldEditor functionality into ListEditor,
 turning a 'null' value into an empty list so it can be edited. But
 then one could no longer tell the difference between 'null' and an
 empty list, and we'd have to add code so that getValue returns 'null'
 if 'null' was passed to setValue and getList() is empty (but never
 return 'null' if a non-null value was passed to setValue!).

 Patch Set #3 implements #1 above, as it's less likely to break
 anyone's code (quite the contrary), at the expense of being
 inconsistent with most other 

[gwt-contrib] Re: Issue 7038: CompositeEditor and ListEditor optimizations (issue1664803)

2012-05-25 Thread t . broyer

On 2012/05/25 17:58:21, skybrian wrote:


In getEditors: The returned
list will be live until the next call to setValue() and shouldn't be
used after that.


[...]


Yeah, #3 is out. Option #2 would make sense if we expected that
complaining early means that most people would fix the problem before
it reaches production. I'm not convinced of that; I think people won't
test the corner cases that result in null list fields in their
AutoBeans (particularly if those corner cases come from the server).


AFAICT, that's already an issue with other editors though: in the
DevGuide for editors [1], if the address or manager is null, then
you'll have an NPE at runtime.

(note: not necessarily AutoBeans, any POJO can be edited with the Editor
framework ;-) )

[1]
https://developers.google.com/web-toolkit/doc/latest/DevGuideUiEditors#Quickstart


So I think #1 might actually be right; accept that the list might be
null and don't break, but don't let the user edit the field either.
Also, I see that having a null is actually the initial state of the
ListEditor so it seems okay to go back to that state.



It seems okay for getEditors to return an empty list when we have no
backing list (yes, we have no editors).



If that seems okay, here's the javadoc to fix so we don't have to have
this discussion again:



- ListEditor constructor: The ListEditor will have no backing list
until setValue() is called with a non-null value.



- setValue(): If a null is passed in, the ListEditor will have no
backing list and edits cannot be made.



- getEditors(): If there is no backing list, an empty list will be

returned.


- getList(): Returns null if there is no backing list and edits
cannot be made.


Done.

https://gwt-code-reviews.appspot.com/1664803/

--
http://groups.google.com/group/Google-Web-Toolkit-Contributors


[gwt-contrib] Re: Issue 7038: CompositeEditor and ListEditor optimizations (issue1664803)

2012-05-24 Thread Brian Slesinsky
On Sat, May 19, 2012 at 9:16 AM, Thomas Broyer t.bro...@gmail.com wrote:

 So I agree that is
 seems logical that a live view would only last until the next
 flush() or at most until the next setValue(). But this isn't
 well-documented in this class or anywhere else that I've found so far.

 To
 me, https://developers.google.com/web-toolkit/doc/latest/DevGuideUiEditors is
 clear enough. YMMV though.

It does explain a lot of things but I'm missing the part where it
explains the lifetime of the view returned by getEditors(). I'd expect
that to be explained in the javadoc for getEditors itself.

 So maybe we want to do that now? I also wonder if, for consistency, we
 want to make sure the live view goes stale on *every* call to
 setValue(), which would make our optimization a bit trickier; we
 should probably create a new ListValueProvider and copy all the
 subeditors into it.


 ListEditorWrapper could track this in detach() and from then on act as an
 immutable list (throwing exceptions if you try to change it).

Sure, that seems like a separate issue though.

Here's my concern: if you call setValue() twice with the same list,
this patch will make the live view returned by getEditors() last
longer than before. So I think maybe we shouldn't reuse the
ListEditorWrapper instance, just the Editors themselves.
ListEditorWrapper looks cheap to construct, so we might as well be
consistent and avoid changing behavior.

On the other hand, maybe you're expecting that the caller *knows* that
they're calling setValue() twice with the same List, so they expect
the view to last longer as a result, sort of like if we were returning
the same list again without wrapping it. If so, maybe this is a change
in behavior to be closer to what the user expects?

 If you ask me, for consistency, I'd
 remove the null-check in ListEditor and let it fail for 'null' values, just
 like it did originally. It might have been added by mistake, I don't know,
 it was added as part of a bigger change and wasn't tracked/documented at
 all, so who knows?

I'm not sure what you mean. Do you mean that setValue() should just
throw an exception for null lists? Or does it blow up later? Or do we
want to avoid blowing up?

 That's the kind of behavior I'd rather fight against: getValue just after
 setValue should try to preserve the value (null vs. empty string)

Yes, good point. Except that in this case, there is no getValue()
method, since this isn't a LeafValueEditor and doesn't implement
HasValue. It looks like all changes get sent to the backing list via
flush()?

If we call setValue() with a null list, I don't think flush() can do
anything, because we don't have any reference to a backing model to
update! Therefore, any changes made in the ListEditor cannot be saved?
You'd have to use an OptionalFieldEditor if you want to save it.

So it seems like at most we can display a read-only, empty list.
There's no point in letting the user edit something they can't save.

Or maybe I missed something - pretty likely, actually.

- Brian

-- 
http://groups.google.com/group/Google-Web-Toolkit-Contributors


[gwt-contrib] Re: Issue 7038: CompositeEditor and ListEditor optimizations (issue1664803)

2012-05-19 Thread Thomas Broyer


On Friday, May 18, 2012 10:02:49 PM UTC+2, Brian Slesinsky wrote:

 On Thu, May 17, 2012 at 5:04 PM,  t.bro...@gmail.com wrote: 

  setValue() is part of the ValueAwareEditor contract (inherited through 
  CompositeEditor); it's called by the Editor framework when you 
  EditorDriver#edit() some object (and, to be exact, also in subeditors of 
  CompositeEditors), then flush() is called when you EditorDriver#flush(). 
  ListEditor#getList() can then be used to add/remove/reorder elements of 
  the edited list, with direct effect on subeditors, which can be accessed 
  by #getEditor(). 
  As you can see, the list returned by either method is stale as soon as 
  #setValue is called again. IMO, this is fine, because getList() should 
  return 'null' if setValue received a 'null' (more on that later); and 
  it's not illogical to return a different list instance when the backing 
  list changes. 

 Okay, I did some reading and it seems that the normal lifecycle of an 
 edit begins with setValue() and ends with flush().


Well, you can call flush() as many times as you want, it doesn't end 
editing. (you can do that to use Bean Validation for instance: call flush() 
to put the fields' values back in the edited object, validate the object, 
if there are any ConstraintViolation, give them to the EditorDriver for 
display; also some editors –e.g. ValueBoxEditor– only report errors on 
flush, so you can only basically only check hasErrors after flush).
 

 So I agree that is 
 seems logical that a live view would only last until the next 
 flush() or at most until the next setValue(). But this isn't 
 well-documented in this class or anywhere else that I've found so far.


To me, 
https://developers.google.com/web-toolkit/doc/latest/DevGuideUiEditors is 
clear enough. YMMV though.
 

 So maybe we want to do that now? I also wonder if, for consistency, we 
 want to make sure the live view goes stale on *every* call to 
 setValue(), which would make our optimization a bit trickier; we 
 should probably create a new ListValueProvider and copy all the 
 subeditors into it.


ListEditorWrapper could track this in detach() and from then on act as an 
immutable list (throwing exceptions if you try to change it).
 

  2. there would still need some special treatment in getList to return 
  'null' if 'null' was passed to setValue. 

 Normally I like to detect null lists and throw an exception 
 immediately (it's usually a mistake) but in this case there may be 
 beans that have null lists, so we should probably not die. But I don't 
 think we need to preserve null lists or that editors need to display 
 null lists differently than empty lists, allow users to specify null 
 versus empty, and so on.


We could basically merge OptionalFieldEditor functionality into ListEditor 
(instead of having to use both) but turning null into empty lists would 
break amny things (see below).
I'm in favor of separation of concerns though. If you have an editor for a 
sub-object, then setting a 'null' will fail with an NPE when trying to pass 
values to sub-editors; I believe this is why OptionalFieldEditor was added 
in the first place (from memory, BobV added it after a discussion with 
Patrick Julien on the GWT Users group). If you ask me, for consistency, I'd 
remove the null-check in ListEditor and let it fail for 'null' values, just 
like it did originally. It might have been added by mistake, I don't know, 
it was added as part of a bigger change and wasn't tracked/documented at 
all, so who knows?
 

 (Do existing editors do anything here?)


CheckBox turns 'null' into 'Boolean.FALSE' and TextBox turns 'null' into 
the empty string, and people have complained.
See http://code.google.com/p/google-web-toolkit/issues/detail?id=5976#c1 
(I'm sure this was discussed, with John or Ray R, and I started working on 
a patch; can't find this though)

If 
 not, I think we might want to immediately convert nulls into empty 
 lists on input, so we don't blow up but you never get a null list back 
 again after an edit. This would be following Postel's law again - be 
 liberal in what you accept and conservative in what you send.


It would however generate a change when using RequestFactory, because 
'null' is different from an empty-list.

 Today, if you want to be able to change the list field from 'null' no 
  non-null or vice versa, you still need the OptionalFieldEditor. 

 Sure, makes sense. 

  flush() must not throw in that case, and getList should return 'null' 
  (rather than, say an empty list, be it unmodifiable). 

 Hmm, why? I think it might be okay to return an empty list.


Only if it was then flushed into the edited property (otherwise your 
changes to the empty list would be lost), changing it from 'null' to an 
empty list even if the user didn't do anything: edit(), flush(), and boom, 
your object has changed!
That's the kind of behavior I'd rather fight against: getValue just after 
setValue should try to preserve the value 

[gwt-contrib] Re: Issue 7038: CompositeEditor and ListEditor optimizations (issue1664803)

2012-05-18 Thread Brian Slesinsky
On Thu, May 17, 2012 at 5:04 PM,  t.bro...@gmail.com wrote:

 setValue() is part of the ValueAwareEditor contract (inherited through
 CompositeEditor); it's called by the Editor framework when you
 EditorDriver#edit() some object (and, to be exact, also in subeditors of
 CompositeEditors), then flush() is called when you EditorDriver#flush().
 ListEditor#getList() can then be used to add/remove/reorder elements of
 the edited list, with direct effect on subeditors, which can be accessed
 by #getEditor().
 As you can see, the list returned by either method is stale as soon as
 #setValue is called again. IMO, this is fine, because getList() should
 return 'null' if setValue received a 'null' (more on that later); and
 it's not illogical to return a different list instance when the backing
 list changes.

Okay, I did some reading and it seems that the normal lifecycle of an
edit begins with setValue() and ends with flush(). So I agree that is
seems logical that a live view would only last until the next
flush() or at most until the next setValue(). But this isn't
well-documented in this class or anywhere else that I've found so far.
So maybe we want to do that now? I also wonder if, for consistency, we
want to make sure the live view goes stale on *every* call to
setValue(), which would make our optimization a bit trickier; we
should probably create a new ListValueProvider and copy all the
subeditors into it.

 2. there would still need some special treatment in getList to return
 'null' if 'null' was passed to setValue.

Normally I like to detect null lists and throw an exception
immediately (it's usually a mistake) but in this case there may be
beans that have null lists, so we should probably not die. But I don't
think we need to preserve null lists or that editors need to display
null lists differently than empty lists, allow users to specify null
versus empty, and so on. (Do existing editors do anything here?) If
not, I think we might want to immediately convert nulls into empty
lists on input, so we don't blow up but you never get a null list back
again after an edit. This would be following Postel's law again - be
liberal in what you accept and conservative in what you send.

 Today, if you want to be able to change the list field from 'null' no
 non-null or vice versa, you still need the OptionalFieldEditor.

Sure, makes sense.

 flush() must not throw in that case, and getList should return 'null'
 (rather than, say an empty list, be it unmodifiable).

Hmm, why? I think it might be okay to return an empty list.

-- 
http://groups.google.com/group/Google-Web-Toolkit-Contributors


[gwt-contrib] Re: Issue 7038: CompositeEditor and ListEditor optimizations (issue1664803)

2012-05-18 Thread Brian Slesinsky
Also: are editors typically designed for reuse, or will we break
people who have taken shortcuts? Maybe editors need to declare somehow
that they can be reused?

-- 
http://groups.google.com/group/Google-Web-Toolkit-Contributors


[gwt-contrib] Re: Issue 7038: CompositeEditor and ListEditor optimizations (issue1664803)

2012-05-18 Thread branflake2267

For me, I'm more concerned about setting it null. Not sure this would
work, but if setValue(null) create an empty list to use and don't even
worry about NPE checks. Shoot if set null and returns empty not such a
bad side effect.

On 2012/05/18 00:04:26, tbroyer wrote:

On 2012/05/17 21:38:03, skybrian wrote:
 Oops, I had started an email about the revert but apparently never

sent it.

 Sorry about that!



No problem!



 I might need some background about the editor framework...




https://gwt-code-reviews.appspot.com/1664803/diff/4002/user/src/com/google/gwt/editor/client/adapters/ListEditor.java

 File user/src/com/google/gwt/editor/client/adapters/ListEditor.java

(right):





https://gwt-code-reviews.appspot.com/1664803/diff/4002/user/src/com/google/gwt/editor/client/adapters/ListEditor.java#newcode84

 user/src/com/google/gwt/editor/client/adapters/ListEditor.java:84:

return

 Collections.emptyList();
 If someone calls setList() then the list returned by this method is

no longer

 live; it will still be empty even though there are new items. Is

that what we

 want? It seems unlikely, but if so it should be documented.



setValue() is part of the ValueAwareEditor contract (inherited through
CompositeEditor); it's called by the Editor framework when you
EditorDriver#edit() some object (and, to be exact, also in subeditors

of

CompositeEditors), then flush() is called when you

EditorDriver#flush().

ListEditor#getList() can then be used to add/remove/reorder elements

of the

edited list, with direct effect on subeditors, which can be accessed

by

#getEditor().
As you can see, the list returned by either method is stale as soon as

#setValue

is called again. IMO, this is fine, because getList() should return

'null' if

setValue received a 'null' (more on that later); and it's not

illogical to

return a different list instance when the backing list changes.



For completeness: calling setValue yourself on any ValueAwareEditor

would in

many case have no effect, and at worse would simply confuse the editor

and/or

the Editor framework. In any case, it wouldn't change the value of the

edited

property after a flush(), because there's no getValue().
The only exception here is OptionalFieldEditor, because it's also a
LeafValueEditor, and this behavior is thus on-purpose.



 It seems like a better idea to create the ListEditorWrapper

immediately in the

 constructor and make it final. When setValue() is called, we should

call a new

 method like ListEditorWrapper.replaceBacking(). Then live views

never expire

and
 we don't have to worry about null checks in this class.



There are a few issues with this approach:
1. it would basically only move the null-checks to ListEditorWrapper.
2. there would still need some special treatment in getList to return

'null' if

'null' was passed to setValue.



Let's talk about that last case though: originally,

ListEditor#getValue would

throw an NPE if it received a 'null'. BobV said on the GWT group at

that time

that you should wrapp the ListEditor into an OptionalFieldEditor if

you could

have 'null's. A few weeks/months later, he added the null-check to

setValue, but

didn't change flush() (and to a lesser extent, getEditors).
Today, if you want to be able to change the list field from 'null' no

non-null

or vice versa, you still need the OptionalFieldEditor.



If you asked me, I would have kept the original rule; at least the

contract was

clear. Now with the ListEditor accepting 'null's, IMO, flush() must

not throw in

that case, and getList should return 'null' (rather than, say an empty

list, be

it unmodifiable). getEditors() could return either 'null' or an empty

list, it

doesn't really matter given that a) the list is unmodifiable and b) if

the value

changes from 'null' to a non-null value, a new list would have been

returned

anyway (I mean, when change the backing list, a live-view retrieved

for the

first value is no longer valid after the call to setValue, the

behavior here

wouldn't change then).
This is what patch set #3 does here.




http://gwt-code-reviews.appspot.com/1664803/

--
http://groups.google.com/group/Google-Web-Toolkit-Contributors


[gwt-contrib] Re: Issue 7038: CompositeEditor and ListEditor optimizations (issue1664803)

2012-05-17 Thread t . broyer

Hi Brian,

I just saw it was rolled back. Patchset #2 fixes the NPE (that was
rather obvious actually).
Should I also add a test?

https://gwt-code-reviews.appspot.com/1664803/

--
http://groups.google.com/group/Google-Web-Toolkit-Contributors


[gwt-contrib] Re: Issue 7038: CompositeEditor and ListEditor optimizations (issue1664803)

2012-05-17 Thread Brian Slesinsky
Yes please. Sorry about missing this in the review!
On May 17, 2012 8:23 AM, t.bro...@gmail.com wrote:

 Hi Brian,

 I just saw it was rolled back. Patchset #2 fixes the NPE (that was
 rather obvious actually).
 Should I also add a test?

 https://gwt-code-reviews.**appspot.com/1664803/https://gwt-code-reviews.appspot.com/1664803/


-- 
http://groups.google.com/group/Google-Web-Toolkit-Contributors

[gwt-contrib] Re: Issue 7038: CompositeEditor and ListEditor optimizations (issue1664803)

2012-05-17 Thread Thomas Broyer
Done.

I also fixed two inconsistencies wrt editing a 'null' value (I just
discussed about it on the GWT users group:
https://groups.google.com/d/topic/google-web-toolkit/xQA-TiQUbLA/discussion
); one of them is a breaking change, though I believe it won't hurt
anyone (suppressed an exception case).

Note that passing 'null' to driver.edit() does not behave the same
(flush() will throw), but that's a different issue (and much less
likely to happen).

On Thu, May 17, 2012 at 6:59 PM, Brian Slesinsky skybr...@google.com wrote:
 Yes please. Sorry about missing this in the review!

 On May 17, 2012 8:23 AM, t.bro...@gmail.com wrote:

 Hi Brian,

 I just saw it was rolled back. Patchset #2 fixes the NPE (that was
 rather obvious actually).
 Should I also add a test?

 https://gwt-code-reviews.appspot.com/1664803/



-- 
Thomas Broyer
/tɔ.ma.bʁwa.je/

-- 
http://groups.google.com/group/Google-Web-Toolkit-Contributors


[gwt-contrib] Re: Issue 7038: CompositeEditor and ListEditor optimizations (issue1664803)

2012-05-17 Thread skybrian

Oops, I had started an email about the revert but apparently never sent
it. Sorry about that!

I might need some background about the editor framework...



https://gwt-code-reviews.appspot.com/1664803/diff/4002/user/src/com/google/gwt/editor/client/adapters/ListEditor.java
File user/src/com/google/gwt/editor/client/adapters/ListEditor.java
(right):

https://gwt-code-reviews.appspot.com/1664803/diff/4002/user/src/com/google/gwt/editor/client/adapters/ListEditor.java#newcode84
user/src/com/google/gwt/editor/client/adapters/ListEditor.java:84:
return Collections.emptyList();
If someone calls setList() then the list returned by this method is no
longer live; it will still be empty even though there are new items. Is
that what we want? It seems unlikely, but if so it should be documented.

It seems like a better idea to create the ListEditorWrapper immediately
in the constructor and make it final. When setValue() is called, we
should call a new method like ListEditorWrapper.replaceBacking(). Then
live views never expire and we don't have to worry about null checks in
this class.

But then again, that's a change in semantics and I know nothing about
the editor framework. If you don't want to open this can of worms, I
suggest reverting the changes to flush() and getEditors() and leaving it
for another CL.

https://gwt-code-reviews.appspot.com/1664803/

--
http://groups.google.com/group/Google-Web-Toolkit-Contributors


[gwt-contrib] Re: Issue 7038: CompositeEditor and ListEditor optimizations (issue1664803)

2012-05-17 Thread t . broyer

On 2012/05/17 21:38:03, skybrian wrote:

Oops, I had started an email about the revert but apparently never

sent it.

Sorry about that!


No problem!


I might need some background about the editor framework...



https://gwt-code-reviews.appspot.com/1664803/diff/4002/user/src/com/google/gwt/editor/client/adapters/ListEditor.java

File user/src/com/google/gwt/editor/client/adapters/ListEditor.java

(right):


https://gwt-code-reviews.appspot.com/1664803/diff/4002/user/src/com/google/gwt/editor/client/adapters/ListEditor.java#newcode84

user/src/com/google/gwt/editor/client/adapters/ListEditor.java:84:

return

Collections.emptyList();
If someone calls setList() then the list returned by this method is no

longer

live; it will still be empty even though there are new items. Is that

what we

want? It seems unlikely, but if so it should be documented.


setValue() is part of the ValueAwareEditor contract (inherited through
CompositeEditor); it's called by the Editor framework when you
EditorDriver#edit() some object (and, to be exact, also in subeditors of
CompositeEditors), then flush() is called when you EditorDriver#flush().
ListEditor#getList() can then be used to add/remove/reorder elements of
the edited list, with direct effect on subeditors, which can be accessed
by #getEditor().
As you can see, the list returned by either method is stale as soon as
#setValue is called again. IMO, this is fine, because getList() should
return 'null' if setValue received a 'null' (more on that later); and
it's not illogical to return a different list instance when the backing
list changes.

For completeness: calling setValue yourself on any ValueAwareEditor
would in many case have no effect, and at worse would simply confuse the
editor and/or the Editor framework. In any case, it wouldn't change the
value of the edited property after a flush(), because there's no
getValue().
The only exception here is OptionalFieldEditor, because it's also a
LeafValueEditor, and this behavior is thus on-purpose.


It seems like a better idea to create the ListEditorWrapper

immediately in the

constructor and make it final. When setValue() is called, we should

call a new

method like ListEditorWrapper.replaceBacking(). Then live views never

expire and

we don't have to worry about null checks in this class.


There are a few issues with this approach:
1. it would basically only move the null-checks to ListEditorWrapper.
2. there would still need some special treatment in getList to return
'null' if 'null' was passed to setValue.

Let's talk about that last case though: originally, ListEditor#getValue
would throw an NPE if it received a 'null'. BobV said on the GWT group
at that time that you should wrapp the ListEditor into an
OptionalFieldEditor if you could have 'null's. A few weeks/months later,
he added the null-check to setValue, but didn't change flush() (and to a
lesser extent, getEditors).
Today, if you want to be able to change the list field from 'null' no
non-null or vice versa, you still need the OptionalFieldEditor.

If you asked me, I would have kept the original rule; at least the
contract was clear. Now with the ListEditor accepting 'null's, IMO,
flush() must not throw in that case, and getList should return 'null'
(rather than, say an empty list, be it unmodifiable). getEditors() could
return either 'null' or an empty list, it doesn't really matter given
that a) the list is unmodifiable and b) if the value changes from 'null'
to a non-null value, a new list would have been returned anyway (I mean,
when change the backing list, a live-view retrieved for the first value
is no longer valid after the call to setValue, the behavior here
wouldn't change then).
This is what patch set #3 does here.



https://gwt-code-reviews.appspot.com/1664803/

--
http://groups.google.com/group/Google-Web-Toolkit-Contributors


[gwt-contrib] Re: Issue 7038: CompositeEditor and ListEditor optimizations (issue1664803)

2012-05-14 Thread skybrian

LGTM


https://gwt-code-reviews.appspot.com/1664803/

--
http://groups.google.com/group/Google-Web-Toolkit-Contributors