|
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, 226289, 246782 |
11 |
* Matthew Hall - bug 221704, 234686, 246625, 226289, 246782, 194734, |
|
|
12 |
* 195222, 247997 |
| 12 |
* Thomas Kratz - bug 213787 |
13 |
* Thomas Kratz - bug 213787 |
| 13 |
*******************************************************************************/ |
14 |
*******************************************************************************/ |
| 14 |
package org.eclipse.core.databinding.beans; |
15 |
package org.eclipse.core.databinding.beans; |
| 15 |
|
16 |
|
| 16 |
import java.beans.BeanInfo; |
|
|
| 17 |
import java.beans.IntrospectionException; |
| 18 |
import java.beans.Introspector; |
| 19 |
import java.beans.PropertyDescriptor; |
17 |
import java.beans.PropertyDescriptor; |
| 20 |
|
18 |
|
| 21 |
import org.eclipse.core.databinding.BindingException; |
|
|
| 22 |
import org.eclipse.core.databinding.observable.IObservable; |
19 |
import org.eclipse.core.databinding.observable.IObservable; |
| 23 |
import org.eclipse.core.databinding.observable.Realm; |
20 |
import org.eclipse.core.databinding.observable.Realm; |
| 24 |
import org.eclipse.core.databinding.observable.list.IObservableList; |
21 |
import org.eclipse.core.databinding.observable.list.IObservableList; |
|
Lines 33-43
Link Here
|
| 33 |
import org.eclipse.core.internal.databinding.beans.BeanObservableMapDecorator; |
30 |
import org.eclipse.core.internal.databinding.beans.BeanObservableMapDecorator; |
| 34 |
import org.eclipse.core.internal.databinding.beans.BeanObservableSetDecorator; |
31 |
import org.eclipse.core.internal.databinding.beans.BeanObservableSetDecorator; |
| 35 |
import org.eclipse.core.internal.databinding.beans.BeanObservableValueDecorator; |
32 |
import org.eclipse.core.internal.databinding.beans.BeanObservableValueDecorator; |
| 36 |
import org.eclipse.core.internal.databinding.beans.JavaBeanObservableList; |
33 |
import org.eclipse.core.internal.databinding.beans.BeanPropertyHelper; |
| 37 |
import org.eclipse.core.internal.databinding.beans.JavaBeanObservableMap; |
|
|
| 38 |
import org.eclipse.core.internal.databinding.beans.JavaBeanObservableSet; |
| 39 |
import org.eclipse.core.internal.databinding.beans.JavaBeanObservableValue; |
| 40 |
import org.eclipse.core.internal.databinding.beans.JavaBeanPropertyObservableMap; |
| 41 |
import org.eclipse.core.runtime.Assert; |
34 |
import org.eclipse.core.runtime.Assert; |
| 42 |
import org.eclipse.core.runtime.IStatus; |
35 |
import org.eclipse.core.runtime.IStatus; |
| 43 |
import org.eclipse.core.runtime.Status; |
36 |
import org.eclipse.core.runtime.Status; |
|
Lines 64-70
Link Here
|
| 64 |
* @param bean |
57 |
* @param bean |
| 65 |
* the object |
58 |
* the object |
| 66 |
* @param propertyName |
59 |
* @param propertyName |
| 67 |
* the name of the property |
60 |
* the name of the property. May be nested e.g. "parent.name" |
| 68 |
* @return an observable value tracking the current value of the named |
61 |
* @return an observable value tracking the current value of the named |
| 69 |
* property of the given bean |
62 |
* property of the given bean |
| 70 |
*/ |
63 |
*/ |
|
Lines 81-115
Link Here
|
| 81 |
* @param bean |
74 |
* @param bean |
| 82 |
* the object |
75 |
* the object |
| 83 |
* @param propertyName |
76 |
* @param propertyName |
| 84 |
* the name of the property |
77 |
* the name of the property. May be nested e.g. "parent.name" |
| 85 |
* @return an observable value tracking the current value of the named |
78 |
* @return an observable value tracking the current value of the named |
| 86 |
* property of the given bean |
79 |
* property of the given bean |
| 87 |
*/ |
80 |
*/ |
| 88 |
public static IObservableValue observeValue(Realm realm, Object bean, |
81 |
public static IObservableValue observeValue(Realm realm, Object bean, |
| 89 |
String propertyName) { |
82 |
String propertyName) { |
| 90 |
PropertyDescriptor descriptor = getPropertyDescriptor(bean.getClass(), |
83 |
return BeanProperties.value(bean.getClass(), propertyName).observe( |
| 91 |
propertyName); |
84 |
realm, bean); |
| 92 |
return new JavaBeanObservableValue(realm, bean, descriptor); |
|
|
| 93 |
} |
85 |
} |
| 94 |
|
86 |
|
| 95 |
/** |
87 |
/** |
| 96 |
* Returns an observable map in the default realm tracking the current |
88 |
* Returns an observable map in the given observable set's realm tracking |
| 97 |
* values of the named property for the beans in the given set. |
89 |
* the current values of the named property for the beans in the given set. |
|
|
90 |
* Elements in the set which do not have the named property will have null |
| 91 |
* values, and attempts to {@link IObservableMap#put(Object, Object) put} |
| 92 |
* values to these elements will be ignored. |
| 93 |
* |
| 94 |
* @param domain |
| 95 |
* the set of bean objects |
| 96 |
* @param propertyName |
| 97 |
* the name of the property. May be nested e.g. "parent.name" |
| 98 |
* @return an observable map tracking the current values of the named |
| 99 |
* property for the beans in the given domain set |
| 100 |
* @since 1.2 |
| 101 |
*/ |
| 102 |
public static IObservableMap observeMap(IObservableSet domain, |
| 103 |
String propertyName) { |
| 104 |
return BeanProperties.value(propertyName).observeDetail(domain); |
| 105 |
} |
| 106 |
|
| 107 |
/** |
| 108 |
* Returns an observable map in the given observable set's realm tracking |
| 109 |
* the current values of the named property for the beans in the given set. |
| 98 |
* |
110 |
* |
| 99 |
* @param domain |
111 |
* @param domain |
| 100 |
* the set of bean objects |
112 |
* the set of bean objects |
| 101 |
* @param beanClass |
113 |
* @param beanClass |
| 102 |
* the common base type of bean objects that may be in the set |
114 |
* the common base type of bean objects that may be in the set |
| 103 |
* @param propertyName |
115 |
* @param propertyName |
| 104 |
* the name of the property |
116 |
* the name of the property. May be nested e.g. "parent.name" |
| 105 |
* @return an observable map tracking the current values of the named |
117 |
* @return an observable map tracking the current values of the named |
| 106 |
* property for the beans in the given domain set |
118 |
* property for the beans in the given domain set |
| 107 |
*/ |
119 |
*/ |
| 108 |
public static IObservableMap observeMap(IObservableSet domain, |
120 |
public static IObservableMap observeMap(IObservableSet domain, |
| 109 |
Class beanClass, String propertyName) { |
121 |
Class beanClass, String propertyName) { |
| 110 |
PropertyDescriptor descriptor = getPropertyDescriptor(beanClass, |
122 |
return BeanProperties.value(beanClass, propertyName).observeDetail( |
| 111 |
propertyName); |
123 |
domain); |
| 112 |
return new JavaBeanObservableMap(domain, descriptor); |
|
|
| 113 |
} |
124 |
} |
| 114 |
|
125 |
|
| 115 |
/** |
126 |
/** |
|
Lines 121-127
Link Here
|
| 121 |
* @param bean |
132 |
* @param bean |
| 122 |
* the bean object |
133 |
* the bean object |
| 123 |
* @param propertyName |
134 |
* @param propertyName |
| 124 |
* the name of the property |
135 |
* the name of the property. May be nested e.g. "parent.name" |
| 125 |
* @return an observable map tracking the map-typed named property of the |
136 |
* @return an observable map tracking the map-typed named property of the |
| 126 |
* given bean object |
137 |
* given bean object |
| 127 |
* @since 1.1 |
138 |
* @since 1.1 |
|
Lines 140-146
Link Here
|
| 140 |
* @param bean |
151 |
* @param bean |
| 141 |
* the bean object |
152 |
* the bean object |
| 142 |
* @param propertyName |
153 |
* @param propertyName |
| 143 |
* the name of the property |
154 |
* the name of the property. May be nested e.g. "parent.name" |
| 144 |
* @param keyType |
155 |
* @param keyType |
| 145 |
* the element type of the observable map's key set, or |
156 |
* the element type of the observable map's key set, or |
| 146 |
* <code>null</code> if untyped |
157 |
* <code>null</code> if untyped |
|
Lines 153-162
Link Here
|
| 153 |
*/ |
164 |
*/ |
| 154 |
public static IObservableMap observeMap(Realm realm, Object bean, |
165 |
public static IObservableMap observeMap(Realm realm, Object bean, |
| 155 |
String propertyName, Class keyType, Class valueType) { |
166 |
String propertyName, Class keyType, Class valueType) { |
| 156 |
PropertyDescriptor descriptor = getPropertyDescriptor(bean.getClass(), |
167 |
return BeanProperties.map(bean.getClass(), propertyName, keyType, |
| 157 |
propertyName); |
168 |
valueType).observe(realm, bean); |
| 158 |
return new JavaBeanPropertyObservableMap(realm, bean, descriptor, |
|
|
| 159 |
keyType, valueType); |
| 160 |
} |
169 |
} |
| 161 |
|
170 |
|
| 162 |
/** |
171 |
/** |
|
Lines 166-172
Link Here
|
| 166 |
* @param bean |
175 |
* @param bean |
| 167 |
* the bean object |
176 |
* the bean object |
| 168 |
* @param propertyName |
177 |
* @param propertyName |
| 169 |
* the name of the property |
178 |
* the name of the property. May be nested e.g. "parent.name" |
| 170 |
* @return an observable map tracking the map-typed named property of the |
179 |
* @return an observable map tracking the map-typed named property of the |
| 171 |
* given bean object |
180 |
* given bean object |
| 172 |
* @since 1.2 |
181 |
* @since 1.2 |
|
Lines 193-233
Link Here
|
| 193 |
* given bean object |
202 |
* given bean object |
| 194 |
* @since 1.2 |
203 |
* @since 1.2 |
| 195 |
*/ |
204 |
*/ |
| 196 |
public static IObservableMap observeMap(Object bean, String propertyName, Class keyType, Class valueType) { |
205 |
public static IObservableMap observeMap(Object bean, String propertyName, |
| 197 |
return observeMap(Realm.getDefault(), bean, propertyName, keyType, valueType); |
206 |
Class keyType, Class valueType) { |
|
|
207 |
return observeMap(Realm.getDefault(), bean, propertyName, keyType, |
| 208 |
valueType); |
| 198 |
} |
209 |
} |
| 199 |
|
210 |
|
| 200 |
/*package*/ static PropertyDescriptor getPropertyDescriptor(Class beanClass, |
211 |
/** |
| 201 |
String propertyName) { |
212 |
* Returns an array of observable maps in the given observable set's realm |
| 202 |
BeanInfo beanInfo; |
213 |
* tracking the current values of the named properties for the beans in the |
| 203 |
try { |
214 |
* given set. Elements in the set which do not have the named property will |
| 204 |
beanInfo = Introspector.getBeanInfo(beanClass); |
215 |
* have null values, and attempts to |
| 205 |
} catch (IntrospectionException e) { |
216 |
* {@link IObservableMap#put(Object, Object) put} values to these elements |
| 206 |
// cannot introspect, give up |
217 |
* will be ignored. |
| 207 |
return null; |
218 |
* |
| 208 |
} |
219 |
* @param domain |
| 209 |
PropertyDescriptor[] propertyDescriptors = beanInfo |
220 |
* the set of objects |
| 210 |
.getPropertyDescriptors(); |
221 |
* @param propertyNames |
| 211 |
for (int i = 0; i < propertyDescriptors.length; i++) { |
222 |
* the array of property names. May be nested e.g. "parent.name" |
| 212 |
PropertyDescriptor descriptor = propertyDescriptors[i]; |
223 |
* @return an array of observable maps tracking the current values of the |
| 213 |
if (descriptor.getName().equals(propertyName)) { |
224 |
* named propertys for the beans in the given domain set |
| 214 |
return descriptor; |
225 |
* @since 1.2 |
| 215 |
} |
226 |
*/ |
|
|
227 |
public static IObservableMap[] observeMaps(IObservableSet domain, |
| 228 |
String[] propertyNames) { |
| 229 |
IObservableMap[] result = new IObservableMap[propertyNames.length]; |
| 230 |
for (int i = 0; i < propertyNames.length; i++) { |
| 231 |
result[i] = observeMap(domain, propertyNames[i]); |
| 216 |
} |
232 |
} |
| 217 |
throw new BindingException( |
233 |
return result; |
| 218 |
"Could not find property with name " + propertyName + " in class " + beanClass); //$NON-NLS-1$ //$NON-NLS-2$ |
|
|
| 219 |
} |
234 |
} |
| 220 |
|
235 |
|
| 221 |
/** |
236 |
/** |
| 222 |
* Returns an array of observable maps in the default realm tracking the |
237 |
* Returns an array of observable maps in the given observable set's realm |
| 223 |
* current values of the named propertys for the beans in the given set. |
238 |
* tracking the current values of the named properties for the beans in the |
|
|
239 |
* given set. |
| 224 |
* |
240 |
* |
| 225 |
* @param domain |
241 |
* @param domain |
| 226 |
* the set of objects |
242 |
* the set of objects |
| 227 |
* @param beanClass |
243 |
* @param beanClass |
| 228 |
* the common base type of objects that may be in the set |
244 |
* the common base type of objects that may be in the set |
| 229 |
* @param propertyNames |
245 |
* @param propertyNames |
| 230 |
* the array of property names |
246 |
* the array of property names. May be nested e.g. "parent.name" |
| 231 |
* @return an array of observable maps tracking the current values of the |
247 |
* @return an array of observable maps tracking the current values of the |
| 232 |
* named propertys for the beans in the given domain set |
248 |
* named propertys for the beans in the given domain set |
| 233 |
*/ |
249 |
*/ |
|
Lines 283-291
Link Here
|
| 283 |
* collection-typed named property of the given bean object. The returned |
299 |
* collection-typed named property of the given bean object. The returned |
| 284 |
* list is mutable. When an item is added or removed the setter is invoked |
300 |
* list is mutable. When an item is added or removed the setter is invoked |
| 285 |
* for the list on the parent bean to provide notification to other |
301 |
* for the list on the parent bean to provide notification to other |
| 286 |
* listeners via <code>PropertyChangeEvents</code>. This is done to |
302 |
* listeners via <code>PropertyChangeEvents</code>. This is done to provide |
| 287 |
* provide the same behavior as is expected from arrays as specified in the |
303 |
* the same behavior as is expected from arrays as specified in the bean |
| 288 |
* bean spec in section 7.2. |
304 |
* spec in section 7.2. |
| 289 |
* |
305 |
* |
| 290 |
* @param realm |
306 |
* @param realm |
| 291 |
* the realm |
307 |
* the realm |
|
Lines 294-301
Link Here
|
| 294 |
* @param propertyName |
310 |
* @param propertyName |
| 295 |
* the name of the property |
311 |
* the name of the property |
| 296 |
* @param elementType |
312 |
* @param elementType |
| 297 |
* type of the elements in the list. If <code>null</code> and |
313 |
* type of the elements in the list. If <code>null</code> and the |
| 298 |
* the property is an array the type will be inferred. If |
314 |
* property is an array the type will be inferred. If |
| 299 |
* <code>null</code> and the property type cannot be inferred |
315 |
* <code>null</code> and the property type cannot be inferred |
| 300 |
* element type will be <code>null</code>. |
316 |
* element type will be <code>null</code>. |
| 301 |
* @return an observable list tracking the collection-typed named property |
317 |
* @return an observable list tracking the collection-typed named property |
|
Lines 303-314
Link Here
|
| 303 |
*/ |
319 |
*/ |
| 304 |
public static IObservableList observeList(Realm realm, Object bean, |
320 |
public static IObservableList observeList(Realm realm, Object bean, |
| 305 |
String propertyName, Class elementType) { |
321 |
String propertyName, Class elementType) { |
| 306 |
PropertyDescriptor propertyDescriptor = getPropertyDescriptor(bean |
322 |
return BeanProperties.list(bean.getClass(), propertyName, elementType) |
| 307 |
.getClass(), propertyName); |
323 |
.observe(realm, bean); |
| 308 |
elementType = getCollectionElementType(elementType, propertyDescriptor); |
|
|
| 309 |
|
| 310 |
return new JavaBeanObservableList(realm, bean, propertyDescriptor, |
| 311 |
elementType); |
| 312 |
} |
324 |
} |
| 313 |
|
325 |
|
| 314 |
/** |
326 |
/** |
|
Lines 379-394
Link Here
|
| 379 |
* @param realm |
391 |
* @param realm |
| 380 |
* the realm to use |
392 |
* the realm to use |
| 381 |
* @param propertyName |
393 |
* @param propertyName |
| 382 |
* the name of the property |
394 |
* the name of the property. May be nested e.g. "parent.name" |
| 383 |
* @return an observable value factory |
395 |
* @return an observable value factory |
| 384 |
*/ |
396 |
*/ |
| 385 |
public static IObservableFactory valueFactory(final Realm realm, |
397 |
public static IObservableFactory valueFactory(final Realm realm, |
| 386 |
final String propertyName) { |
398 |
final String propertyName) { |
| 387 |
return new IObservableFactory() { |
399 |
return BeanProperties.value(propertyName).valueFactory(realm); |
| 388 |
public IObservable createObservable(Object target) { |
|
|
| 389 |
return observeValue(realm, target, propertyName); |
| 390 |
} |
| 391 |
}; |
| 392 |
} |
400 |
} |
| 393 |
|
401 |
|
| 394 |
/** |
402 |
/** |
|
Lines 396-402
Link Here
|
| 396 |
* realm, tracking the given property of a particular bean object |
404 |
* realm, tracking the given property of a particular bean object |
| 397 |
* |
405 |
* |
| 398 |
* @param propertyName |
406 |
* @param propertyName |
| 399 |
* the name of the property |
407 |
* the name of the property. May be nested e.g. "parent.name" |
| 400 |
* @return an observable value factory |
408 |
* @return an observable value factory |
| 401 |
* @since 1.2 |
409 |
* @since 1.2 |
| 402 |
*/ |
410 |
*/ |
|
Lines 417-427
Link Here
|
| 417 |
*/ |
425 |
*/ |
| 418 |
public static IObservableFactory listFactory(final Realm realm, |
426 |
public static IObservableFactory listFactory(final Realm realm, |
| 419 |
final String propertyName, final Class elementType) { |
427 |
final String propertyName, final Class elementType) { |
| 420 |
return new IObservableFactory() { |
428 |
return BeanProperties.list(propertyName, elementType) |
| 421 |
public IObservable createObservable(Object target) { |
429 |
.listFactory(realm); |
| 422 |
return observeList(realm, target, propertyName, elementType); |
|
|
| 423 |
} |
| 424 |
}; |
| 425 |
} |
430 |
} |
| 426 |
|
431 |
|
| 427 |
/** |
432 |
/** |
|
Lines 451-461
Link Here
|
| 451 |
*/ |
456 |
*/ |
| 452 |
public static IObservableFactory setFactory(final Realm realm, |
457 |
public static IObservableFactory setFactory(final Realm realm, |
| 453 |
final String propertyName) { |
458 |
final String propertyName) { |
| 454 |
return new IObservableFactory() { |
459 |
return BeanProperties.set(propertyName).setFactory(realm); |
| 455 |
public IObservable createObservable(Object target) { |
|
|
| 456 |
return observeSet(realm, target, propertyName); |
| 457 |
} |
| 458 |
}; |
| 459 |
} |
460 |
} |
| 460 |
|
461 |
|
| 461 |
/** |
462 |
/** |
|
Lines 479-484
Link Here
|
| 479 |
* @param realm |
480 |
* @param realm |
| 480 |
* @param master |
481 |
* @param master |
| 481 |
* @param propertyName |
482 |
* @param propertyName |
|
|
483 |
* the name of the property. May be nested e.g. "parent.name" |
| 482 |
* @param propertyType |
484 |
* @param propertyType |
| 483 |
* can be <code>null</code> |
485 |
* can be <code>null</code> |
| 484 |
* @return an observable value that tracks the current value of the named |
486 |
* @return an observable value that tracks the current value of the named |
|
Lines 494-504
Link Here
|
| 494 |
warnIfDifferentRealms(realm, master.getRealm()); |
496 |
warnIfDifferentRealms(realm, master.getRealm()); |
| 495 |
|
497 |
|
| 496 |
IObservableValue value = MasterDetailObservables.detailValue(master, |
498 |
IObservableValue value = MasterDetailObservables.detailValue(master, |
| 497 |
valueFactory(realm, propertyName), propertyType); |
499 |
BeanProperties.value(propertyName, propertyType).valueFactory( |
| 498 |
BeanObservableValueDecorator decorator = new BeanObservableValueDecorator( |
500 |
realm), propertyType); |
| 499 |
value, getValueTypePropertyDescriptor(master, propertyName)); |
501 |
return new BeanObservableValueDecorator(value, BeanPropertyHelper |
| 500 |
|
502 |
.getValueTypePropertyDescriptor(master, propertyName)); |
| 501 |
return decorator; |
|
|
| 502 |
} |
503 |
} |
| 503 |
|
504 |
|
| 504 |
/* package */static void warnIfDifferentRealms(Realm detailRealm, |
505 |
/* package */static void warnIfDifferentRealms(Realm detailRealm, |
|
Lines 521-526
Link Here
|
| 521 |
* |
522 |
* |
| 522 |
* @param master |
523 |
* @param master |
| 523 |
* @param propertyName |
524 |
* @param propertyName |
|
|
525 |
* the name of the property. May be nested e.g. "parent.name" |
| 524 |
* @param propertyType |
526 |
* @param propertyType |
| 525 |
* can be <code>null</code> |
527 |
* can be <code>null</code> |
| 526 |
* @return an observable value that tracks the current value of the named |
528 |
* @return an observable value that tracks the current value of the named |
|
Lines 531-547
Link Here
|
| 531 |
*/ |
533 |
*/ |
| 532 |
public static IObservableValue observeDetailValue(IObservableValue master, |
534 |
public static IObservableValue observeDetailValue(IObservableValue master, |
| 533 |
String propertyName, Class propertyType) { |
535 |
String propertyName, Class propertyType) { |
| 534 |
return observeDetailValue(master.getRealm(), master, propertyName, |
536 |
Class beanClass = null; |
| 535 |
propertyType); |
537 |
if (master.getValueType() instanceof Class) |
|
|
538 |
beanClass = (Class) master.getValueType(); |
| 539 |
return observeDetailValue(master, beanClass, propertyName, propertyType); |
| 536 |
} |
540 |
} |
| 537 |
|
541 |
|
| 538 |
/** |
542 |
/** |
| 539 |
* Helper method for |
543 |
* Helper method for |
| 540 |
* <code>MasterDetailObservables.detailValue(master, valueFactory(realm, |
544 |
* <code>MasterDetailObservables.detailValue(master, valueFactory(realm, |
| 541 |
* propertyName), propertyType)</code>. |
545 |
* propertyName), propertyType)</code>. This method returns an |
| 542 |
* This method returns an {@link IBeanObservable} with a |
546 |
* {@link IBeanObservable} with a {@link PropertyDescriptor} based on the |
| 543 |
* {@link PropertyDescriptor} based on the given master type and property |
547 |
* given master type and property name. |
| 544 |
* name. |
|
|
| 545 |
* |
548 |
* |
| 546 |
* @param realm |
549 |
* @param realm |
| 547 |
* the realm |
550 |
* the realm |
|
Lines 551-557
Link Here
|
| 551 |
* @param masterType |
554 |
* @param masterType |
| 552 |
* the type of the master observable value |
555 |
* the type of the master observable value |
| 553 |
* @param propertyName |
556 |
* @param propertyName |
| 554 |
* the property name |
557 |
* the property name. May be nested e.g. "parent.name" |
| 555 |
* @param propertyType |
558 |
* @param propertyType |
| 556 |
* can be <code>null</code> |
559 |
* can be <code>null</code> |
| 557 |
* @return an observable value that tracks the current value of the named |
560 |
* @return an observable value that tracks the current value of the named |
|
Lines 564-578
Link Here
|
| 564 |
* instead. |
567 |
* instead. |
| 565 |
*/ |
568 |
*/ |
| 566 |
public static IObservableValue observeDetailValue(Realm realm, |
569 |
public static IObservableValue observeDetailValue(Realm realm, |
| 567 |
IObservableValue master, Class masterType, String propertyName, Class propertyType) { |
570 |
IObservableValue master, Class masterType, String propertyName, |
|
|
571 |
Class propertyType) { |
| 568 |
warnIfDifferentRealms(realm, master.getRealm()); |
572 |
warnIfDifferentRealms(realm, master.getRealm()); |
| 569 |
Assert.isNotNull(masterType, "masterType cannot be null"); //$NON-NLS-1$ |
573 |
Assert.isNotNull(masterType, "masterType cannot be null"); //$NON-NLS-1$ |
| 570 |
IObservableValue value = MasterDetailObservables.detailValue(master, |
574 |
IObservableValue value = MasterDetailObservables.detailValue(master, |
| 571 |
valueFactory(realm, propertyName), propertyType); |
575 |
BeanProperties.value(masterType, propertyName, propertyType) |
| 572 |
BeanObservableValueDecorator decorator = new BeanObservableValueDecorator( |
576 |
.valueFactory(realm), propertyType); |
| 573 |
value, getPropertyDescriptor(masterType, propertyName)); |
577 |
return new BeanObservableValueDecorator(value, BeanPropertyHelper |
| 574 |
|
578 |
.getPropertyDescriptor(masterType, propertyName)); |
| 575 |
return decorator; |
|
|
| 576 |
} |
579 |
} |
| 577 |
|
580 |
|
| 578 |
/** |
581 |
/** |
|
Lines 588-594
Link Here
|
| 588 |
* @param masterType |
591 |
* @param masterType |
| 589 |
* the type of the master observable value |
592 |
* the type of the master observable value |
| 590 |
* @param propertyName |
593 |
* @param propertyName |
| 591 |
* the property name |
594 |
* the property name. May be nested e.g. "parent.name" |
| 592 |
* @param propertyType |
595 |
* @param propertyType |
| 593 |
* can be <code>null</code> |
596 |
* can be <code>null</code> |
| 594 |
* @return an observable value that tracks the current value of the named |
597 |
* @return an observable value that tracks the current value of the named |
|
Lines 599-606
Link Here
|
| 599 |
*/ |
602 |
*/ |
| 600 |
public static IObservableValue observeDetailValue(IObservableValue master, |
603 |
public static IObservableValue observeDetailValue(IObservableValue master, |
| 601 |
Class masterType, String propertyName, Class propertyType) { |
604 |
Class masterType, String propertyName, Class propertyType) { |
| 602 |
return observeDetailValue(master.getRealm(), master, masterType, |
605 |
return BeanProperties.value(masterType, propertyName, propertyType) |
| 603 |
propertyName, propertyType); |
606 |
.observeDetail(master); |
| 604 |
} |
607 |
} |
| 605 |
|
608 |
|
| 606 |
/** |
609 |
/** |
|
Lines 625-637
Link Here
|
| 625 |
IObservableValue master, String propertyName, Class propertyType) { |
628 |
IObservableValue master, String propertyName, Class propertyType) { |
| 626 |
warnIfDifferentRealms(realm, master.getRealm()); |
629 |
warnIfDifferentRealms(realm, master.getRealm()); |
| 627 |
IObservableList observableList = MasterDetailObservables.detailList( |
630 |
IObservableList observableList = MasterDetailObservables.detailList( |
| 628 |
master, listFactory(realm, propertyName, propertyType), |
631 |
master, BeanProperties.list(propertyName, propertyType) |
| 629 |
propertyType); |
632 |
.listFactory(realm), propertyType); |
| 630 |
BeanObservableListDecorator decorator = new BeanObservableListDecorator( |
633 |
return new BeanObservableListDecorator(observableList, |
| 631 |
observableList, getValueTypePropertyDescriptor(master, |
634 |
BeanPropertyHelper.getValueTypePropertyDescriptor(master, |
| 632 |
propertyName)); |
635 |
propertyName)); |
| 633 |
|
|
|
| 634 |
return decorator; |
| 635 |
} |
636 |
} |
| 636 |
|
637 |
|
| 637 |
/** |
638 |
/** |
|
Lines 650-657
Link Here
|
| 650 |
*/ |
651 |
*/ |
| 651 |
public static IObservableList observeDetailList(IObservableValue master, |
652 |
public static IObservableList observeDetailList(IObservableValue master, |
| 652 |
String propertyName, Class propertyType) { |
653 |
String propertyName, Class propertyType) { |
| 653 |
return observeDetailList(master.getRealm(), master, propertyName, |
654 |
Class beanClass = null; |
| 654 |
propertyType); |
655 |
if (master.getValueType() instanceof Class) |
|
|
656 |
beanClass = (Class) master.getValueType(); |
| 657 |
return BeanProperties.list(beanClass, propertyName, propertyType) |
| 658 |
.observeDetail(master); |
| 655 |
} |
659 |
} |
| 656 |
|
660 |
|
| 657 |
/** |
661 |
/** |
|
Lines 677-689
Link Here
|
| 677 |
warnIfDifferentRealms(realm, master.getRealm()); |
681 |
warnIfDifferentRealms(realm, master.getRealm()); |
| 678 |
|
682 |
|
| 679 |
IObservableSet observableSet = MasterDetailObservables.detailSet( |
683 |
IObservableSet observableSet = MasterDetailObservables.detailSet( |
| 680 |
master, setFactory(realm, propertyName, propertyType), |
684 |
master, BeanProperties.set(propertyName, propertyType) |
| 681 |
propertyType); |
685 |
.setFactory(realm), propertyType); |
| 682 |
BeanObservableSetDecorator decorator = new BeanObservableSetDecorator( |
686 |
return new BeanObservableSetDecorator(observableSet, BeanPropertyHelper |
| 683 |
observableSet, getValueTypePropertyDescriptor(master, |
687 |
.getValueTypePropertyDescriptor(master, propertyName)); |
| 684 |
propertyName)); |
|
|
| 685 |
|
| 686 |
return decorator; |
| 687 |
} |
688 |
} |
| 688 |
|
689 |
|
| 689 |
/** |
690 |
/** |
|
Lines 702-709
Link Here
|
| 702 |
*/ |
703 |
*/ |
| 703 |
public static IObservableSet observeDetailSet(IObservableValue master, |
704 |
public static IObservableSet observeDetailSet(IObservableValue master, |
| 704 |
String propertyName, Class propertyType) { |
705 |
String propertyName, Class propertyType) { |
| 705 |
return observeDetailSet(master.getRealm(), master, propertyName, |
706 |
Class beanClass = null; |
| 706 |
propertyType); |
707 |
if (master.getValueType() instanceof Class) |
|
|
708 |
beanClass = (Class) master.getValueType(); |
| 709 |
return BeanProperties.set(beanClass, propertyName, propertyType) |
| 710 |
.observeDetail(master); |
| 707 |
} |
711 |
} |
| 708 |
|
712 |
|
| 709 |
/** |
713 |
/** |
|
Lines 724-734
Link Here
|
| 724 |
IObservableValue master, String propertyName) { |
728 |
IObservableValue master, String propertyName) { |
| 725 |
warnIfDifferentRealms(realm, master.getRealm()); |
729 |
warnIfDifferentRealms(realm, master.getRealm()); |
| 726 |
IObservableMap observableMap = MasterDetailObservables.detailMap( |
730 |
IObservableMap observableMap = MasterDetailObservables.detailMap( |
| 727 |
master, mapPropertyFactory(realm, propertyName)); |
731 |
master, BeanProperties.map(propertyName).mapFactory(realm)); |
| 728 |
BeanObservableMapDecorator decorator = new BeanObservableMapDecorator( |
732 |
return new BeanObservableMapDecorator(observableMap, BeanPropertyHelper |
| 729 |
observableMap, getValueTypePropertyDescriptor(master, |
733 |
.getValueTypePropertyDescriptor(master, propertyName)); |
| 730 |
propertyName)); |
|
|
| 731 |
return decorator; |
| 732 |
} |
734 |
} |
| 733 |
|
735 |
|
| 734 |
/** |
736 |
/** |
|
Lines 743-749
Link Here
|
| 743 |
*/ |
745 |
*/ |
| 744 |
public static IObservableMap observeDetailMap(IObservableValue master, |
746 |
public static IObservableMap observeDetailMap(IObservableValue master, |
| 745 |
String propertyName) { |
747 |
String propertyName) { |
| 746 |
return observeDetailMap(master.getRealm(), master, propertyName); |
748 |
Class beanClass = null; |
|
|
749 |
if (master.getValueType() instanceof Class) |
| 750 |
beanClass = (Class) master.getValueType(); |
| 751 |
return BeanProperties.map(beanClass, propertyName) |
| 752 |
.observeDetail(master); |
| 747 |
} |
753 |
} |
| 748 |
|
754 |
|
| 749 |
/** |
755 |
/** |
|
Lines 771-782
Link Here
|
| 771 |
*/ |
777 |
*/ |
| 772 |
public static IObservableSet observeSet(Realm realm, Object bean, |
778 |
public static IObservableSet observeSet(Realm realm, Object bean, |
| 773 |
String propertyName, Class elementType) { |
779 |
String propertyName, Class elementType) { |
| 774 |
PropertyDescriptor propertyDescriptor = getPropertyDescriptor(bean |
780 |
return BeanProperties.set(bean.getClass(), propertyName, elementType) |
| 775 |
.getClass(), propertyName); |
781 |
.observe(realm, bean); |
| 776 |
elementType = getCollectionElementType(elementType, propertyDescriptor); |
|
|
| 777 |
|
| 778 |
return new JavaBeanObservableSet(realm, bean, propertyDescriptor, |
| 779 |
elementType); |
| 780 |
} |
782 |
} |
| 781 |
|
783 |
|
| 782 |
/** |
784 |
/** |
|
Lines 824-834
Link Here
|
| 824 |
*/ |
826 |
*/ |
| 825 |
public static IObservableFactory setFactory(final Realm realm, |
827 |
public static IObservableFactory setFactory(final Realm realm, |
| 826 |
final String propertyName, final Class elementType) { |
828 |
final String propertyName, final Class elementType) { |
| 827 |
return new IObservableFactory() { |
829 |
return BeanProperties.set(propertyName, elementType).setFactory(realm); |
| 828 |
public IObservable createObservable(Object target) { |
|
|
| 829 |
return observeSet(realm, target, propertyName, elementType); |
| 830 |
} |
| 831 |
}; |
| 832 |
} |
830 |
} |
| 833 |
|
831 |
|
| 834 |
/** |
832 |
/** |
|
Lines 861-879
Link Here
|
| 861 |
* @param beanClass |
859 |
* @param beanClass |
| 862 |
* the common base type of bean objects that may be in the set |
860 |
* the common base type of bean objects that may be in the set |
| 863 |
* @param propertyName |
861 |
* @param propertyName |
| 864 |
* the name of the property |
862 |
* the name of the property. May be nested e.g. "parent.name" |
| 865 |
* @return a factory for creating {@link IObservableMap} objects |
863 |
* @return a factory for creating {@link IObservableMap} objects |
| 866 |
* |
864 |
* |
| 867 |
* @since 1.1 |
865 |
* @since 1.1 |
| 868 |
*/ |
866 |
*/ |
| 869 |
public static IObservableFactory setToMapFactory(final Class beanClass, final String propertyName) { |
867 |
public static IObservableFactory setToMapFactory(final Class beanClass, |
|
|
868 |
final String propertyName) { |
| 870 |
return new IObservableFactory() { |
869 |
return new IObservableFactory() { |
| 871 |
public IObservable createObservable(Object target) { |
870 |
public IObservable createObservable(Object target) { |
| 872 |
return observeMap((IObservableSet) target, beanClass, propertyName); |
871 |
return observeMap((IObservableSet) target, beanClass, |
|
|
872 |
propertyName); |
| 873 |
} |
873 |
} |
| 874 |
}; |
874 |
}; |
| 875 |
} |
875 |
} |
| 876 |
|
876 |
|
| 877 |
/** |
877 |
/** |
| 878 |
* Returns a factory for creating an observable map. The factory, when |
878 |
* Returns a factory for creating an observable map. The factory, when |
| 879 |
* provided with a bean object, will create an {@link IObservableMap} in the |
879 |
* provided with a bean object, will create an {@link IObservableMap} in the |
|
Lines 890-900
Link Here
|
| 890 |
*/ |
890 |
*/ |
| 891 |
public static IObservableFactory mapPropertyFactory(final Realm realm, |
891 |
public static IObservableFactory mapPropertyFactory(final Realm realm, |
| 892 |
final String propertyName) { |
892 |
final String propertyName) { |
| 893 |
return new IObservableFactory() { |
893 |
return BeanProperties.map(propertyName).mapFactory(realm); |
| 894 |
public IObservable createObservable(Object target) { |
|
|
| 895 |
return observeMap(realm, target, propertyName); |
| 896 |
} |
| 897 |
}; |
| 898 |
} |
894 |
} |
| 899 |
|
895 |
|
| 900 |
/** |
896 |
/** |
|
Lines 911-942
Link Here
|
| 911 |
public static IObservableFactory mapPropertyFactory(String propertyName) { |
907 |
public static IObservableFactory mapPropertyFactory(String propertyName) { |
| 912 |
return mapPropertyFactory(Realm.getDefault(), propertyName); |
908 |
return mapPropertyFactory(Realm.getDefault(), propertyName); |
| 913 |
} |
909 |
} |
| 914 |
|
|
|
| 915 |
/** |
| 916 |
* @param elementType |
| 917 |
* can be <code>null</code> |
| 918 |
* @param propertyDescriptor |
| 919 |
* @return type of the items in a collection/array property |
| 920 |
*/ |
| 921 |
/*package*/ static Class getCollectionElementType(Class elementType, |
| 922 |
PropertyDescriptor propertyDescriptor) { |
| 923 |
if (elementType == null) { |
| 924 |
Class propertyType = propertyDescriptor.getPropertyType(); |
| 925 |
elementType = propertyType.isArray() ? propertyType |
| 926 |
.getComponentType() : Object.class; |
| 927 |
} |
| 928 |
|
| 929 |
return elementType; |
| 930 |
} |
| 931 |
|
| 932 |
/** |
| 933 |
* @param observable |
| 934 |
* @param propertyName |
| 935 |
* @return property descriptor or <code>null</code> |
| 936 |
*/ |
| 937 |
/* package*/ static PropertyDescriptor getValueTypePropertyDescriptor( |
| 938 |
IObservableValue observable, String propertyName) { |
| 939 |
return (observable.getValueType() != null) ? getPropertyDescriptor( |
| 940 |
(Class) observable.getValueType(), propertyName) : null; |
| 941 |
} |
| 942 |
} |
910 |
} |