|
Lines 8-24
Link Here
|
| 8 |
* Contributors: |
8 |
* Contributors: |
| 9 |
* IBM Corporation - initial API and implementation |
9 |
* IBM Corporation - initial API and implementation |
| 10 |
* Brad Reynolds - bugs 164268, 171616, 147515 |
10 |
* Brad Reynolds - bugs 164268, 171616, 147515 |
| 11 |
* Matthew Hall - bug 221704, 234686, 246625 |
11 |
* Matthew Hall - bug 221704, 234686, 246625, 194734 |
| 12 |
* Thomas Kratz - bug 213787 |
12 |
* Thomas Kratz - bug 213787 |
| 13 |
*******************************************************************************/ |
13 |
*******************************************************************************/ |
| 14 |
package org.eclipse.core.databinding.beans; |
14 |
package org.eclipse.core.databinding.beans; |
| 15 |
|
15 |
|
| 16 |
import java.beans.BeanInfo; |
|
|
| 17 |
import java.beans.IntrospectionException; |
| 18 |
import java.beans.Introspector; |
| 19 |
import java.beans.PropertyDescriptor; |
16 |
import java.beans.PropertyDescriptor; |
| 20 |
|
17 |
|
| 21 |
import org.eclipse.core.databinding.BindingException; |
|
|
| 22 |
import org.eclipse.core.databinding.observable.IObservable; |
18 |
import org.eclipse.core.databinding.observable.IObservable; |
| 23 |
import org.eclipse.core.databinding.observable.Realm; |
19 |
import org.eclipse.core.databinding.observable.Realm; |
| 24 |
import org.eclipse.core.databinding.observable.list.IObservableList; |
20 |
import org.eclipse.core.databinding.observable.list.IObservableList; |
|
Lines 27-41
Link Here
|
| 27 |
import org.eclipse.core.databinding.observable.masterdetail.MasterDetailObservables; |
23 |
import org.eclipse.core.databinding.observable.masterdetail.MasterDetailObservables; |
| 28 |
import org.eclipse.core.databinding.observable.set.IObservableSet; |
24 |
import org.eclipse.core.databinding.observable.set.IObservableSet; |
| 29 |
import org.eclipse.core.databinding.observable.value.IObservableValue; |
25 |
import org.eclipse.core.databinding.observable.value.IObservableValue; |
|
|
26 |
import org.eclipse.core.databinding.property.IListProperty; |
| 27 |
import org.eclipse.core.databinding.property.IMapProperty; |
| 28 |
import org.eclipse.core.databinding.property.ISetProperty; |
| 29 |
import org.eclipse.core.databinding.property.IValueProperty; |
| 30 |
import org.eclipse.core.databinding.property.PropertyObservables; |
| 30 |
import org.eclipse.core.internal.databinding.beans.BeanObservableListDecorator; |
31 |
import org.eclipse.core.internal.databinding.beans.BeanObservableListDecorator; |
| 31 |
import org.eclipse.core.internal.databinding.beans.BeanObservableMapDecorator; |
32 |
import org.eclipse.core.internal.databinding.beans.BeanObservableMapDecorator; |
| 32 |
import org.eclipse.core.internal.databinding.beans.BeanObservableSetDecorator; |
33 |
import org.eclipse.core.internal.databinding.beans.BeanObservableSetDecorator; |
| 33 |
import org.eclipse.core.internal.databinding.beans.BeanObservableValueDecorator; |
34 |
import org.eclipse.core.internal.databinding.beans.BeanObservableValueDecorator; |
| 34 |
import org.eclipse.core.internal.databinding.beans.JavaBeanObservableList; |
35 |
import org.eclipse.core.internal.databinding.beans.BeanPropertyHelper; |
| 35 |
import org.eclipse.core.internal.databinding.beans.JavaBeanObservableMap; |
|
|
| 36 |
import org.eclipse.core.internal.databinding.beans.JavaBeanObservableSet; |
| 37 |
import org.eclipse.core.internal.databinding.beans.JavaBeanObservableValue; |
| 38 |
import org.eclipse.core.internal.databinding.beans.JavaBeanPropertyObservableMap; |
| 39 |
import org.eclipse.core.runtime.Assert; |
36 |
import org.eclipse.core.runtime.Assert; |
| 40 |
|
37 |
|
| 41 |
/** |
38 |
/** |
|
Lines 83-91
Link Here
|
| 83 |
*/ |
80 |
*/ |
| 84 |
public static IObservableValue observeValue(Realm realm, Object bean, |
81 |
public static IObservableValue observeValue(Realm realm, Object bean, |
| 85 |
String propertyName) { |
82 |
String propertyName) { |
| 86 |
PropertyDescriptor descriptor = getPropertyDescriptor(bean.getClass(), |
83 |
IValueProperty property = BeanProperties.valueProperty(bean.getClass(), |
| 87 |
propertyName); |
84 |
propertyName); |
| 88 |
return new JavaBeanObservableValue(realm, bean, descriptor); |
85 |
PropertyDescriptor propertyDescriptor = ((IBeanProperty) property) |
|
|
86 |
.getPropertyDescriptor(); |
| 87 |
return new BeanObservableValueDecorator(PropertyObservables |
| 88 |
.observeValue(realm, bean, property), propertyDescriptor); |
| 89 |
} |
89 |
} |
| 90 |
|
90 |
|
| 91 |
/** |
91 |
/** |
|
Lines 103-111
Link Here
|
| 103 |
*/ |
103 |
*/ |
| 104 |
public static IObservableMap observeMap(IObservableSet domain, |
104 |
public static IObservableMap observeMap(IObservableSet domain, |
| 105 |
Class beanClass, String propertyName) { |
105 |
Class beanClass, String propertyName) { |
| 106 |
PropertyDescriptor descriptor = getPropertyDescriptor(beanClass, |
106 |
IValueProperty property = BeanProperties.valueProperty(beanClass, |
| 107 |
propertyName); |
107 |
propertyName); |
| 108 |
return new JavaBeanObservableMap(domain, descriptor); |
108 |
PropertyDescriptor propertyDescriptor = ((IBeanProperty) property) |
|
|
109 |
.getPropertyDescriptor(); |
| 110 |
return new BeanObservableMapDecorator(PropertyObservables.observeDetailValues( |
| 111 |
domain, property), propertyDescriptor); |
| 109 |
} |
112 |
} |
| 110 |
|
113 |
|
| 111 |
/** |
114 |
/** |
|
Lines 124-132
Link Here
|
| 124 |
*/ |
127 |
*/ |
| 125 |
public static IObservableMap observeMap(Realm realm, Object bean, |
128 |
public static IObservableMap observeMap(Realm realm, Object bean, |
| 126 |
String propertyName) { |
129 |
String propertyName) { |
| 127 |
PropertyDescriptor descriptor = getPropertyDescriptor(bean.getClass(), |
130 |
IMapProperty property = BeanProperties.mapProperty(bean.getClass(), |
| 128 |
propertyName); |
131 |
propertyName); |
| 129 |
return new JavaBeanPropertyObservableMap(realm, bean, descriptor); |
132 |
PropertyDescriptor propertyDescriptor = ((IBeanProperty) property) |
|
|
133 |
.getPropertyDescriptor(); |
| 134 |
return new BeanObservableMapDecorator(PropertyObservables.observeMap( |
| 135 |
bean, property), propertyDescriptor); |
| 130 |
} |
136 |
} |
| 131 |
|
137 |
|
| 132 |
/** |
138 |
/** |
|
Lines 145-171
Link Here
|
| 145 |
return observeMap(Realm.getDefault(), bean, propertyName); |
151 |
return observeMap(Realm.getDefault(), bean, propertyName); |
| 146 |
} |
152 |
} |
| 147 |
|
153 |
|
| 148 |
/*package*/ static PropertyDescriptor getPropertyDescriptor(Class beanClass, |
|
|
| 149 |
String propertyName) { |
| 150 |
BeanInfo beanInfo; |
| 151 |
try { |
| 152 |
beanInfo = Introspector.getBeanInfo(beanClass); |
| 153 |
} catch (IntrospectionException e) { |
| 154 |
// cannot introspect, give up |
| 155 |
return null; |
| 156 |
} |
| 157 |
PropertyDescriptor[] propertyDescriptors = beanInfo |
| 158 |
.getPropertyDescriptors(); |
| 159 |
for (int i = 0; i < propertyDescriptors.length; i++) { |
| 160 |
PropertyDescriptor descriptor = propertyDescriptors[i]; |
| 161 |
if (descriptor.getName().equals(propertyName)) { |
| 162 |
return descriptor; |
| 163 |
} |
| 164 |
} |
| 165 |
throw new BindingException( |
| 166 |
"Could not find property with name " + propertyName + " in class " + beanClass); //$NON-NLS-1$ //$NON-NLS-2$ |
| 167 |
} |
| 168 |
|
| 169 |
/** |
154 |
/** |
| 170 |
* Returns an array of observable maps in the default realm tracking the |
155 |
* Returns an array of observable maps in the default realm tracking the |
| 171 |
* current values of the named propertys for the beans in the given set. |
156 |
* current values of the named propertys for the beans in the given set. |
|
Lines 231-239
Link Here
|
| 231 |
* collection-typed named property of the given bean object. The returned |
216 |
* collection-typed named property of the given bean object. The returned |
| 232 |
* list is mutable. When an item is added or removed the setter is invoked |
217 |
* list is mutable. When an item is added or removed the setter is invoked |
| 233 |
* for the list on the parent bean to provide notification to other |
218 |
* for the list on the parent bean to provide notification to other |
| 234 |
* listeners via <code>PropertyChangeEvents</code>. This is done to |
219 |
* listeners via <code>PropertyChangeEvents</code>. This is done to provide |
| 235 |
* provide the same behavior as is expected from arrays as specified in the |
220 |
* the same behavior as is expected from arrays as specified in the bean |
| 236 |
* bean spec in section 7.2. |
221 |
* spec in section 7.2. |
| 237 |
* |
222 |
* |
| 238 |
* @param realm |
223 |
* @param realm |
| 239 |
* the realm |
224 |
* the realm |
|
Lines 242-249
Link Here
|
| 242 |
* @param propertyName |
227 |
* @param propertyName |
| 243 |
* the name of the property |
228 |
* the name of the property |
| 244 |
* @param elementType |
229 |
* @param elementType |
| 245 |
* type of the elements in the list. If <code>null</code> and |
230 |
* type of the elements in the list. If <code>null</code> and the |
| 246 |
* the property is an array the type will be inferred. If |
231 |
* property is an array the type will be inferred. If |
| 247 |
* <code>null</code> and the property type cannot be inferred |
232 |
* <code>null</code> and the property type cannot be inferred |
| 248 |
* element type will be <code>null</code>. |
233 |
* element type will be <code>null</code>. |
| 249 |
* @return an observable list tracking the collection-typed named property |
234 |
* @return an observable list tracking the collection-typed named property |
|
Lines 251-262
Link Here
|
| 251 |
*/ |
236 |
*/ |
| 252 |
public static IObservableList observeList(Realm realm, Object bean, |
237 |
public static IObservableList observeList(Realm realm, Object bean, |
| 253 |
String propertyName, Class elementType) { |
238 |
String propertyName, Class elementType) { |
| 254 |
PropertyDescriptor propertyDescriptor = getPropertyDescriptor(bean |
239 |
IListProperty property = BeanProperties.listProperty(bean.getClass(), |
| 255 |
.getClass(), propertyName); |
240 |
propertyName, elementType); |
| 256 |
elementType = getCollectionElementType(elementType, propertyDescriptor); |
241 |
PropertyDescriptor propertyDescriptor = ((IBeanProperty) property) |
| 257 |
|
242 |
.getPropertyDescriptor(); |
| 258 |
return new JavaBeanObservableList(realm, bean, propertyDescriptor, |
243 |
return new BeanObservableListDecorator(PropertyObservables.observeList( |
| 259 |
elementType); |
244 |
realm, bean, property), propertyDescriptor); |
| 260 |
} |
245 |
} |
| 261 |
|
246 |
|
| 262 |
/** |
247 |
/** |
|
Lines 436-448
Link Here
|
| 436 |
*/ |
421 |
*/ |
| 437 |
public static IObservableValue observeDetailValue(Realm realm, |
422 |
public static IObservableValue observeDetailValue(Realm realm, |
| 438 |
IObservableValue master, String propertyName, Class propertyType) { |
423 |
IObservableValue master, String propertyName, Class propertyType) { |
| 439 |
|
|
|
| 440 |
IObservableValue value = MasterDetailObservables.detailValue(master, |
424 |
IObservableValue value = MasterDetailObservables.detailValue(master, |
| 441 |
valueFactory(realm, propertyName), propertyType); |
425 |
valueFactory(realm, propertyName), propertyType); |
| 442 |
BeanObservableValueDecorator decorator = new BeanObservableValueDecorator( |
426 |
return new BeanObservableValueDecorator(value, BeanPropertyHelper |
| 443 |
value, getValueTypePropertyDescriptor(master, propertyName)); |
427 |
.getValueTypePropertyDescriptor(master, propertyName)); |
| 444 |
|
|
|
| 445 |
return decorator; |
| 446 |
} |
428 |
} |
| 447 |
|
429 |
|
| 448 |
/** |
430 |
/** |
|
Lines 468-477
Link Here
|
| 468 |
/** |
450 |
/** |
| 469 |
* Helper method for |
451 |
* Helper method for |
| 470 |
* <code>MasterDetailObservables.detailValue(master, valueFactory(realm, |
452 |
* <code>MasterDetailObservables.detailValue(master, valueFactory(realm, |
| 471 |
* propertyName), propertyType)</code>. |
453 |
* propertyName), propertyType)</code>. This method returns an |
| 472 |
* This method returns an {@link IBeanObservable} with a |
454 |
* {@link IBeanObservable} with a {@link PropertyDescriptor} based on the |
| 473 |
* {@link PropertyDescriptor} based on the given master type and property |
455 |
* given master type and property name. |
| 474 |
* name. |
|
|
| 475 |
* |
456 |
* |
| 476 |
* @param realm |
457 |
* @param realm |
| 477 |
* the realm |
458 |
* the realm |
|
Lines 491-504
Link Here
|
| 491 |
* @since 1.1 |
472 |
* @since 1.1 |
| 492 |
*/ |
473 |
*/ |
| 493 |
public static IObservableValue observeDetailValue(Realm realm, |
474 |
public static IObservableValue observeDetailValue(Realm realm, |
| 494 |
IObservableValue master, Class masterType, String propertyName, Class propertyType) { |
475 |
IObservableValue master, Class masterType, String propertyName, |
|
|
476 |
Class propertyType) { |
| 495 |
Assert.isNotNull(masterType, "masterType cannot be null"); //$NON-NLS-1$ |
477 |
Assert.isNotNull(masterType, "masterType cannot be null"); //$NON-NLS-1$ |
| 496 |
IObservableValue value = MasterDetailObservables.detailValue(master, |
478 |
IObservableValue value = MasterDetailObservables.detailValue(master, |
| 497 |
valueFactory(realm, propertyName), propertyType); |
479 |
valueFactory(realm, propertyName), propertyType); |
| 498 |
BeanObservableValueDecorator decorator = new BeanObservableValueDecorator( |
480 |
return new BeanObservableValueDecorator(value, BeanPropertyHelper |
| 499 |
value, getPropertyDescriptor(masterType, propertyName)); |
481 |
.getPropertyDescriptor(masterType, propertyName)); |
| 500 |
|
|
|
| 501 |
return decorator; |
| 502 |
} |
482 |
} |
| 503 |
|
483 |
|
| 504 |
/** |
484 |
/** |
|
Lines 549-559
Link Here
|
| 549 |
IObservableList observableList = MasterDetailObservables.detailList( |
529 |
IObservableList observableList = MasterDetailObservables.detailList( |
| 550 |
master, listFactory(realm, propertyName, propertyType), |
530 |
master, listFactory(realm, propertyName, propertyType), |
| 551 |
propertyType); |
531 |
propertyType); |
| 552 |
BeanObservableListDecorator decorator = new BeanObservableListDecorator( |
532 |
return new BeanObservableListDecorator(observableList, |
| 553 |
observableList, getValueTypePropertyDescriptor(master, |
533 |
BeanPropertyHelper.getValueTypePropertyDescriptor(master, |
| 554 |
propertyName)); |
534 |
propertyName)); |
| 555 |
|
|
|
| 556 |
return decorator; |
| 557 |
} |
535 |
} |
| 558 |
|
536 |
|
| 559 |
/** |
537 |
/** |
|
Lines 593-607
Link Here
|
| 593 |
*/ |
571 |
*/ |
| 594 |
public static IObservableSet observeDetailSet(Realm realm, |
572 |
public static IObservableSet observeDetailSet(Realm realm, |
| 595 |
IObservableValue master, String propertyName, Class propertyType) { |
573 |
IObservableValue master, String propertyName, Class propertyType) { |
| 596 |
|
|
|
| 597 |
IObservableSet observableSet = MasterDetailObservables.detailSet( |
574 |
IObservableSet observableSet = MasterDetailObservables.detailSet( |
| 598 |
master, setFactory(realm, propertyName, propertyType), |
575 |
master, setFactory(realm, propertyName, propertyType), |
| 599 |
propertyType); |
576 |
propertyType); |
| 600 |
BeanObservableSetDecorator decorator = new BeanObservableSetDecorator( |
577 |
return new BeanObservableSetDecorator(observableSet, BeanPropertyHelper |
| 601 |
observableSet, getValueTypePropertyDescriptor(master, |
578 |
.getValueTypePropertyDescriptor(master, propertyName)); |
| 602 |
propertyName)); |
|
|
| 603 |
|
| 604 |
return decorator; |
| 605 |
} |
579 |
} |
| 606 |
|
580 |
|
| 607 |
/** |
581 |
/** |
|
Lines 640-649
Link Here
|
| 640 |
IObservableValue master, String propertyName) { |
614 |
IObservableValue master, String propertyName) { |
| 641 |
IObservableMap observableMap = MasterDetailObservables.detailMap( |
615 |
IObservableMap observableMap = MasterDetailObservables.detailMap( |
| 642 |
master, mapPropertyFactory(realm, propertyName)); |
616 |
master, mapPropertyFactory(realm, propertyName)); |
| 643 |
BeanObservableMapDecorator decorator = new BeanObservableMapDecorator( |
617 |
return new BeanObservableMapDecorator(observableMap, BeanPropertyHelper |
| 644 |
observableMap, getValueTypePropertyDescriptor(master, |
618 |
.getValueTypePropertyDescriptor(master, propertyName)); |
| 645 |
propertyName)); |
|
|
| 646 |
return decorator; |
| 647 |
} |
619 |
} |
| 648 |
|
620 |
|
| 649 |
/** |
621 |
/** |
|
Lines 686-697
Link Here
|
| 686 |
*/ |
658 |
*/ |
| 687 |
public static IObservableSet observeSet(Realm realm, Object bean, |
659 |
public static IObservableSet observeSet(Realm realm, Object bean, |
| 688 |
String propertyName, Class elementType) { |
660 |
String propertyName, Class elementType) { |
| 689 |
PropertyDescriptor propertyDescriptor = getPropertyDescriptor(bean |
661 |
ISetProperty property = BeanProperties.setProperty(bean.getClass(), |
| 690 |
.getClass(), propertyName); |
662 |
propertyName, elementType); |
| 691 |
elementType = getCollectionElementType(elementType, propertyDescriptor); |
663 |
PropertyDescriptor propertyDescriptor = ((IBeanProperty) property) |
| 692 |
|
664 |
.getPropertyDescriptor(); |
| 693 |
return new JavaBeanObservableSet(realm, bean, propertyDescriptor, |
665 |
return new BeanObservableSetDecorator(PropertyObservables.observeSet( |
| 694 |
elementType); |
666 |
realm, bean, property), propertyDescriptor); |
| 695 |
} |
667 |
} |
| 696 |
|
668 |
|
| 697 |
/** |
669 |
/** |
|
Lines 778-794
Link Here
|
| 778 |
* @param propertyName |
750 |
* @param propertyName |
| 779 |
* the name of the property |
751 |
* the name of the property |
| 780 |
* @return a factory for creating {@link IObservableMap} objects |
752 |
* @return a factory for creating {@link IObservableMap} objects |
| 781 |
* |
753 |
* |
| 782 |
* @since 1.1 |
754 |
* @since 1.1 |
| 783 |
*/ |
755 |
*/ |
| 784 |
public static IObservableFactory setToMapFactory(final Class beanClass, final String propertyName) { |
756 |
public static IObservableFactory setToMapFactory(final Class beanClass, |
|
|
757 |
final String propertyName) { |
| 785 |
return new IObservableFactory() { |
758 |
return new IObservableFactory() { |
| 786 |
public IObservable createObservable(Object target) { |
759 |
public IObservable createObservable(Object target) { |
| 787 |
return observeMap((IObservableSet) target, beanClass, propertyName); |
760 |
return observeMap((IObservableSet) target, beanClass, |
|
|
761 |
propertyName); |
| 788 |
} |
762 |
} |
| 789 |
}; |
763 |
}; |
| 790 |
} |
764 |
} |
| 791 |
|
765 |
|
| 792 |
/** |
766 |
/** |
| 793 |
* Returns a factory for creating an observable map. The factory, when |
767 |
* Returns a factory for creating an observable map. The factory, when |
| 794 |
* provided with a bean object, will create an {@link IObservableMap} in the |
768 |
* provided with a bean object, will create an {@link IObservableMap} in the |
|
Lines 826-857
Link Here
|
| 826 |
public static IObservableFactory mapPropertyFactory(String propertyName) { |
800 |
public static IObservableFactory mapPropertyFactory(String propertyName) { |
| 827 |
return mapPropertyFactory(Realm.getDefault(), propertyName); |
801 |
return mapPropertyFactory(Realm.getDefault(), propertyName); |
| 828 |
} |
802 |
} |
| 829 |
|
|
|
| 830 |
/** |
| 831 |
* @param elementType |
| 832 |
* can be <code>null</code> |
| 833 |
* @param propertyDescriptor |
| 834 |
* @return type of the items in a collection/array property |
| 835 |
*/ |
| 836 |
/*package*/ static Class getCollectionElementType(Class elementType, |
| 837 |
PropertyDescriptor propertyDescriptor) { |
| 838 |
if (elementType == null) { |
| 839 |
Class propertyType = propertyDescriptor.getPropertyType(); |
| 840 |
elementType = propertyType.isArray() ? propertyType |
| 841 |
.getComponentType() : Object.class; |
| 842 |
} |
| 843 |
|
| 844 |
return elementType; |
| 845 |
} |
| 846 |
|
| 847 |
/** |
| 848 |
* @param observable |
| 849 |
* @param propertyName |
| 850 |
* @return property descriptor or <code>null</code> |
| 851 |
*/ |
| 852 |
/* package*/ static PropertyDescriptor getValueTypePropertyDescriptor( |
| 853 |
IObservableValue observable, String propertyName) { |
| 854 |
return (observable.getValueType() != null) ? getPropertyDescriptor( |
| 855 |
(Class) observable.getValueType(), propertyName) : null; |
| 856 |
} |
| 857 |
} |
803 |
} |