Community
Participate
Working Groups
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.