The Item interface provides access to a set of named
properties. Each property is identified by a property
identifier (PID) and a reference to such a property can be queried
from an Item with
getItemProperty() using the identifier.
Examples on the use of items include rows in a Table,
with the properties corresponding to table columns, nodes in a
Tree, and the the data bound to a
Form, with item's properties bound to individual form
fields.
Items are generally equivalent to objects in the object-oriented model, but
with the exception that they are configurable and provide an event handling
mechanism. The simplest way to utilize Item interface
is to use existing implementations. Provided utility classes include a
configurable property set (PropertysetItem) and a
bean-to-item adapter (BeanItem). Also, a
Form implements the interface and can therefore be used
directly as an item.
In addition to being used indirectly by many user interface components, items
provide the basic data model underlying the Form
component. In simple cases, forms can even be generated automatically from
items. The properties of the item correspond to the fields of the form.
The Item interface defines inner interfaces for
maintaining the item property set and listening changes made to
it. PropertySetChangeEvent events can be emitted by a
class implementing the PropertySetChangeNotifier
interface. They can be received through the
PropertySetChangeListener interface.
The PropertysetItem is a generic implementation of
the Item interface that allows storing
properties. The properties are added with
addItemProperty(), which takes a name and the
property as parameters.
The following example demonstrates a typical case of collecting
ObjectProperty properties in an item:
PropertysetItem item = new PropertysetItem();
item.addItemProperty("name", new ObjectProperty("Zaphod"));
item.addItemProperty("age", new ObjectProperty(42));
// Bind it to a component
Form form = new Form();
form.setItemDataSource(item);
The BeanItem implementation of the
Item interface is a wrapper for Java Bean
objects. In fact, only the setters and getters are required while
serialization and other bean features are not, so you can wrap almost any
POJOs with minimal requirements.
// Here is a bean (or more exactly a POJO)
class Person {
String name;
int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age.intValue();
}
}
// Create an instance of the bean
Person bean = new Person();
// Wrap it in a BeanItem
BeanItem<Person> item = new BeanItem<Person>(bean);
// Bind it to a component
Form form = new Form();
form.setItemDataSource(item);
You can use the getBean() method to get a
reference to the underlying bean.
You may often have composite classes where one class "has a" another
class. For example, consider the following
Planet class which "has a" discoverer:
// Here is a bean with two nested beans
public class Planet implements Serializable {
String name;
Person discoverer;
public Planet(String name, Person discoverer) {
this.name = name;
this.discoverer = discoverer;
}
... getters and setters ...
}
...
// Create an instance of the bean
Planet planet = new Planet("Uranus",
new Person("William Herschel", 1738));
When shown in a Form, for example, you would
want to list the properties of the nested bean along the properties of
the composite bean. You can do that by binding the properties of the
nested bean individually with a MethodProperty
or NestedMethodProperty. You should usually
hide the nested bean from binding as a property by listing only the
bound properties in the constructor.
// Wrap it in a BeanItem and hide the nested bean property
BeanItem<Planet> item = new BeanItem<Planet>(planet,
new String[]{"name"});
// Bind the nested properties.
// Use NestedMethodProperty to bind using dot notation.
item.addItemProperty("discoverername",
new NestedMethodProperty(planet, "discoverer.name"));
// The other way is to use regular MethodProperty.
item.addItemProperty("discovererborn",
new MethodProperty<Person>(planet.getDiscoverer(),
"born"));
The difference is that NestedMethodProperty
does not access the nested bean immediately but only when accessing
the property values, while when using
MethodProperty the nested bean is accessed when
creating the method property. The difference is only significant if
the nested bean can be null or be changed later.
You can use such a bean item for example in a
Form as follows:
// Bind it to a component
Form form = new Form();
form.setItemDataSource(item);
// Nicer captions
form.getField("discoverername").setCaption("Discoverer");
form.getField("discovererborn").setCaption("Born");
The BeanContainer and
BeanItemContainer allow easy definition of
nested bean properties with
addNestedContainerProperty(), as described in
the section called “Nested Properties”.