1 /******************************************************************************* 2 * Copyright (c) 2008, 2016 Matthew Hall and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * Matthew Hall - initial API and implementation (bug 194734) 13 * Matthew Hall - bug 195222, 247997, 261843, 264307 14 * Lars Vogel <Lars.Vogel@vogella.com> - Bug 488364 15 ******************************************************************************/ 16 17 package org.eclipse.core.databinding.beans.typed; 18 19 import java.beans.PropertyDescriptor; 20 import java.util.ArrayList; 21 import java.util.List; 22 23 import org.eclipse.core.databinding.beans.IBeanListProperty; 24 import org.eclipse.core.databinding.beans.IBeanMapProperty; 25 import org.eclipse.core.databinding.beans.IBeanSetProperty; 26 import org.eclipse.core.databinding.beans.IBeanValueProperty; 27 import org.eclipse.core.databinding.property.list.IListProperty; 28 import org.eclipse.core.databinding.property.map.IMapProperty; 29 import org.eclipse.core.databinding.property.set.ISetProperty; 30 import org.eclipse.core.databinding.property.value.IValueProperty; 31 import org.eclipse.core.internal.databinding.beans.AnonymousBeanListProperty; 32 import org.eclipse.core.internal.databinding.beans.AnonymousBeanMapProperty; 33 import org.eclipse.core.internal.databinding.beans.AnonymousBeanSetProperty; 34 import org.eclipse.core.internal.databinding.beans.AnonymousBeanValueProperty; 35 import org.eclipse.core.internal.databinding.beans.BeanListProperty; 36 import org.eclipse.core.internal.databinding.beans.BeanListPropertyDecorator; 37 import org.eclipse.core.internal.databinding.beans.BeanMapProperty; 38 import org.eclipse.core.internal.databinding.beans.BeanMapPropertyDecorator; 39 import org.eclipse.core.internal.databinding.beans.BeanPropertyHelper; 40 import org.eclipse.core.internal.databinding.beans.BeanSetProperty; 41 import org.eclipse.core.internal.databinding.beans.BeanSetPropertyDecorator; 42 import org.eclipse.core.internal.databinding.beans.BeanValueProperty; 43 import org.eclipse.core.internal.databinding.beans.BeanValuePropertyDecorator; 44 45 /** 46 * A factory for creating properties for Java objects that conform to the 47 * <a href="http://java.sun.com/products/javabeans/docs/spec.html">JavaBean 48 * specification</a> for bound properties. 49 * <p> 50 * This class is a new version of the deprecated class with the same name in the 51 * parent package. The difference is that this class returns typed property 52 * objects. This class is located in its own package to be able to coexist with 53 * the old version while having the same name. 54 * 55 * @since 1.5 56 */ 57 public class BeanProperties { 58 /** 59 * Returns a value property for the given property name of an arbitrary bean 60 * class. Objects lacking the named property are treated the same as if the 61 * property always contains null. 62 * 63 * @param propertyName 64 * the property name. May be nested e.g. "parent.name" 65 * @return a value property for the given property name of an arbitrary bean 66 * class. 67 */ value(String propertyName)68 public static <S, T> IBeanValueProperty<S, T> value(String propertyName) { 69 return value(null, propertyName, null); 70 } 71 72 /** 73 * Returns a value property for the given property name of an arbitrary bean 74 * class. Objects lacking the named property are treated the same as if the 75 * property always contains null. 76 * 77 * @param propertyName 78 * the property name. May be nested e.g. "parent.name" 79 * @param valueType 80 * the value type of the returned value property 81 * @return a value property for the given property name of an arbitrary bean 82 * class. 83 */ value(String propertyName, Class<T> valueType)84 public static <S, T> IBeanValueProperty<S, T> value(String propertyName, Class<T> valueType) { 85 return value(null, propertyName, valueType); 86 } 87 88 /** 89 * Returns a value property for the given property name of the given bean 90 * class. 91 * 92 * @param beanClass 93 * the bean class 94 * @param propertyName 95 * the property name. May be nested e.g. "parent.name" 96 * @return a value property for the given property name of the given bean 97 * class. 98 */ value(Class<S> beanClass, String propertyName)99 public static <S, T> IBeanValueProperty<S, T> value(Class<S> beanClass, String propertyName) { 100 return value(beanClass, propertyName, null); 101 } 102 103 /** 104 * Returns a value property for the given property name of the given bean 105 * class. 106 * 107 * @param beanClass 108 * the bean class 109 * @param propertyName 110 * the property name. May be nested e.g. "parent.name" 111 * @param valueType 112 * the value type of the returned value property 113 * @return a value property for the given property name of the given bean 114 * class. 115 */ 116 @SuppressWarnings("unchecked") value(Class<S> beanClass, String propertyName, Class<T> valueType)117 public static <S, T> IBeanValueProperty<S, T> value(Class<S> beanClass, String propertyName, Class<T> valueType) { 118 String[] propertyNames = split(propertyName); 119 if (propertyNames.length > 1) 120 valueType = null; 121 122 PropertyDescriptor propertyDescriptor; 123 IValueProperty<S, T> property; 124 if (beanClass == null) { 125 propertyDescriptor = null; 126 property = new AnonymousBeanValueProperty<>(propertyNames[0], valueType); 127 } else { 128 propertyDescriptor = BeanPropertyHelper.getPropertyDescriptor(beanClass, propertyNames[0]); 129 property = new BeanValueProperty<>(propertyDescriptor, valueType); 130 } 131 132 IBeanValueProperty<S, T> beanProperty = new BeanValuePropertyDecorator<>(property, propertyDescriptor); 133 for (int i = 1; i < propertyNames.length; i++) { 134 beanProperty = (IBeanValueProperty<S, T>) beanProperty.value(propertyNames[i]); 135 } 136 return beanProperty; 137 } 138 split(String propertyName)139 private static String[] split(String propertyName) { 140 if (propertyName.indexOf('.') == -1) 141 return new String[] { propertyName }; 142 List<String> propertyNames = new ArrayList<>(); 143 int index; 144 while ((index = propertyName.indexOf('.')) != -1) { 145 propertyNames.add(propertyName.substring(0, index)); 146 propertyName = propertyName.substring(index + 1); 147 } 148 propertyNames.add(propertyName); 149 return propertyNames.toArray(new String[propertyNames.size()]); 150 } 151 152 /** 153 * Returns a value property array for the given property names of the given 154 * bean class. 155 * 156 * @param beanClass 157 * the bean class 158 * @param propertyNames 159 * defines the property names. May be nested e.g. "parent.name" 160 * @return a value property array for the given property names of the given 161 * bean class. 162 */ values(Class<S> beanClass, String... propertyNames)163 public static <S, T> IBeanValueProperty<S, T>[] values(Class<S> beanClass, String... propertyNames) { 164 @SuppressWarnings("unchecked") 165 IBeanValueProperty<S, T>[] properties = new IBeanValueProperty[propertyNames.length]; 166 for (int i = 0; i < properties.length; i++) 167 properties[i] = value(beanClass, propertyNames[i], null); 168 return properties; 169 } 170 171 /** 172 * Returns a value property array for the given property names of an 173 * arbitrary bean class. 174 * 175 * @param propertyNames 176 * defines the property names. May be nested e.g. "parent.name" 177 * @return a value property array for the given property names of the given 178 * bean class. 179 */ values(String... propertyNames)180 public static <S, T> IBeanValueProperty<S, T>[] values(String... propertyNames) { 181 return values(null, propertyNames); 182 } 183 184 /** 185 * Returns a set property for the given property name of an arbitrary bean 186 * class. Objects lacking the named property are treated the same as if the 187 * property always contains an empty set. 188 * 189 * @param propertyName 190 * the property name 191 * @return a set property for the given property name of an arbitrary bean 192 * class. 193 */ set(String propertyName)194 public static <S, E> IBeanSetProperty<S, E> set(String propertyName) { 195 return set(null, propertyName, null); 196 } 197 198 /** 199 * Returns a set property for the given property name of an arbitrary bean 200 * class. Objects lacking the named property are treated the same as if the 201 * property always contains an empty set. 202 * 203 * @param propertyName 204 * the property name 205 * @param elementType 206 * the element type of the returned set property 207 * @return a set property for the given property name of an arbitrary bean 208 * class. 209 */ set(String propertyName, Class<E> elementType)210 public static <S, E> IBeanSetProperty<S, E> set(String propertyName, Class<E> elementType) { 211 return set(null, propertyName, elementType); 212 } 213 214 /** 215 * Returns a set property for the given property name of the given bean 216 * class. 217 * 218 * @param beanClass 219 * the bean class 220 * @param propertyName 221 * the property name 222 * @return a set property for the given property name of the given bean 223 * class. 224 */ set(Class<S> beanClass, String propertyName)225 public static <S, E> IBeanSetProperty<S, E> set(Class<S> beanClass, String propertyName) { 226 return set(beanClass, propertyName, null); 227 } 228 229 /** 230 * Returns a set property for the given property name of the given bean 231 * class. 232 * 233 * @param beanClass 234 * the bean class 235 * @param propertyName 236 * the property name 237 * @param elementType 238 * the element type of the returned set property 239 * @return a set property for the given property name of the given bean 240 * class. 241 */ set(Class<S> beanClass, String propertyName, Class<E> elementType)242 public static <S, E> IBeanSetProperty<S, E> set(Class<S> beanClass, String propertyName, Class<E> elementType) { 243 PropertyDescriptor propertyDescriptor; 244 ISetProperty<S, E> property; 245 if (beanClass == null) { 246 propertyDescriptor = null; 247 property = new AnonymousBeanSetProperty<>(propertyName, elementType); 248 } else { 249 propertyDescriptor = BeanPropertyHelper.getPropertyDescriptor( 250 beanClass, propertyName); 251 property = new BeanSetProperty<>(propertyDescriptor, elementType); 252 } 253 return new BeanSetPropertyDecorator<>(property, propertyDescriptor); 254 } 255 256 /** 257 * Returns a list property for the given property name of an arbitrary bean 258 * class. Objects lacking the named property are treated the same as if the 259 * property always contains an empty list. 260 * 261 * @param propertyName 262 * the property name 263 * @return a list property for the given property name of an arbitrary bean 264 * class. 265 */ list(String propertyName)266 public static <S, E> IBeanListProperty<S, E> list(String propertyName) { 267 return list(null, propertyName, null); 268 } 269 270 /** 271 * Returns a list property for the given property name of an arbitrary bean 272 * class. Objects lacking the named property are treated the same as if the 273 * property always contains an empty list. 274 * 275 * @param propertyName 276 * the property name 277 * @param elementType 278 * the element type of the returned list property 279 * @return a list property for the given property name of the given bean 280 * class. 281 */ list(String propertyName, Class<E> elementType)282 public static <S, E> IBeanListProperty<S, E> list(String propertyName, Class<E> elementType) { 283 return list(null, propertyName, elementType); 284 } 285 286 /** 287 * Returns a list property for the given property name of the given bean 288 * class. 289 * 290 * @param beanClass 291 * the bean class 292 * @param propertyName 293 * the property name 294 * @return a list property for the given property name of the given bean 295 * class. 296 */ list(Class<S> beanClass, String propertyName)297 public static <S, E> IBeanListProperty<S, E> list(Class<S> beanClass, String propertyName) { 298 return list(beanClass, propertyName, null); 299 } 300 301 /** 302 * Returns a list property for the given property name of the given bean 303 * class. 304 * 305 * @param beanClass 306 * the bean class 307 * @param propertyName 308 * the property name 309 * @param elementType 310 * the element type of the returned list property 311 * @return a list property for the given property name of the given bean 312 * class. 313 */ list(Class<S> beanClass, String propertyName, Class<E> elementType)314 public static <S, E> IBeanListProperty<S, E> list(Class<S> beanClass, String propertyName, Class<E> elementType) { 315 PropertyDescriptor propertyDescriptor; 316 IListProperty<S, E> property; 317 if (beanClass == null) { 318 propertyDescriptor = null; 319 property = new AnonymousBeanListProperty<>(propertyName, elementType); 320 } else { 321 propertyDescriptor = BeanPropertyHelper.getPropertyDescriptor( 322 beanClass, propertyName); 323 property = new BeanListProperty<>(propertyDescriptor, elementType); 324 } 325 return new BeanListPropertyDecorator<>(property, propertyDescriptor); 326 } 327 328 /** 329 * Returns a map property for the given property name of an arbitrary bean 330 * class. Objects lacking the named property are treated the same as if the 331 * property always contains an empty map. 332 * 333 * @param propertyName 334 * the property name 335 * @return a map property for the given property name of an arbitrary bean 336 * class. 337 */ map(String propertyName)338 public static <S, K, V> IBeanMapProperty<S, K, V> map(String propertyName) { 339 return map(null, propertyName, null, null); 340 } 341 342 /** 343 * Returns a map property for the given property name of an arbitrary bean 344 * class. Objects lacking the named property are treated the same as if the 345 * property always contains an empty map. 346 * 347 * @param propertyName 348 * the property name 349 * @param keyType 350 * the key type for the returned map property 351 * @param valueType 352 * the value type for the returned map property 353 * @return a map property for the given property name of an arbitrary bean 354 * class. 355 */ map(String propertyName, Class<K> keyType, Class<V> valueType)356 public static <S, K, V> IBeanMapProperty<S, K, V> map(String propertyName, Class<K> keyType, Class<V> valueType) { 357 return map(null, propertyName, keyType, valueType); 358 } 359 360 /** 361 * Returns a map property for the given property name of the given bean 362 * class. 363 * 364 * @param beanClass 365 * the bean class 366 * @param propertyName 367 * the property name 368 * @return a map property for the given property name of the given bean 369 * class. 370 */ map(Class<S> beanClass, String propertyName)371 public static <S, K, V> IBeanMapProperty<S, K, V> map(Class<S> beanClass, String propertyName) { 372 return map(beanClass, propertyName, null, null); 373 } 374 375 /** 376 * Returns a map property for the given property name of the given bean 377 * class. 378 * 379 * @param beanClass 380 * the bean class 381 * @param propertyName 382 * the property name 383 * @param keyType 384 * the key type for the returned map property 385 * @param valueType 386 * the value type for the returned map property 387 * @return a map property for the given property name of the given bean 388 * class. 389 */ map(Class<S> beanClass, String propertyName, Class<K> keyType, Class<V> valueType)390 public static <S, K, V> IBeanMapProperty<S, K, V> map(Class<S> beanClass, String propertyName, Class<K> keyType, 391 Class<V> valueType) { 392 PropertyDescriptor propertyDescriptor; 393 IMapProperty<S, K, V> property; 394 if (beanClass == null) { 395 propertyDescriptor = null; 396 property = new AnonymousBeanMapProperty<>(propertyName, keyType, valueType); 397 } else { 398 propertyDescriptor = BeanPropertyHelper.getPropertyDescriptor(beanClass, propertyName); 399 property = new BeanMapProperty<>(propertyDescriptor, keyType, valueType); 400 } 401 return new BeanMapPropertyDecorator<>(property, propertyDescriptor); 402 } 403 } 404