Holding properties in Items

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 Implementation

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);

Wrapping a Bean in a BeanItem

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)
public class Person {
    String name;
    int yearOfBirth;

    public Person(String name, int yearOfBirth) {
        this.name = name;
        this.yearOfBirth = yearOfBirth;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getYearOfBirth() {
        return yearOfBirth;
    }

    public void setYearOfBirth(int yearOfBirth) {
        this.yearOfBirth = yearOfBirth;
    }
}

// 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.

Nested Beans

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(),
                                "yearOfBirth"));

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");
A Form with Nested Bean Properties

The BeanContainer and BeanItemContainer allow easy definition of nested bean properties with addNestedContainerProperty(), as described in "Nested Properties".