summaryrefslogtreecommitdiffstats
path: root/documentation/datamodel/datamodel-properties.asciidoc
diff options
context:
space:
mode:
Diffstat (limited to 'documentation/datamodel/datamodel-properties.asciidoc')
-rw-r--r--documentation/datamodel/datamodel-properties.asciidoc399
1 files changed, 0 insertions, 399 deletions
diff --git a/documentation/datamodel/datamodel-properties.asciidoc b/documentation/datamodel/datamodel-properties.asciidoc
deleted file mode 100644
index d5d0d3e39d..0000000000
--- a/documentation/datamodel/datamodel-properties.asciidoc
+++ /dev/null
@@ -1,399 +0,0 @@
----
-title: Properties
-order: 2
-layout: page
----
-
-[[datamodel.properties]]
-= Properties
-
-The [interfacename]#Property# interface is the base of the Vaadin Data Model. It
-provides a standardized API for a single data value object that can be read
-(get) and written (set). A property is always typed, but can optionally support
-data type conversions. The type of a property can be any Java class. Optionally,
-properties can provide value change events for following their changes.
-
-You can set the value of a property with [methodname]#setValue()# and read with
-[methodname]#getValue()#.
-
-In the following, we set and read the property value from a
-[classname]#TextField# component, which implements the [interfacename]#Property#
-interface to allow accessing the field value.
-
-
-----
-final TextField tf = new TextField("Name");
-
-// Set the value
-tf.setValue("The text field value");
-
-// When the field value is edited by the user
-tf.addValueChangeListener(
- new Property.ValueChangeListener() {
- public void valueChange(ValueChangeEvent event) {
- // Do something with the new value
- layout.addComponent(new Label(tf.getValue()));
- }
-});
-----
-See the http://demo.vaadin.com/book-examples-vaadin7/book#datamodel.properties.basic[on-line example, window="_blank"].
-
-Changes in the property value usually fire a [classname]#ValueChangeEvent#,
-which can be handled with a [classname]#ValueChangeListener#. The event object
-provides reference to the property with [methodname]#getProperty()#. Note that
-its [methodname]#getValue()# method returns the value with [classname]#Object#
-type, so you need to cast it to the proper type.
-
-Properties are in themselves unnamed. They are collected in __items__, which
-associate the properties with names: the __Property Identifiers__ or __PID__s.
-Items can be further contained in containers and are identified with __Item
-Identifiers__ or __IID__s. In the spreadsheet analogy, __Property Identifiers__
-would correspond to column names and __Item Identifiers__ to row names. The
-identifiers can be arbitrary objects, but must implement the
-[methodname]#equals(Object)# and [methodname]#hashCode()# methods so that they
-can be used in any standard Java [classname]#Collection#.
-
-The [classname]#Property# interface can be utilized either by implementing the
-interface or by using some of the built-in property implementations. Vaadin
-includes a [classname]#Property# interface implementation for arbitrary function
-pairs and bean properties, with the [classname]#MethodProperty# class, and for
-simple object properties, with the [classname]#ObjectProperty# class, as
-described later.
-
-In addition to the simple components, selection components provide their current
-selection as the property value. In single selection mode, the property is a
-single item identifier, while in multiple selection mode it is a set of item
-identifiers. See the documentation of the selection components for further
-details.
-
-Components that can be bound to a property have an internal default data source
-object, typically a [classname]#ObjectProperty#, which is described later. As
-all such components are viewers or editors, also described later, so you can
-rebind a component to any data source with
-[methodname]#setPropertyDataSource()#.
-
-[[datamodel.properties.viewers]]
-== Property Viewers and Editors
-
-The most important function of the [classname]#Property# as well as of the other
-data model interfaces is to connect classes implementing the interface directly
-to editor and viewer classes. This means connecting a data source (model) to a
-user interface component (views) to allow editing or viewing the data model.
-
-A property can be bound to a component implementing the [classname]#Viewer#
-interface with [methodname]#setPropertyDataSource()#.
-
-
-----
-// Have a data model
-ObjectProperty property =
- new ObjectProperty("Hello", String.class);
-
-// Have a component that implements Viewer
-Label viewer = new Label();
-
-// Bind it to the data
-viewer.setPropertyDataSource(property);
-----
-
-You can use the same method in the [classname]#Editor# interface to bind a
-component that allows editing a particular property type to a property.
-
-
-----
-// Have a data model
-ObjectProperty property =
- new ObjectProperty("Hello", String.class);
-
-// Have a component that implements Viewer
-TextField editor = new TextField("Edit Greeting");
-
-// Bind it to the data
-editor.setPropertyDataSource(property);
-
-----
-
-As all field components implement the [classname]#Property# interface, you can
-bind any component implementing the [classname]#Viewer# interface to any field,
-assuming that the viewer is able the view the object type of the field.
-Continuing from the above example, we can bind a [classname]#Label# to the
-[classname]#TextField# value:
-
-
-----
-Label viewer = new Label();
-viewer.setPropertyDataSource(editor);
-
-// The value shown in the viewer is updated immediately
-// after editing the value in the editor (once it
-// loses the focus)
-editor.setImmediate(true);
-----
-
-If a field has validators, as described in
-<<dummy/../../../framework/components/components-fields#components.fields.validation,"Field
-Validation">>, the validators are executed before writing the value to the
-property data source, or by calling the [methodname]#validate()# or
-[methodname]#commit()# for the field.
-
-
-[[datamodel.properties.objectproperty]]
-== [classname]#ObjectProperty# Implementation
-
-The [classname]#ObjectProperty# class is a simple implementation of the
-[classname]#Property# interface that allows storing an arbitrary Java object.
-
-
-----
-// Have a component that implements Viewer interface
-final TextField tf = new TextField("Name");
-
-// Have a data model with some data
-String myObject = "Hello";
-
-// Wrap it in an ObjectProperty
-ObjectProperty property =
- new ObjectProperty(myObject, String.class);
-
-// Bind the property to the component
-tf.setPropertyDataSource(property);
-----
-
-
-[[datamodel.properties.converter]]
-== Converting Between Property Type and Representation
-
-Fields allow editing a certain type, such as a [classname]#String# or
-[classname]#Date#. The bound property, on the other hand, could have some
-entirely different type. Conversion between a representation edited by the field
-and the model defined in the property is handler with a converter that
-implements the [interfacename]#Converter# interface.
-
-Most common type conversions, such as between string and integer, are handled by
-the default converters. They are created in a converter factory global in the
-application.
-
-[[datamodel.properties.converter.basic]]
-=== Basic Use of Converters
-
-The [methodname]#setConverter([interfacename]#Converter#)# method sets the
-converter for a field. The method is defined in [classname]#AbstractField#.
-
-
-----
-// Have an integer property
-final ObjectProperty<Integer> property =
- new ObjectProperty<Integer>(42);
-
-// Create a TextField, which edits Strings
-final TextField tf = new TextField("Name");
-
-// Use a converter between String and Integer
-tf.setConverter(new StringToIntegerConverter());
-
-// And bind the field
-tf.setPropertyDataSource(property);
-----
-
-The built-in converters are the following:
-
-[[datamodel.properties.converter.basic.built-in]]
-.Built-in Converters
-[options="header"]
-|===============
-|Converter|Representation|Model
-|[classname]#StringToIntegerConverter#|[classname]#String#|[classname]#Integer#
-|[classname]#StringToDoubleConverter#|[classname]#String#|[classname]#Double#
-|[classname]#StringToNumberConverter#|[classname]#String#|[classname]#Number#
-|[classname]#StringToBooleanConverter#|[classname]#String#|[classname]#Boolean#
-|[classname]#StringToDateConverter#|[classname]#String#|[classname]#Date#
-|[classname]#DateToLongConverter#|[classname]#Date#|[classname]#Long#
-
-|===============
-
-
-
-In addition, there is a [classname]#ReverseConverter# that takes a converter as
-a parameter and reverses the conversion direction.
-
-If a converter already exists for a type, the
-[methodname]#setConverter([interfacename]#Class#)# retrieves the converter for
-the given type from the converter factory, and then sets it for the field. This
-method is used implicitly when binding field to a property data source.
-
-
-[[datamodel.properties.converter.custom]]
-=== Implementing a Converter
-
-A conversion always occurs between a __representation type__, edited by the
-field component, and a __model type__, that is, the type of the property data
-source. Converters implement the [interfacename]#Converter# interface defined in
-the [package]#com.vaadin.data.util.converter# package.
-
-For example, let us assume that we have a simple [classname]#Complex# type for
-storing complex values.
-
-
-----
-public class ComplexConverter
- implements Converter<String, Complex> {
- @Override
- public Complex convertToModel(String value, Locale locale)
- throws ConversionException {
- String parts[] =
- value.replaceAll("[\\(\\)]", "").split(",");
- if (parts.length != 2)
- throw new ConversionException(
- "Unable to parse String to Complex");
- return new Complex(Double.parseDouble(parts[0]),
- Double.parseDouble(parts[1]));
- }
-
- @Override
- public String convertToPresentation(Complex value,
- Locale locale)
- throws ConversionException {
- return "("+value.getReal()+","+value.getImag()+")";
- }
-
- @Override
- public Class<Complex> getModelType() {
- return Complex.class;
- }
-
- @Override
- public Class<String> getPresentationType() {
- return String.class;
- }
-}
-----
-
-The conversion methods get the locale for the conversion as a parameter.
-
-
-[[datamodel.properties.converter.converterfactory]]
-=== Converter Factory
-
-If a field does not directly allow editing a property type, a default converter
-is attempted to create using an application-global converter factory. If you
-define your own converters that you wish to include in the converter factory,
-you need to implement one yourself. While you could implement the
-[interfacename]#ConverterFactory# interface, it is usually easier to just extend
-[classname]#DefaultConverterFactory#.
-
-
-----
-class MyConverterFactory extends DefaultConverterFactory {
- @Override
- public <PRESENTATION, MODEL> Converter<PRESENTATION, MODEL>
- createConverter(Class<PRESENTATION> presentationType,
- Class<MODEL> modelType) {
- // Handle one particular type conversion
- if (String.class == presentationType &&
- Complex.class == modelType)
- return (Converter<PRESENTATION, MODEL>)
- new ComplexConverter();
-
- // Default to the supertype
- return super.createConverter(presentationType,
- modelType);
- }
-}
-
-// Use the factory globally in the application
-Application.getCurrentApplication().setConverterFactory(
- new MyConverterFactory());
-----
-
-
-
-ifdef::web[]
-[[datamodel.properties.implementing]]
-== Implementing the [classname]#Property# Interface
-
-Implementation of the [classname]#Property# interface requires defining setters
-and getters for the value and the __read-only__ mode. Only a getter is needed
-for the property type, as the type is often fixed in property implementations.
-
-The following example shows a simple implementation of the [classname]#Property#
-interface:
-
-
-----
-class MyProperty implements Property {
- Integer data = 0;
- boolean readOnly = false;
-
- // Return the data type of the model
- public Class<?> getType() {
- return Integer.class;
- }
-
- public Object getValue() {
- return data;
- }
-
- // Override the default implementation in Object
- @Override
- public String toString() {
- return Integer.toHexString(data);
- }
-
- public boolean isReadOnly() {
- return readOnly;
- }
-
- public void setReadOnly(boolean newStatus) {
- readOnly = newStatus;
- }
-
- public void setValue(Object newValue)
- throws ReadOnlyException, ConversionException {
- if (readOnly)
- throw new ReadOnlyException();
-
- // Already the same type as the internal representation
- if (newValue instanceof Integer)
- data = (Integer) newValue;
-
- // Conversion from a string is required
- else if (newValue instanceof String)
- try {
- data = Integer.parseInt((String) newValue, 16);
- } catch (NumberFormatException e) {
- throw new ConversionException();
- }
- else
- // Don't know how to convert any other types
- throw new ConversionException();
-
- // Reverse decode the hexadecimal value
- }
-}
-
-// Instantiate the property and set its data
-MyProperty property = new MyProperty();
-property.setValue(42);
-
-// Bind it to a component
-final TextField tf = new TextField("Name", property);
-----
-
-The components get the displayed value by the [methodname]#toString()# method,
-so it is necessary to override it. To allow editing the value, value returned in
-the [methodname]#toString()# must be in a format that is accepted by the
-[methodname]#setValue()# method, unless the property is read-only. The
-[methodname]#toString()# can perform any type conversion necessary to make the
-internal type a string, and the [methodname]#setValue()# must be able to make a
-reverse conversion.
-
-The implementation example does not notify about changes in the property value
-or in the read-only mode. You should normally also implement at least the
-[classname]#Property.ValueChangeNotifier# and
-[classname]#Property.ReadOnlyStatusChangeNotifier#. See the
-[classname]#ObjectProperty# class for an example of the implementation.
-
-endif::web[]
-
-
-