Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

BeanItem.java 7.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. /*
  2. @VaadinApache2LicenseForJavaFiles@
  3. */
  4. package com.vaadin.data.util;
  5. import java.beans.BeanInfo;
  6. import java.beans.IntrospectionException;
  7. import java.beans.Introspector;
  8. import java.beans.PropertyDescriptor;
  9. import java.lang.reflect.Method;
  10. import java.util.ArrayList;
  11. import java.util.Arrays;
  12. import java.util.Collection;
  13. import java.util.LinkedHashMap;
  14. import java.util.List;
  15. import java.util.Map;
  16. /**
  17. * A wrapper class for adding the Item interface to any Java Bean.
  18. *
  19. * @author Vaadin Ltd.
  20. * @version
  21. * @VERSION@
  22. * @since 3.0
  23. */
  24. @SuppressWarnings("serial")
  25. public class BeanItem<BT> extends PropertysetItem {
  26. /**
  27. * The bean which this Item is based on.
  28. */
  29. private final BT bean;
  30. /**
  31. * <p>
  32. * Creates a new instance of <code>BeanItem</code> and adds all properties
  33. * of a Java Bean to it. The properties are identified by their respective
  34. * bean names.
  35. * </p>
  36. *
  37. * <p>
  38. * Note : This version only supports introspectable bean properties and
  39. * their getter and setter methods. Stand-alone <code>is</code> and
  40. * <code>are</code> methods are not supported.
  41. * </p>
  42. *
  43. * @param bean
  44. * the Java Bean to copy properties from.
  45. *
  46. */
  47. public BeanItem(BT bean) {
  48. this(bean, getPropertyDescriptors((Class<BT>) bean.getClass()));
  49. }
  50. /**
  51. * <p>
  52. * Creates a new instance of <code>BeanItem</code> using a pre-computed set
  53. * of properties. The properties are identified by their respective bean
  54. * names.
  55. * </p>
  56. *
  57. * @param bean
  58. * the Java Bean to copy properties from.
  59. * @param propertyDescriptors
  60. * pre-computed property descriptors
  61. */
  62. BeanItem(BT bean,
  63. Map<String, VaadinPropertyDescriptor<BT>> propertyDescriptors) {
  64. this.bean = bean;
  65. for (VaadinPropertyDescriptor<BT> pd : propertyDescriptors.values()) {
  66. addItemProperty(pd.getName(), pd.createProperty(bean));
  67. }
  68. }
  69. /**
  70. * <p>
  71. * Creates a new instance of <code>BeanItem</code> and adds all listed
  72. * properties of a Java Bean to it - in specified order. The properties are
  73. * identified by their respective bean names.
  74. * </p>
  75. *
  76. * <p>
  77. * Note : This version only supports introspectable bean properties and
  78. * their getter and setter methods. Stand-alone <code>is</code> and
  79. * <code>are</code> methods are not supported.
  80. * </p>
  81. *
  82. * @param bean
  83. * the Java Bean to copy properties from.
  84. * @param propertyIds
  85. * id of the property.
  86. */
  87. public BeanItem(BT bean, Collection<?> propertyIds) {
  88. this.bean = bean;
  89. // Create bean information
  90. LinkedHashMap<String, VaadinPropertyDescriptor<BT>> pds = getPropertyDescriptors((Class<BT>) bean
  91. .getClass());
  92. // Add all the bean properties as MethodProperties to this Item
  93. for (Object id : propertyIds) {
  94. VaadinPropertyDescriptor<BT> pd = pds.get(id);
  95. if (pd != null) {
  96. addItemProperty(pd.getName(), pd.createProperty(bean));
  97. }
  98. }
  99. }
  100. /**
  101. * <p>
  102. * Creates a new instance of <code>BeanItem</code> and adds all listed
  103. * properties of a Java Bean to it - in specified order. The properties are
  104. * identified by their respective bean names.
  105. * </p>
  106. *
  107. * <p>
  108. * Note : This version only supports introspectable bean properties and
  109. * their getter and setter methods. Stand-alone <code>is</code> and
  110. * <code>are</code> methods are not supported.
  111. * </p>
  112. *
  113. * @param bean
  114. * the Java Bean to copy properties from.
  115. * @param propertyIds
  116. * ids of the properties.
  117. */
  118. public BeanItem(BT bean, String[] propertyIds) {
  119. this(bean, Arrays.asList(propertyIds));
  120. }
  121. /**
  122. * <p>
  123. * Perform introspection on a Java Bean class to find its properties.
  124. * </p>
  125. *
  126. * <p>
  127. * Note : This version only supports introspectable bean properties and
  128. * their getter and setter methods. Stand-alone <code>is</code> and
  129. * <code>are</code> methods are not supported.
  130. * </p>
  131. *
  132. * @param beanClass
  133. * the Java Bean class to get properties for.
  134. * @return an ordered map from property names to property descriptors
  135. */
  136. static <BT> LinkedHashMap<String, VaadinPropertyDescriptor<BT>> getPropertyDescriptors(
  137. final Class<BT> beanClass) {
  138. final LinkedHashMap<String, VaadinPropertyDescriptor<BT>> pdMap = new LinkedHashMap<String, VaadinPropertyDescriptor<BT>>();
  139. // Try to introspect, if it fails, we just have an empty Item
  140. try {
  141. List<PropertyDescriptor> propertyDescriptors = getBeanPropertyDescriptor(beanClass);
  142. // Add all the bean properties as MethodProperties to this Item
  143. // later entries on the list overwrite earlier ones
  144. for (PropertyDescriptor pd : propertyDescriptors) {
  145. final Method getMethod = pd.getReadMethod();
  146. if ((getMethod != null)
  147. && getMethod.getDeclaringClass() != Object.class) {
  148. VaadinPropertyDescriptor<BT> vaadinPropertyDescriptor = new MethodPropertyDescriptor(
  149. pd.getName(), pd.getPropertyType(),
  150. pd.getReadMethod(), pd.getWriteMethod());
  151. pdMap.put(pd.getName(), vaadinPropertyDescriptor);
  152. }
  153. }
  154. } catch (final java.beans.IntrospectionException ignored) {
  155. }
  156. return pdMap;
  157. }
  158. /**
  159. * Returns the property descriptors of a class or an interface.
  160. *
  161. * For an interface, superinterfaces are also iterated as Introspector does
  162. * not take them into account (Oracle Java bug 4275879), but in that case,
  163. * both the setter and the getter for a property must be in the same
  164. * interface and should not be overridden in subinterfaces for the discovery
  165. * to work correctly.
  166. *
  167. * For interfaces, the iteration is depth first and the properties of
  168. * superinterfaces are returned before those of their subinterfaces.
  169. *
  170. * @param beanClass
  171. * @return
  172. * @throws IntrospectionException
  173. */
  174. private static List<PropertyDescriptor> getBeanPropertyDescriptor(
  175. final Class<?> beanClass) throws IntrospectionException {
  176. // Oracle bug 4275879: Introspector does not consider superinterfaces of
  177. // an interface
  178. if (beanClass.isInterface()) {
  179. List<PropertyDescriptor> propertyDescriptors = new ArrayList<PropertyDescriptor>();
  180. for (Class<?> cls : beanClass.getInterfaces()) {
  181. propertyDescriptors.addAll(getBeanPropertyDescriptor(cls));
  182. }
  183. BeanInfo info = Introspector.getBeanInfo(beanClass);
  184. propertyDescriptors.addAll(Arrays.asList(info
  185. .getPropertyDescriptors()));
  186. return propertyDescriptors;
  187. } else {
  188. BeanInfo info = Introspector.getBeanInfo(beanClass);
  189. return Arrays.asList(info.getPropertyDescriptors());
  190. }
  191. }
  192. /**
  193. * Gets the underlying JavaBean object.
  194. *
  195. * @return the bean object.
  196. */
  197. public BT getBean() {
  198. return bean;
  199. }
  200. }