Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

datamodel-container.asciidoc 31KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834
  1. ---
  2. title: Collecting Items in Containers
  3. order: 5
  4. layout: page
  5. ---
  6. [[datamodel.container]]
  7. = Collecting Items in Containers
  8. ((("[classname]#Container#", id="term.datamodel.container", range="startofrange")))
  9. The [classname]#Container# interface is the highest containment level of the
  10. Vaadin data model, for containing items (rows) which in turn contain properties
  11. (columns). Containers can therefore represent tabular data, which can be viewed
  12. in a [classname]#Table# or some other selection component, as well as
  13. hierarchical data.
  14. The items contained in a container are identified by an __item identifier__ or
  15. __IID__, and the properties by a __property identifier__ or __PID__.
  16. [[datamodel.container.intro]]
  17. == Basic Use of Containers
  18. The basic use of containers involves creating one, adding items to it, and
  19. binding it as a container data source of a component.
  20. [[datamodel.container.intro.default]]
  21. === Default Containers and Delegation
  22. Before saying anything about creation of containers, it should be noted that all
  23. components that can be bound to a container data source are by default bound to
  24. a default container. For example, [classname]#Table# is bound to a
  25. [classname]#IndexedContainer#, [classname]#Tree# to a
  26. [classname]#HierarchicalContainer#, and so forth.
  27. All of the user interface components using containers also implement the
  28. relevant container interfaces themselves, so that the access to the underlying
  29. data source is delegated through the component.
  30. ----
  31. // Create a table with one column
  32. Table table = new Table("My Table");
  33. table.addContainerProperty("col1", String.class, null);
  34. // Access items and properties through the component
  35. table.addItem("row1"); // Create item by explicit ID
  36. Item item1 = table.getItem("row1");
  37. Property property1 = item1.getItemProperty("col1");
  38. property1.setValue("some given value");
  39. // Equivalent access through the container
  40. Container container = table.getContainerDataSource();
  41. container.addItem("row2");
  42. Item item2 = container.getItem("row2");
  43. Property property2 = item2.getItemProperty("col1");
  44. property2.setValue("another given value");
  45. ----
  46. [[datamodel.container.intro.creating]]
  47. === Creating and Binding a Container
  48. A container is created and bound to a component as follows:
  49. ----
  50. // Create a container of some type
  51. Container container = new IndexedContainer();
  52. // Initialize the container as required by the container type
  53. container.addContainerProperty("name", String.class, "none");
  54. container.addContainerProperty("volume", Double.class, 0.0);
  55. ... add items ...
  56. // Bind it to a component
  57. Table table = new Table("My Table");
  58. table.setContainerDataSource(container);
  59. ----
  60. Most components that can be bound to a container allow passing it also in the
  61. constructor, in addition to using [methodname]#setContainerDataSource()#.
  62. Creation of the container depends on its type. For some containers, such as the
  63. [classname]#IndexedContainer#, you need to define the contained properties
  64. (columns) as was done above, while some others determine them otherwise. The
  65. definition of a property with [methodname]#addContainerProperty()# requires a
  66. unique property ID, type, and a default value. You can also give
  67. [parameter]#null#.
  68. Vaadin has a several built-in in-memory container implementations, such as
  69. [classname]#IndexedContainer# and [classname]#BeanItemContainer#, which are easy
  70. to use for setting up nonpersistent data storages. For persistent data, either
  71. the built-in [classname]#SQLContainer# or the [classname]#JPAContainer# add-on
  72. container can be used.
  73. [[datamodel.container.intro.adding]]
  74. === Adding Items and Accessing Properties
  75. Items can be added to a container with the [methodname]#addItem()# method. The
  76. parameterless version of the method automatically generates the item ID.
  77. ----
  78. // Create an item
  79. Object itemId = container.addItem();
  80. ----
  81. Properties can be requested from container by first requesting an item with
  82. [methodname]#getItem()# and then getting the properties from the item with
  83. [methodname]#getItemProperty()#.
  84. ----
  85. // Get the item object
  86. Item item = container.getItem(itemId);
  87. // Access a property in the item
  88. Property<String> nameProperty =
  89. item.getItemProperty("name");
  90. // Do something with the property
  91. nameProperty.setValue("box");
  92. ----
  93. You can also get a property directly by the item and property ids with
  94. [methodname]#getContainerProperty()#.
  95. ----
  96. container.getContainerProperty(itemId, "volume").setValue(5.0);
  97. ----
  98. [[datamodel.container.intro.givenid]]
  99. === Adding Items by Given ID
  100. Some containers, such as [classname]#IndexedContainer# and
  101. [classname]#HierarchicalContainer#, allow adding items by a given ID, which can
  102. be any [classname]#Object#.
  103. ----
  104. Item item = container.addItem("agivenid");
  105. item.getItemProperty("name").setValue("barrel");
  106. Item.getItemProperty("volume").setValue(119.2);
  107. ----
  108. Notice that the actual item __is not__ given as a parameter to the method, only
  109. its ID, as the interface assumes that the container itself creates all the items
  110. it contains. Some container implementations can provide methods to add
  111. externally created items, and they can even assume that the item ID object is
  112. also the item itself. Lazy containers might not create the item immediately, but
  113. lazily when it is accessed by its ID.
  114. [[datamodel.container.inner]]
  115. == Container Subinterfaces
  116. The [classname]#Container# interface contains inner interfaces that container
  117. implementations can implement to fulfill different features required by
  118. components that present container data.
  119. [interfacename]#Container.Filterable#:: Filterable containers allow filtering the contained items by filters, as
  120. described in <<datamodel.container.filtered>>.
  121. [interfacename]#Container.Hierarchical#:: Hierarchical containers allow representing hierarchical relationships between
  122. items and are required by the [classname]#Tree# and [classname]#TreeTable#
  123. components. The [classname]#HierarchicalContainer# is a built-in in-memory
  124. container for hierarchical data, and is used as the default container for the
  125. tree components. The [classname]#FilesystemContainer# provides access to
  126. browsing the content of a file system. Also [classname]#JPAContainer# is
  127. hierarchical, as described in
  128. <<dummy/../../../framework/jpacontainer/jpacontainer-usage#jpacontainer.usage.hierarchical,"Hierarchical
  129. Container">>.
  130. [interfacename]#Container.Indexed#:: An indexed container allows accessing items by an index number, not just their
  131. item ID. This feature is required by some components, especially
  132. [classname]#Table#, which needs to provide lazy access to large containers. The
  133. [classname]#IndexedContainer# is a basic in-memory implementation, as described
  134. in <<datamodel.container.indexedcontainer>>.
  135. [interfacename]#Container.Ordered#:: An ordered container allows traversing the items in successive order in either
  136. direction. Most built-in containers are ordered.
  137. [interfacename]#Container.SimpleFilterable#:: This interface enables filtering a container by string matching with
  138. [methodname]#addContainerFilter()#. The filtering is done by either searching
  139. the given string anywhere in a property value, or as its prefix.
  140. [interfacename]#Container.Sortable#:: A sortable container is required by some components that allow sorting the
  141. content, such as [classname]#Table#, where the user can click a column header to
  142. sort the table by the column. Some other components, such as
  143. [classname]#Calendar#, may require that the content is sorted to be able to
  144. display it properly. Depending on the implementation, sorting can be done only
  145. when the [methodname]#sort()# method is called, or the container is
  146. automatically kept in order according to the last call of the method.
  147. See the API documentation for a detailed description of the interfaces.
  148. [[datamodel.container.indexedcontainer]]
  149. == [classname]#IndexedContainer#
  150. The [classname]#IndexedContainer# is an in-memory container that implements the
  151. [interfacename]#Indexed# interface to allow referencing the items by an index.
  152. [classname]#IndexedContainer# is used as the default container in most selection
  153. components in Vaadin.
  154. The properties need to be defined with [methodname]#addContainerProperty()#,
  155. which takes the property ID, type, and a default value. This must be done before
  156. any items are added to the container.
  157. ----
  158. // Create the container
  159. IndexedContainer container = new IndexedContainer();
  160. // Define the properties (columns)
  161. container.addContainerProperty("name", String.class, "noname");
  162. container.addContainerProperty("volume", Double.class, -1.0d);
  163. // Add some items
  164. Object content[][] = { {"jar", 2.0}, {"bottle", 0.75},
  165. {"can", 1.5}};
  166. for (Object[] row: content) {
  167. Item newItem = container.getItem(container.addItem());
  168. newItem.getItemProperty("name").setValue(row[0]);
  169. newItem.getItemProperty("volume").setValue(row[1]);
  170. }
  171. ----
  172. New items are added with [methodname]#addItem()#, which returns the item ID of
  173. the new item, or by giving the item ID as a parameter as was described earlier.
  174. Note that the [classname]#Table# component, which has
  175. [classname]#IndexedContainer# as its default container, has a conveniency
  176. [methodname]#addItem()# method that allows adding items as object vectors
  177. containing the property values.
  178. The container implements the [interfacename]#Container.Indexed# feature to allow
  179. accessing the item IDs by their index number, with [methodname]#getIdByIndex()#,
  180. etc. The feature is required mainly for internal purposes of some components,
  181. such as [classname]#Table#, which uses it to enable lazy transmission of table
  182. data to the client-side.
  183. [[datamodel.container.beancontainer]]
  184. == [classname]#BeanContainer#
  185. The [classname]#BeanContainer# is an in-memory container for JavaBean objects.
  186. Each contained bean is wrapped inside a [classname]#BeanItem# wrapper. The item
  187. properties are determined automatically by inspecting the getter and setter
  188. methods of the class. This requires that the bean class has public visibility,
  189. local classes for example are not allowed. Only beans of the same type can be
  190. added to the container.
  191. The generic has two parameters: a bean type and an item identifier type. The
  192. item identifiers can be obtained by defining a custom resolver, using a specific
  193. item property for the IDs, or by giving item IDs explicitly. As such, it is more
  194. general than the [classname]#BeanItemContainer#, which uses the bean object
  195. itself as the item identifier, making the use usually simpler. Managing the item
  196. IDs makes [classname]#BeanContainer# more complex to use, but it is necessary in
  197. some cases where the [methodname]#equals()# or [methodname]#hashCode()# methods
  198. have been reimplemented in the bean.
  199. ----
  200. // Here is a JavaBean
  201. public class Bean implements Serializable {
  202. String name;
  203. double energy; // Energy content in kJ/100g
  204. public Bean(String name, double energy) {
  205. this.name = name;
  206. this.energy = energy;
  207. }
  208. public String getName() {
  209. return name;
  210. }
  211. public void setName(String name) {
  212. this.name = name;
  213. }
  214. public double getEnergy() {
  215. return energy;
  216. }
  217. public void setEnergy(double energy) {
  218. this.energy = energy;
  219. }
  220. }
  221. void basic(VerticalLayout layout) {
  222. // Create a container for such beans with
  223. // strings as item IDs.
  224. BeanContainer<String, Bean> beans =
  225. new BeanContainer<String, Bean>(Bean.class);
  226. // Use the name property as the item ID of the bean
  227. beans.setBeanIdProperty("name");
  228. // Add some beans to it
  229. beans.addBean(new Bean("Mung bean", 1452.0));
  230. beans.addBean(new Bean("Chickpea", 686.0));
  231. beans.addBean(new Bean("Lentil", 1477.0));
  232. beans.addBean(new Bean("Common bean", 129.0));
  233. beans.addBean(new Bean("Soybean", 1866.0));
  234. // Bind a table to it
  235. Table table = new Table("Beans of All Sorts", beans);
  236. layout.addComponent(table);
  237. }
  238. ----
  239. See the http://demo.vaadin.com/book-examples-vaadin7/book#datamodel.container.beancontainer.basic[on-line example, window="_blank"].
  240. To use explicit item IDs, use the methods [methodname]#addItem(Object, Object)#,
  241. [methodname]#addItemAfter(Object, Object, Object)#, and
  242. [methodname]#addItemAt(int, Object, Object)#.
  243. It is not possible to add additional properties to the container, except
  244. properties in a nested bean.
  245. [[datamodel.container.beancontainer.nestedproperties]]
  246. === Nested Properties
  247. ((("nested bean properties", id="term.datamodel.container.beancontainer.nestedproperties", range="startofrange")))
  248. If you have a nested bean with an 1:1 relationship inside a bean type contained
  249. in a [classname]#BeanContainer# or [classname]#BeanItemContainer#, you can add
  250. its properties to the container by specifying them with
  251. [methodname]#addNestedContainerProperty()#. The feature is defined at the level
  252. of [classname]#AbstractBeanContainer#.
  253. ((("[methodname]#addNestedContainerProperty()#")))
  254. As with the bean in a bean container, also a nested bean must have public
  255. visibility or otherwise an access exception is thrown. An intermediate reference
  256. from a bean in the bean container to a nested bean may have a null value.
  257. For example, let us assume that we have the following two beans with the first
  258. one nested inside the second one.
  259. ----
  260. /** Bean to be nested */
  261. public class EqCoord implements Serializable {
  262. double rightAscension; /* In angle hours */
  263. double declination; /* In degrees */
  264. ... setters and getters for the properties ...
  265. }
  266. /** Bean referencing a nested bean */
  267. public class Star implements Serializable {
  268. String name;
  269. EqCoord equatorial; /* Nested bean */
  270. ... setters and getters for the properties ...
  271. }
  272. ----
  273. See the http://demo.vaadin.com/book-examples-vaadin7/book#datamodel.container.beanitemcontainer.nestedbean[on-line example, window="_blank"].
  274. After creating the container, you can declare the nested properties by
  275. specifying their property identifiers with the
  276. [methodname]#addNestedContainerProperty()# in dot notation.
  277. ----
  278. // Create a container for beans
  279. BeanItemContainer<Star> stars =
  280. new BeanItemContainer<Star>(Star.class);
  281. // Declare the nested properties to be used in the container
  282. stars.addNestedContainerProperty("equatorial.rightAscension");
  283. stars.addNestedContainerProperty("equatorial.declination");
  284. // Add some items
  285. stars.addBean(new Star("Sirius", new EqCoord(6.75, 16.71611)));
  286. stars.addBean(new Star("Polaris", new EqCoord(2.52, 89.26417)));
  287. // Here the nested bean reference is null
  288. stars.addBean(new Star("Vega", null));
  289. ----
  290. See the http://demo.vaadin.com/book-examples-vaadin7/book#datamodel.container.beanitemcontainer.nestedbean[on-line example, window="_blank"].
  291. If you bind such a container to a [classname]#Table#, you probably also need to
  292. set the column headers. Notice that the entire nested bean itself is still a
  293. property in the container and would be displayed in its own column. The
  294. [methodname]#toString()# method is used for obtaining the displayed value, which
  295. is by default an object reference. You normally do not want this, so you can
  296. hide the column with [methodname]#setVisibleColumns()#.
  297. ((("[methodname]#setVisibleColumns()#")))
  298. ----
  299. // Put them in a table
  300. Table table = new Table("Stars", stars);
  301. table.setColumnHeader("equatorial.rightAscension", "RA");
  302. table.setColumnHeader("equatorial.declination", "Decl");
  303. table.setPageLength(table.size());
  304. // Have to set explicitly to hide the "equatorial" property
  305. table.setVisibleColumns("name",
  306. "equatorial.rightAscension", "equatorial.declination");
  307. ----
  308. See the http://demo.vaadin.com/book-examples-vaadin7/book#datamodel.container.beanitemcontainer.nestedbean[on-line example, window="_blank"].
  309. The resulting table is shown in
  310. <<figure.datamodel.container.beancontainer.nestedproperties>>.
  311. [[figure.datamodel.container.beancontainer.nestedproperties]]
  312. .[classname]#Table# Bound to a [classname]#BeanContainer# with Nested Properties
  313. image::img/beanitemcontainer-nested-beans.png[]
  314. The bean binding in [classname]#AbstractBeanContainer# normally uses the
  315. [classname]#MethodProperty# implementation of the [classname]#Property#
  316. interface to access the bean properties using the setter and getter methods. For
  317. nested properties, the [classname]#NestedMethodProperty# implementation is used.
  318. ((("[classname]#MethodProperty#")))
  319. ((("[classname]#NestedMethodProperty#")))
  320. (((range="endofrange", startref="term.datamodel.container.beancontainer.nestedproperties")))
  321. ifdef::web[]
  322. [[datamodel.container.beancontainer.idresolver]]
  323. === Defining a Bean ID Resolver
  324. If a bean ID resolver is set using [methodname]#setBeanIdResolver()# or
  325. [methodname]#setBeanIdProperty()#, the methods [methodname]#addBean()#,
  326. [methodname]#addBeanAfter()#, [methodname]#addBeanAt()# and
  327. [methodname]#addAll()# can be used to add items to the container. If one of
  328. these methods is called, the resolver is used to generate an identifier for the
  329. item (must not return [parameter]#null#).
  330. Note that explicit item identifiers can also be used when a resolver has been
  331. set by calling the [methodname]#addItem*()# methods - the resolver is only used
  332. when adding beans using the [methodname]#addBean*()# or
  333. [methodname]#addAll(Collection)# methods.
  334. endif::web[]
  335. [[datamodel.container.beanitemcontainer]]
  336. == [classname]#BeanItemContainer#
  337. [classname]#BeanItemContainer# is a container for JavaBean objects where each
  338. bean is wrapped inside a [classname]#BeanItem# wrapper. The item properties are
  339. determined automatically by inspecting the getter and setter methods of the
  340. class. This requires that the bean class has public visibility, local classes
  341. for example are not allowed. Only beans of the same type can be added to the
  342. container.
  343. [classname]#BeanItemContainer# is a specialized version of the
  344. [classname]#BeanContainer# described in <<datamodel.container.beancontainer>>.
  345. It uses the bean itself as the item identifier, which makes it a bit easier to
  346. use than [classname]#BeanContainer# in many cases. The latter is, however,
  347. needed if the bean has reimplemented the [methodname]#equals()# or
  348. [methodname]#hashCode()# methods.
  349. Let us revisit the example given in <<datamodel.container.beancontainer>> using
  350. the [classname]#BeanItemContainer#.
  351. ----
  352. // Create a container for the beans
  353. BeanItemContainer<Bean> beans =
  354. new BeanItemContainer<Bean>(Bean.class);
  355. // Add some beans to it
  356. beans.addBean(new Bean("Mung bean", 1452.0));
  357. beans.addBean(new Bean("Chickpea", 686.0));
  358. beans.addBean(new Bean("Lentil", 1477.0));
  359. beans.addBean(new Bean("Common bean", 129.0));
  360. beans.addBean(new Bean("Soybean", 1866.0));
  361. // Bind a table to it
  362. Table table = new Table("Beans of All Sorts", beans);
  363. ----
  364. See the http://demo.vaadin.com/book-examples-vaadin7/book#datamodel.container.beanitemcontainer.basic[on-line example, window="_blank"].
  365. It is not possible to add additional properties to a
  366. [classname]#BeanItemContainer#, except properties in a nested bean, as described
  367. in <<datamodel.container.beancontainer>>. ((("nested bean
  368. properties")))
  369. ifdef::web[]
  370. [[datamodel.container.iterating]]
  371. == Iterating Over a Container
  372. As the items in a [classname]#Container# are not necessarily indexed, iterating
  373. over the items has to be done using an [classname]#Iterator#. The
  374. [methodname]#getItemIds()# method of [classname]#Container# returns a
  375. [classname]#Collection# of item identifiers over which you can iterate. The
  376. following example demonstrates a typical case where you iterate over the values
  377. of check boxes in a column of a [classname]#Table# component. The context of the
  378. example is the example used in
  379. <<dummy/../../../framework/components/components-table#components.table,"Table">>.
  380. ----
  381. // Collect the results of the iteration into this string.
  382. String items = "";
  383. // Iterate over the item identifiers of the table.
  384. for (Iterator i = table.getItemIds().iterator(); i.hasNext();) {
  385. // Get the current item identifier, which is an integer.
  386. int iid = (Integer) i.next();
  387. // Now get the actual item from the table.
  388. Item item = table.getItem(iid);
  389. // And now we can get to the actual checkbox object.
  390. Button button = (Button)
  391. (item.getItemProperty("ismember").getValue());
  392. // If the checkbox is selected.
  393. if ((Boolean)button.getValue() == true) {
  394. // Do something with the selected item; collect the
  395. // first names in a string.
  396. items += item.getItemProperty("First Name")
  397. .getValue() + " ";
  398. }
  399. }
  400. // Do something with the results; display the selected items.
  401. layout.addComponent (new Label("Selected items: " + items));
  402. ----
  403. Notice that the [methodname]#getItemIds()# returns an __unmodifiable
  404. collection__, so the [classname]#Container# may not be modified during
  405. iteration. You can not, for example, remove items from the
  406. [classname]#Container# during iteration. The modification includes modification
  407. in another thread. If the [classname]#Container# is modified during iteration, a
  408. [classname]#ConcurrentModificationException# is thrown and the iterator may be
  409. left in an undefined state.
  410. endif::web[]
  411. [[datamodel.container.gpc]]
  412. == [classname]#GeneratedPropertyContainer#
  413. [classname]#GeneratedPropertyContainer# is a container wrapper that allows
  414. defining generated values for properties (columns). The generated properties can
  415. shadow properties with the same IDs in the wrapped container. Removing a
  416. property from the wrapper hides it.
  417. The container is especially useful with [classname]#Grid#, which does not
  418. support generated columns or hiding columns like [classname]#Table# does.
  419. [[datamodel.container.gpc.wrapping]]
  420. === Wrapping a Container
  421. A container to be wrapped must be a [interfacename]#Container.Indexed#. It can
  422. optionally also implement [interfacename]#Container.Sortable# or
  423. [interfacename]#Container.Filterable# to enable sorting and filtering the
  424. container, respectively.
  425. For example, let us consider the following container with some regular columns:
  426. ----
  427. IndexedContainer container = new IndexedContainer();
  428. container.addContainerProperty("firstname", String.class, null);
  429. container.addContainerProperty("lastname", String.class, null);
  430. container.addContainerProperty("born", Integer.class, null);
  431. container.addContainerProperty("died", Integer.class, null);
  432. // Wrap it
  433. GeneratedPropertyContainer gpcontainer =
  434. new GeneratedPropertyContainer(container);
  435. ----
  436. [[datamodel.container.gpc.properties]]
  437. === Generated Properties
  438. Now, you can add generated properties in the container with
  439. [methodname]#addGeneratedProperty()# by specifying a property ID and a
  440. [interfacename]#PropertyValueGenerator#. The method takes the ID of the
  441. generated property as first parameter; you can use a same ID as in the wrapped
  442. container to shadow its properties.
  443. You need to implement [methodname]#getType()#, which must return the class
  444. object of the value type of the property, and [methodname]#getValue()#, which
  445. returns the property value for the given item. The item ID and the property ID
  446. of the generated property are also given in case they are needed. You can access
  447. other properties of the item to compute the property value.
  448. ----
  449. gpcontainer.addGeneratedProperty("lived",
  450. new PropertyValueGenerator<Integer>() {
  451. @Override
  452. public Integer getValue(Item item, Object itemId,
  453. Object propertyId) {
  454. int born = (Integer)
  455. item.getItemProperty("born").getValue();
  456. int died = (Integer)
  457. item.getItemProperty("died").getValue();
  458. return Integer.valueOf(died - born);
  459. }
  460. @Override
  461. public Class<Integer> getType() {
  462. return Integer.class;
  463. }
  464. });
  465. ----
  466. You can access other items in the container, also their generated properties,
  467. although you should beware of accidental recursion.
  468. [[datamodel.container.gpc.using]]
  469. === Using [classname]#GeneratedPropertyContainer#
  470. Finally, you need to bind the [classname]#GeneratedPropertyContainer# to the
  471. component instead of the wrapped container.
  472. ----
  473. Grid grid = new Grid(gpcontainer);
  474. ----
  475. When using [classname]#GeneratedPropertyContainer# in [classname]#Grid#, notice
  476. that generated columns are read-only, so you can not add grid rows with
  477. [methodname]#addRow()#. In editable mode, editor fields are not generated for
  478. generated columns.
  479. [[datamodel.container.gpc.sorting]]
  480. === Sorting
  481. Even though the [classname]#GeneratedPropertyContainer# implements
  482. [interfacename]#Container.Sortable#, the wrapped container must also support it
  483. or otherwise sorting is disabled. Also, the generated properties are not
  484. normally sortable, but require special handling to enable sorting.
  485. [[datamodel.container.filtered]]
  486. == [classname]#Filterable# Containers
  487. ((("Container", "Filterable", id="term.datamodel.container.filtered.filterable", range="startofrange")))
  488. ((("[classname]#Filter# (in [classname]#Container#)", id="term.datamodel.container.filtered.filters", range="startofrange")))
  489. Containers that implement the [classname]#Container.Filterable# interface can be
  490. filtered. For example, the built-in [classname]#IndexedContainer# and the bean
  491. item containers implement it. Filtering is typically used for filtering the
  492. content of a [classname]#Table#.
  493. ((("[classname]#IndexedContainer#")))
  494. ((("[classname]#Table#")))
  495. Filters implement the [classname]#Filter# interface and you add them to a
  496. filterable container with the [methodname]#addContainerFilter()# method.
  497. Container items that pass the filter condition are kept and shown in the
  498. filterable component.
  499. ((("[methodname]#addContainerFilter()#")))
  500. ----
  501. Filter filter = new SimpleStringFilter("name",
  502. "Douglas", true, false);
  503. table.addContainerFilter(filter);
  504. ----
  505. See the http://demo.vaadin.com/book-examples-vaadin7/book#datamodel.container.filter.basic[on-line example, window="_blank"].
  506. If multiple filters are added to a container, they are evaluated using the
  507. logical AND operator so that only items that are passed by all the filters are
  508. kept.
  509. [[datamodel.container.filtered.composite]]
  510. === Atomic and Composite Filters
  511. Filters can be classified as __atomic__ and __composite__. Atomic filters, such
  512. as [classname]#SimpleStringFilter#, define a single condition, usually for a
  513. specific container property. Composite filters make filtering decisions based on
  514. the result of one or more other filters. The built-in composite filters
  515. implement the logical operators AND, OR, or NOT.
  516. For example, the following composite filter would filter out items where the
  517. [literal]#++name++# property contains the name "Douglas" somewhere __or__ where
  518. the [literal]#++age++# property has value less than 42. The properties must have
  519. [classname]#String# and [classname]#Integer# types, respectively.
  520. ----
  521. filter = new Or(new SimpleStringFilter("name",
  522. "Douglas", true, false),
  523. new Compare.Less("age", 42));
  524. ----
  525. [[datamodel.container.filtered.builtin]]
  526. === Built-In Filter Types
  527. The built-in filter types are the following:
  528. [classname]#SimpleStringFilter#:: ((("[classname]#SimpleStringFilter#")))
  529. +
  530. Passes items where the specified property, that must be of [classname]#String#
  531. type, contains the given [parameter]#filterString# as a substring. If
  532. [parameter]#ignoreCase# is [parameter]#true#, the search is case insensitive. If
  533. the [parameter]#onlyMatchPrefix# is [parameter]#true#, the substring may only be
  534. in the beginning of the string, otherwise it may be elsewhere as well.
  535. [classname]#IsNull#:: ((("[classname]#IsNull# (filter)")))
  536. +
  537. Passes items where the specified property has null value. For in-memory
  538. filtering, a simple [literal]#++==++# check is performed. For other containers,
  539. the comparison implementation is container dependent, but should correspond to
  540. the in-memory null check.
  541. [classname]#Equal#,[classname]#Greater#,
  542. [classname]#Less#,
  543. [classname]#GreaterOrEqual#, and[classname]#LessOrEqual#:: ((("[classname]#Equal# (filter)")))
  544. ((("[classname]#Greater# (filter)")))
  545. ((("[classname]#Less# (filter)")))
  546. ((("[classname]#GreaterOrEqual# (filter)")))
  547. ((("[classname]#LessOrEqual# (filter)")))
  548. +
  549. The comparison filter implementations compare the specified property value to
  550. the given constant and pass items for which the comparison result is true. The
  551. comparison operators are included in the abstract [classname]#Compare# class.
  552. +
  553. For the [classname]#Equal# filter, the [methodname]#equals()# method for the
  554. property is used in built-in in-memory containers. In other types of containers,
  555. the comparison is container dependent and may use, for example, database
  556. comparison operations.
  557. +
  558. For the other filters, the property value type must implement the
  559. [classname]#Comparable# interface to work with the built-in in-memory
  560. containers. Again for the other types of containers, the comparison is container
  561. dependent.
  562. [classname]#And#and[classname]#Or#:: ((("[classname]#And# (filter)")))
  563. ((("[classname]#Or# (filter)")))
  564. +
  565. These logical operator filters are composite filters that combine multiple other
  566. filters.
  567. [classname]#Not#:: ((("[classname]#Not# (filter)")))
  568. +
  569. The logical unary operator filter negates which items are passed by the filter
  570. given as the parameter.
  571. [[datamodel.container.filtered.custom]]
  572. === Implementing Custom Filters
  573. A custom filter needs to implement the [classname]#Container.Filter# interface.
  574. A filter can use a single or multiple properties for the filtering logic. The
  575. properties used by the filter must be returned with the
  576. [methodname]#appliesToProperty()# method. If the filter applies to a
  577. user-defined property or properties, it is customary to give the properties as
  578. the first argument for the constructor of the filter.
  579. ----
  580. class MyCustomFilter implements Container.Filter {
  581. protected String propertyId;
  582. protected String regex;
  583. public MyCustomFilter(String propertyId, String regex) {
  584. this.propertyId = propertyId;
  585. this.regex = regex;
  586. }
  587. /** Tells if this filter works on the given property. */
  588. @Override
  589. public boolean appliesToProperty(Object propertyId) {
  590. return propertyId != null &&
  591. propertyId.equals(this.propertyId);
  592. }
  593. ----
  594. See the http://demo.vaadin.com/book-examples-vaadin7/book#datamodel.container.filter.custom[on-line example, window="_blank"].
  595. The actual filtering logic is done in the [methodname]#passesFilter()# method,
  596. which simply returns [literal]#++true++# if the item should pass the filter and
  597. [literal]#++false++# if it should be filtered out.
  598. ----
  599. /** Apply the filter on an item to check if it passes. */
  600. @Override
  601. public boolean passesFilter(Object itemId, Item item)
  602. throws UnsupportedOperationException {
  603. // Acquire the relevant property from the item object
  604. Property p = item.getItemProperty(propertyId);
  605. // Should always check validity
  606. if (p == null || !p.getType().equals(String.class))
  607. return false;
  608. String value = (String) p.getValue();
  609. // The actual filter logic
  610. return value.matches(regex);
  611. }
  612. }
  613. ----
  614. See the http://demo.vaadin.com/book-examples-vaadin7/book#datamodel.container.filter.custom[on-line example, window="_blank"].
  615. You can use such a custom filter just like any other:
  616. ----
  617. c.addContainerFilter(
  618. new MyCustomFilter("Name", (String) tf.getValue()));
  619. ----
  620. See the http://demo.vaadin.com/book-examples-vaadin7/book#datamodel.container.filter.custom[on-line example, window="_blank"].
  621. (((range="endofrange", startref="term.datamodel.container.filtered.filters")))
  622. (((range="endofrange", startref="term.datamodel.container.filtered.filterable")))
  623. (((range="endofrange", startref="term.datamodel.container")))