Bug 568252 - [DataBinding] typed BeanProperties - QoL improvement for value().observe()
Summary: [DataBinding] typed BeanProperties - QoL improvement for value().observe()
Status: NEW
Alias: None
Product: Platform
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 4.18   Edit
Hardware: All All
: P3 enhancement (vote)
Target Milestone: ---   Edit
Assignee: Platform-UI-Inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-10-26 10:02 EDT by Marko Friedemann CLA
Modified: 2020-10-26 10:02 EDT (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Marko Friedemann CLA 2020-10-26 10:02:17 EDT
Hey,

I recently rewrote existing code from the deprecated untyped databinding classes
to the typed ones, mainly for cleaning up, getting rid of warning suppressions etc.

In doing so, I stumbled upon a slight inconvenience with BeanProperties.value(...) and
the subsequent DelegatingValueProperty.observe(...), that either requires an ugly cast
or messing around with DecoratingObservableValue (and another cast).

,-- old code, using org.eclipse.core.databinding.beans.BeanProperties --
| 
| protected <W extends Widget, T> void bind(W widget, ModelObject pojo, String prop) {
| 	// [...]
| 	IObservableValue<T> propertyObservable = BeanProperties.value(
| 		pojo.getClass(), prop).<T>observe(pojo);
| 	// [...]
| }
`---

,-- new code, using org.eclipse.core.databinding.beans.typed.BeanProperties --
| 
| protected <W extends Widget, T> void bind(W widget, ModelObject pojo, String prop) {
| 	// [...]
| 	IObservableValue<T> propertyObservable = BeanProperties.<ModelObject, T>value(
| 		// #1, ugly cast to satisfy method signature
| 		(Class<ModelObject>) pojo.getClass(), propertyName).observe(pojo);
| 	// [...]
| }
`---

First issue, the signature of the value() method used here is:
,-- (https://git.eclipse.org/c/platform/eclipse.platform.ui.git/tree/bundles/org.eclipse.core.databinding.beans/src/org/eclipse/core/databinding/beans/typed/BeanProperties.java?id=0475aa4a1e912f18eec6b857bfb17b9e46b15350#n99) --
| public static <S, T> IBeanValueProperty<S, T> value(Class<S> beanClass, String propertyName) {
| 	return value(beanClass, propertyName, null);
| }
`---

So, supplying the pojo.getClass() (which is Class<? extends ModelObject>) still
requires a cast, and the unchecked warning we tried to get rid off is still there.

To get rid of that cast, I then tried to use the value() method that does not take
the class argument:
,-- (https://git.eclipse.org/c/platform/eclipse.platform.ui.git/tree/bundles/org.eclipse.core.databinding.beans/src/org/eclipse/core/databinding/beans/typed/BeanProperties.java?id=0475aa4a1e912f18eec6b857bfb17b9e46b15350#n68) --
| public static <S, T> IBeanValueProperty<S, T> value(String propertyName) {
| 	return value(null, propertyName, null);
| }
`---

Due to not having access to the target class, the result is a BeanObservableValueDecorator
using an AnonymousBeanValueProperty and a propertyDescriptor of null. Calling observe() on this
uses delegate.observe() and correctly creates a new, non-anonymous BeanValueObservableDecorator
with the propertyDescriptor initialized.
BUT it immediately creates another one, supplying its own propertyDecriptor (null) again:
,-- (https://git.eclipse.org/c/platform/eclipse.platform.ui.git/tree/bundles/org.eclipse.core.databinding.beans/src/org/eclipse/core/internal/databinding/beans/BeanValuePropertyDecorator.java?id=0475aa4a1e912f18eec6b857bfb17b9e46b15350#n142) --
| public IObservableValue<T> observe(S source) {
| 	return new BeanObservableValueDecorator<>(delegate.observe(source), propertyDescriptor);
| }
`---

The end result: the observable does not have the propertyDescriptor set, requiring extra code like
,--
| // ...
| IBeanObservable bo = (IBeanObservable) binding.getModel();
| // #2, check and messing around with DecoratingObservableValue and another cast
| if (null == bo.getPropertyDescriptor() && bo instanceof DecoratingObservableValue) {
| 	bo = (IBeanObservable) ((DecoratingObservableValue<?>) bo).getDecorated();
| }
`---


TLDR;
The typed BeanProperties might be improved, QoL wise, with a number of changes, or even a combination of them.

1)
Change the signature of the value(Class<S> beanClass, ...) methods to avoid casts like #1 above

- public static <S, T> IBeanValueProperty<S, T> value(Class<S> beanClass, ...
+ public static <S, T> IBeanValueProperty<S, T> value(Class<? extends S> beanClass, ...



2)
Check if the observe(...) methods in BeanValuePropertyDecorator:142ff might not just return
the result of invoking the delegated method.

- return new BeanObservableValueDecorator<>(delegate.observe(source), propertyDescriptor);
+ return delegate.observe(source);


Thanks for reading,
best regards,
M.