You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

BeanItemContainer.java 8.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. /*
  2. * Copyright 2000-2014 Vaadin Ltd.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5. * use this file except in compliance with the License. You may obtain a copy of
  6. * the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. * License for the specific language governing permissions and limitations under
  14. * the License.
  15. */
  16. package com.vaadin.data.util;
  17. import java.util.Collection;
  18. /**
  19. * An in-memory container for JavaBeans.
  20. *
  21. * <p>
  22. * The properties of the container are determined automatically by introspecting
  23. * the used JavaBean class. Only beans of the same type can be added to the
  24. * container.
  25. * </p>
  26. *
  27. * <p>
  28. * BeanItemContainer uses the beans themselves as identifiers. The
  29. * {@link Object#hashCode()} of a bean is used when storing and looking up beans
  30. * so it must not change during the lifetime of the bean (it should not depend
  31. * on any part of the bean that can be modified). Typically this restricts the
  32. * implementation of {@link Object#equals(Object)} as well in order for it to
  33. * fulfill the contract between {@code equals()} and {@code hashCode()}.
  34. * </p>
  35. *
  36. * <p>
  37. * To add items to the container, use the methods {@link #addBean(Object)},
  38. * {@link #addBeanAfter(Object, Object)} and {@link #addBeanAt(int, Object)}.
  39. * Also {@link #addItem(Object)}, {@link #addItemAfter(Object, Object)} and
  40. * {@link #addItemAt(int, Object)} can be used as synonyms for them.
  41. * </p>
  42. *
  43. * <p>
  44. * It is not possible to add additional properties to the container.
  45. * </p>
  46. *
  47. * @param <BEANTYPE>
  48. * The type of the Bean
  49. *
  50. * @since 5.4
  51. */
  52. @SuppressWarnings("serial")
  53. public class BeanItemContainer<BEANTYPE> extends
  54. AbstractBeanContainer<BEANTYPE, BEANTYPE> {
  55. /**
  56. * Bean identity resolver that returns the bean itself as its item
  57. * identifier.
  58. *
  59. * This corresponds to the old behavior of {@link BeanItemContainer}, and
  60. * requires suitable (identity-based) equals() and hashCode() methods on the
  61. * beans.
  62. *
  63. * @param <BT>
  64. *
  65. * @since 6.5
  66. */
  67. private static class IdentityBeanIdResolver<BT> implements
  68. BeanIdResolver<BT, BT> {
  69. @Override
  70. public BT getIdForBean(BT bean) {
  71. return bean;
  72. }
  73. }
  74. /**
  75. * Constructs a {@code BeanItemContainer} for beans of the given type.
  76. *
  77. * @param type
  78. * the type of the beans that will be added to the container.
  79. * @throws IllegalArgumentException
  80. * If {@code type} is null
  81. */
  82. public BeanItemContainer(Class<? super BEANTYPE> type)
  83. throws IllegalArgumentException {
  84. super(type);
  85. super.setBeanIdResolver(new IdentityBeanIdResolver<BEANTYPE>());
  86. }
  87. /**
  88. * Constructs a {@code BeanItemContainer} and adds the given beans to it.
  89. * The collection must not be empty.
  90. * {@link BeanItemContainer#BeanItemContainer(Class)} can be used for
  91. * creating an initially empty {@code BeanItemContainer}.
  92. *
  93. * Note that when using this constructor, the actual class of the first item
  94. * in the collection is used to determine the bean properties supported by
  95. * the container instance, and only beans of that class or its subclasses
  96. * can be added to the collection. If this is problematic or empty
  97. * collections need to be supported, use {@link #BeanItemContainer(Class)}
  98. * and {@link #addAll(Collection)} instead.
  99. *
  100. * @param collection
  101. * a non empty {@link Collection} of beans.
  102. * @throws IllegalArgumentException
  103. * If the collection is null or empty.
  104. *
  105. * @deprecated As of 6.5, use {@link #BeanItemContainer(Class, Collection)}
  106. * instead
  107. */
  108. @SuppressWarnings("unchecked")
  109. @Deprecated
  110. public BeanItemContainer(Collection<? extends BEANTYPE> collection)
  111. throws IllegalArgumentException {
  112. // must assume the class is BT
  113. // the class information is erased by the compiler
  114. this((Class<BEANTYPE>) getBeanClassForCollection(collection),
  115. collection);
  116. }
  117. /**
  118. * Internal helper method to support the deprecated {@link Collection}
  119. * container.
  120. *
  121. * @param <BT>
  122. * @param collection
  123. * @return
  124. * @throws IllegalArgumentException
  125. */
  126. @SuppressWarnings("unchecked")
  127. @Deprecated
  128. private static <BT> Class<? extends BT> getBeanClassForCollection(
  129. Collection<? extends BT> collection)
  130. throws IllegalArgumentException {
  131. if (collection == null || collection.isEmpty()) {
  132. throw new IllegalArgumentException(
  133. "The collection passed to BeanItemContainer constructor must not be null or empty. Use the other BeanItemContainer constructor.");
  134. }
  135. return (Class<? extends BT>) collection.iterator().next().getClass();
  136. }
  137. /**
  138. * Constructs a {@code BeanItemContainer} and adds the given beans to it.
  139. *
  140. * @param type
  141. * the type of the beans that will be added to the container.
  142. * @param collection
  143. * a {@link Collection} of beans (can be empty or null).
  144. * @throws IllegalArgumentException
  145. * If {@code type} is null
  146. */
  147. public BeanItemContainer(Class<? super BEANTYPE> type,
  148. Collection<? extends BEANTYPE> collection)
  149. throws IllegalArgumentException {
  150. super(type);
  151. super.setBeanIdResolver(new IdentityBeanIdResolver<BEANTYPE>());
  152. if (collection != null) {
  153. addAll(collection);
  154. }
  155. }
  156. /**
  157. * Adds all the beans from a {@link Collection} in one go. More efficient
  158. * than adding them one by one.
  159. *
  160. * @param collection
  161. * The collection of beans to add. Must not be null.
  162. */
  163. @Override
  164. public void addAll(Collection<? extends BEANTYPE> collection) {
  165. super.addAll(collection);
  166. }
  167. /**
  168. * Adds the bean after the given bean.
  169. *
  170. * The bean is used both as the item contents and as the item identifier.
  171. *
  172. * @param previousItemId
  173. * the bean (of type BT) after which to add newItemId
  174. * @param newItemId
  175. * the bean (of type BT) to add (not null)
  176. *
  177. * @see com.vaadin.data.Container.Ordered#addItemAfter(Object, Object)
  178. */
  179. @Override
  180. @SuppressWarnings("unchecked")
  181. public BeanItem<BEANTYPE> addItemAfter(Object previousItemId,
  182. Object newItemId) throws IllegalArgumentException {
  183. return super.addBeanAfter((BEANTYPE) previousItemId,
  184. (BEANTYPE) newItemId);
  185. }
  186. /**
  187. * Adds a new bean at the given index.
  188. *
  189. * The bean is used both as the item contents and as the item identifier.
  190. *
  191. * @param index
  192. * Index at which the bean should be added.
  193. * @param newItemId
  194. * The bean to add to the container.
  195. * @return Returns the new BeanItem or null if the operation fails.
  196. */
  197. @Override
  198. @SuppressWarnings("unchecked")
  199. public BeanItem<BEANTYPE> addItemAt(int index, Object newItemId)
  200. throws IllegalArgumentException {
  201. return super.addBeanAt(index, (BEANTYPE) newItemId);
  202. }
  203. /**
  204. * Adds the bean to the Container.
  205. *
  206. * The bean is used both as the item contents and as the item identifier.
  207. *
  208. * @see com.vaadin.data.Container#addItem(Object)
  209. */
  210. @Override
  211. @SuppressWarnings("unchecked")
  212. public BeanItem<BEANTYPE> addItem(Object itemId) {
  213. return super.addBean((BEANTYPE) itemId);
  214. }
  215. /**
  216. * Adds the bean to the Container.
  217. *
  218. * The bean is used both as the item contents and as the item identifier.
  219. *
  220. * @see com.vaadin.data.Container#addItem(Object)
  221. */
  222. @Override
  223. public BeanItem<BEANTYPE> addBean(BEANTYPE bean) {
  224. return addItem(bean);
  225. }
  226. /**
  227. * Unsupported in BeanItemContainer.
  228. */
  229. @Override
  230. protected void setBeanIdResolver(
  231. AbstractBeanContainer.BeanIdResolver<BEANTYPE, BEANTYPE> beanIdResolver)
  232. throws UnsupportedOperationException {
  233. throw new UnsupportedOperationException(
  234. "BeanItemContainer always uses an IdentityBeanIdResolver");
  235. }
  236. }