From f6f111b88fcf65c9d75f36daaa046dd26efc68e5 Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Thu, 4 Aug 2016 20:58:28 +0300 Subject: Rename Field, AbstractField to legacy names Change-Id: I46ce708e0f10e4c9fa3d11a2aef5be0248c2999f --- .../com/vaadin/data/fieldgroup/BeanFieldGroup.java | 18 +- .../fieldgroup/DefaultFieldGroupFieldFactory.java | 22 +- .../com/vaadin/data/fieldgroup/FieldGroup.java | 114 +- .../data/fieldgroup/FieldGroupFieldFactory.java | 8 +- .../com/vaadin/data/fieldgroup/PropertyId.java | 4 +- .../main/java/com/vaadin/event/FieldEvents.java | 20 +- .../com/vaadin/legacy/ui/LegacyAbstractField.java | 1863 ++++++++++++++++++++ .../java/com/vaadin/legacy/ui/LegacyField.java | 140 ++ .../main/java/com/vaadin/server/VaadinSession.java | 4 +- .../main/java/com/vaadin/ui/AbstractComponent.java | 5 +- .../src/main/java/com/vaadin/ui/AbstractField.java | 1852 ------------------- .../main/java/com/vaadin/ui/AbstractSelect.java | 13 +- .../main/java/com/vaadin/ui/AbstractTextField.java | 5 +- server/src/main/java/com/vaadin/ui/CheckBox.java | 7 +- server/src/main/java/com/vaadin/ui/Component.java | 11 +- .../src/main/java/com/vaadin/ui/CustomField.java | 6 +- server/src/main/java/com/vaadin/ui/DateField.java | 28 +- .../java/com/vaadin/ui/DefaultFieldFactory.java | 13 +- server/src/main/java/com/vaadin/ui/Field.java | 138 -- server/src/main/java/com/vaadin/ui/Form.java | 141 +- .../main/java/com/vaadin/ui/FormFieldFactory.java | 6 +- server/src/main/java/com/vaadin/ui/Grid.java | 192 +- .../src/main/java/com/vaadin/ui/ProgressBar.java | 7 +- .../src/main/java/com/vaadin/ui/RichTextArea.java | 3 +- server/src/main/java/com/vaadin/ui/Slider.java | 7 +- server/src/main/java/com/vaadin/ui/Table.java | 23 +- .../main/java/com/vaadin/ui/TableFieldFactory.java | 7 +- server/src/main/java/com/vaadin/ui/TextField.java | 4 +- 28 files changed, 2366 insertions(+), 2295 deletions(-) create mode 100644 server/src/main/java/com/vaadin/legacy/ui/LegacyAbstractField.java create mode 100644 server/src/main/java/com/vaadin/legacy/ui/LegacyField.java delete mode 100644 server/src/main/java/com/vaadin/ui/AbstractField.java delete mode 100644 server/src/main/java/com/vaadin/ui/Field.java (limited to 'server/src/main/java/com/vaadin') diff --git a/server/src/main/java/com/vaadin/data/fieldgroup/BeanFieldGroup.java b/server/src/main/java/com/vaadin/data/fieldgroup/BeanFieldGroup.java index 0a92c00cad..62eb51b811 100644 --- a/server/src/main/java/com/vaadin/data/fieldgroup/BeanFieldGroup.java +++ b/server/src/main/java/com/vaadin/data/fieldgroup/BeanFieldGroup.java @@ -24,18 +24,18 @@ import com.vaadin.data.Item; import com.vaadin.data.util.BeanItem; import com.vaadin.data.util.BeanUtil; import com.vaadin.data.validator.BeanValidator; -import com.vaadin.ui.Field; +import com.vaadin.legacy.ui.LegacyField; public class BeanFieldGroup extends FieldGroup { private final Class beanType; private static Boolean beanValidationImplementationAvailable = null; - private final Map, BeanValidator> defaultValidators; + private final Map, BeanValidator> defaultValidators; public BeanFieldGroup(Class beanType) { this.beanType = beanType; - this.defaultValidators = new HashMap, BeanValidator>(); + this.defaultValidators = new HashMap, BeanValidator>(); } @Override @@ -149,20 +149,20 @@ public class BeanFieldGroup extends FieldGroup { } @Override - public void bind(Field field, Object propertyId) { + public void bind(LegacyField field, Object propertyId) { ensureNestedPropertyAdded(propertyId); super.bind(field, propertyId); } @Override - public T buildAndBind(String caption, Object propertyId, + public T buildAndBind(String caption, Object propertyId, Class fieldType) throws BindException { ensureNestedPropertyAdded(propertyId); return super.buildAndBind(caption, propertyId, fieldType); } @Override - public void unbind(Field field) throws BindException { + public void unbind(LegacyField field) throws BindException { super.unbind(field); BeanValidator removed = defaultValidators.remove(field); @@ -172,7 +172,7 @@ public class BeanFieldGroup extends FieldGroup { } @Override - protected void configureField(Field field) { + protected void configureField(LegacyField field) { super.configureField(field); // Add Bean validators if there are annotations if (isBeanValidationImplementationAvailable() @@ -226,7 +226,7 @@ public class BeanFieldGroup extends FieldGroup { * @param bean * the bean to be bound * @param objectWithMemberFields - * the class that contains {@link Field}s for bean properties + * the class that contains {@link LegacyField}s for bean properties * @return the bean field group used to make binding */ public static BeanFieldGroup bindFieldsUnbuffered(T bean, @@ -247,7 +247,7 @@ public class BeanFieldGroup extends FieldGroup { * @param bean * the bean to be bound * @param objectWithMemberFields - * the class that contains {@link Field}s for bean properties + * the class that contains {@link LegacyField}s for bean properties * @return the bean field group used to make binding */ public static BeanFieldGroup bindFieldsBuffered(T bean, diff --git a/server/src/main/java/com/vaadin/data/fieldgroup/DefaultFieldGroupFieldFactory.java b/server/src/main/java/com/vaadin/data/fieldgroup/DefaultFieldGroupFieldFactory.java index b6bf97e68e..27f4628bae 100644 --- a/server/src/main/java/com/vaadin/data/fieldgroup/DefaultFieldGroupFieldFactory.java +++ b/server/src/main/java/com/vaadin/data/fieldgroup/DefaultFieldGroupFieldFactory.java @@ -20,13 +20,13 @@ import java.util.EnumSet; import com.vaadin.data.Item; import com.vaadin.data.fieldgroup.FieldGroup.BindException; -import com.vaadin.ui.AbstractField; +import com.vaadin.legacy.ui.LegacyField; +import com.vaadin.legacy.ui.LegacyAbstractField; import com.vaadin.ui.AbstractSelect; import com.vaadin.ui.AbstractTextField; import com.vaadin.ui.CheckBox; import com.vaadin.ui.ComboBox; import com.vaadin.ui.DateField; -import com.vaadin.ui.Field; import com.vaadin.ui.InlineDateField; import com.vaadin.ui.ListSelect; import com.vaadin.ui.NativeSelect; @@ -64,7 +64,7 @@ public class DefaultFieldGroupFieldFactory implements FieldGroupFieldFactory { } @Override - public T createField(Class type, Class fieldType) { + public T createField(Class type, Class fieldType) { if (Enum.class.isAssignableFrom(type)) { return createEnumField(type, fieldType); } else if (Date.class.isAssignableFrom(type)) { @@ -89,7 +89,7 @@ public class DefaultFieldGroupFieldFactory implements FieldGroupFieldFactory { return rta; } - private T createEnumField(Class type, + private T createEnumField(Class type, Class fieldType) { // Determine first if we should (or can) create a select for the enum Class selectClass = null; @@ -110,9 +110,9 @@ public class DefaultFieldGroupFieldFactory implements FieldGroupFieldFactory { return null; } - private T createDateField(Class type, + private T createDateField(Class type, Class fieldType) { - AbstractField field; + LegacyAbstractField field; if (InlineDateField.class.isAssignableFrom(fieldType)) { field = new InlineDateField(); @@ -157,10 +157,10 @@ public class DefaultFieldGroupFieldFactory implements FieldGroupFieldFactory { * @since 7.4 * @param fieldType * the type of the field - * @return true if any AbstractField can be assigned to the field + * @return true if any LegacyAbstractField can be assigned to the field */ protected boolean anyField(Class fieldType) { - return fieldType == Field.class || fieldType == AbstractField.class; + return fieldType == LegacyField.class || fieldType == LegacyAbstractField.class; } /** @@ -169,11 +169,11 @@ public class DefaultFieldGroupFieldFactory implements FieldGroupFieldFactory { * the type of the field * @return true if any AbstractSelect can be assigned to the field */ - protected boolean anySelect(Class fieldType) { + protected boolean anySelect(Class fieldType) { return anyField(fieldType) || fieldType == AbstractSelect.class; } - protected T createBooleanField(Class fieldType) { + protected T createBooleanField(Class fieldType) { if (fieldType.isAssignableFrom(CheckBox.class)) { CheckBox cb = new CheckBox(null); cb.setImmediate(true); @@ -213,7 +213,7 @@ public class DefaultFieldGroupFieldFactory implements FieldGroupFieldFactory { * @return A field capable of editing the data or null if no field could be * created */ - protected T createDefaultField(Class type, + protected T createDefaultField(Class type, Class fieldType) { if (fieldType.isAssignableFrom(TextField.class)) { return fieldType.cast(createAbstractTextField(TextField.class)); diff --git a/server/src/main/java/com/vaadin/data/fieldgroup/FieldGroup.java b/server/src/main/java/com/vaadin/data/fieldgroup/FieldGroup.java index aaaae9e4f7..9c926637ef 100644 --- a/server/src/main/java/com/vaadin/data/fieldgroup/FieldGroup.java +++ b/server/src/main/java/com/vaadin/data/fieldgroup/FieldGroup.java @@ -29,9 +29,9 @@ import com.vaadin.data.Item; import com.vaadin.data.Property; import com.vaadin.data.Validator.InvalidValueException; import com.vaadin.data.util.TransactionalPropertyWrapper; -import com.vaadin.ui.AbstractField; +import com.vaadin.legacy.ui.LegacyField; +import com.vaadin.legacy.ui.LegacyAbstractField; import com.vaadin.ui.DefaultFieldFactory; -import com.vaadin.ui.Field; import com.vaadin.ui.Form; import com.vaadin.util.ReflectTools; @@ -62,8 +62,8 @@ public class FieldGroup implements Serializable { private boolean enabled = true; private boolean readOnly = false; - private HashMap> propertyIdToField = new HashMap>(); - private LinkedHashMap, Object> fieldToPropertyId = new LinkedHashMap, Object>(); + private HashMap> propertyIdToField = new HashMap>(); + private LinkedHashMap, Object> fieldToPropertyId = new LinkedHashMap, Object>(); private List commitHandlers = new ArrayList(); /** @@ -101,7 +101,7 @@ public class FieldGroup implements Serializable { public void setItemDataSource(Item itemDataSource) { this.itemDataSource = itemDataSource; - for (Field f : fieldToPropertyId.keySet()) { + for (LegacyField f : fieldToPropertyId.keySet()) { bind(f, fieldToPropertyId.get(f)); } } @@ -126,7 +126,7 @@ public class FieldGroup implements Serializable { * * @see #setBuffered(boolean) for more details on buffered mode * - * @see Field#isBuffered() + * @see LegacyField#isBuffered() * @return true if buffered mode is on, false otherwise * */ @@ -145,7 +145,7 @@ public class FieldGroup implements Serializable { * The default is to use buffered mode. *

* - * @see Field#setBuffered(boolean) + * @see LegacyField#setBuffered(boolean) * @param buffered * true to turn on buffered mode, false otherwise */ @@ -155,7 +155,7 @@ public class FieldGroup implements Serializable { } this.buffered = buffered; - for (Field field : getFields()) { + for (LegacyField field : getFields()) { field.setBuffered(buffered); } } @@ -181,7 +181,7 @@ public class FieldGroup implements Serializable { */ public void setEnabled(boolean fieldsEnabled) { enabled = fieldsEnabled; - for (Field field : getFields()) { + for (LegacyField field : getFields()) { field.setEnabled(fieldsEnabled); } } @@ -211,7 +211,7 @@ public class FieldGroup implements Serializable { */ public void setReadOnly(boolean fieldsReadOnly) { readOnly = fieldsReadOnly; - for (Field field : getFields()) { + for (LegacyField field : getFields()) { if (field.getPropertyDataSource() == null || !field.getPropertyDataSource().isReadOnly()) { field.setReadOnly(fieldsReadOnly); @@ -229,7 +229,7 @@ public class FieldGroup implements Serializable { * * @return A collection with all bound Fields */ - public Collection> getFields() { + public Collection> getFields() { return fieldToPropertyId.keySet(); } @@ -249,7 +249,7 @@ public class FieldGroup implements Serializable { * If the field is null or the property id is already bound to * another field by this field binder */ - public void bind(Field field, Object propertyId) throws BindException { + public void bind(LegacyField field, Object propertyId) throws BindException { throwIfFieldIsNull(field, propertyId); throwIfPropertyIdAlreadyBound(field, propertyId); @@ -287,7 +287,7 @@ public class FieldGroup implements Serializable { return new TransactionalPropertyWrapper(itemProperty); } - private void throwIfFieldIsNull(Field field, Object propertyId) { + private void throwIfFieldIsNull(LegacyField field, Object propertyId) { if (field == null) { throw new BindException( String.format( @@ -296,7 +296,7 @@ public class FieldGroup implements Serializable { } } - private void throwIfPropertyIdAlreadyBound(Field field, Object propertyId) { + private void throwIfPropertyIdAlreadyBound(LegacyField field, Object propertyId) { if (propertyIdToField.containsKey(propertyId) && propertyIdToField.get(propertyId) != field) { throw new BindException("Property id " + propertyId @@ -342,7 +342,7 @@ public class FieldGroup implements Serializable { * If the field is not bound by this field binder or not bound * to the correct property id */ - public void unbind(Field field) throws BindException { + public void unbind(LegacyField field) throws BindException { Object propertyId = fieldToPropertyId.get(field); if (propertyId == null) { throw new BindException( @@ -378,7 +378,7 @@ public class FieldGroup implements Serializable { * @param field * The field to update */ - protected void configureField(Field field) { + protected void configureField(LegacyField field) { field.setBuffered(isBuffered()); field.setEnabled(isEnabled()); @@ -478,7 +478,7 @@ public class FieldGroup implements Serializable { try { firePreCommitEvent(); - Map, InvalidValueException> invalidValueExceptions = commitFields(); + Map, InvalidValueException> invalidValueExceptions = commitFields(); if (invalidValueExceptions.isEmpty()) { firePostCommitEvent(); @@ -501,10 +501,10 @@ public class FieldGroup implements Serializable { * @return a propertyId to validation exception map which is empty if all * commits succeeded */ - private Map, InvalidValueException> commitFields() { - Map, InvalidValueException> invalidValueExceptions = new HashMap, InvalidValueException>(); + private Map, InvalidValueException> commitFields() { + Map, InvalidValueException> invalidValueExceptions = new HashMap, InvalidValueException>(); - for (Field f : fieldToPropertyId.keySet()) { + for (LegacyField f : fieldToPropertyId.keySet()) { try { f.commit(); } catch (InvalidValueException e) { @@ -523,7 +523,7 @@ public class FieldGroup implements Serializable { */ public static class FieldGroupInvalidValueException extends InvalidValueException { - private Map, InvalidValueException> invalidValueExceptions; + private Map, InvalidValueException> invalidValueExceptions; /** * Constructs a new exception with the specified validation exceptions. @@ -532,7 +532,7 @@ public class FieldGroup implements Serializable { * a property id to exception map */ public FieldGroupInvalidValueException( - Map, InvalidValueException> invalidValueExceptions) { + Map, InvalidValueException> invalidValueExceptions) { super(null, invalidValueExceptions.values().toArray( new InvalidValueException[invalidValueExceptions.size()])); this.invalidValueExceptions = invalidValueExceptions; @@ -544,13 +544,13 @@ public class FieldGroup implements Serializable { * * @return a map with all the invalid value exceptions */ - public Map, InvalidValueException> getInvalidFields() { + public Map, InvalidValueException> getInvalidFields() { return invalidValueExceptions; } } private void startTransactions() throws CommitException { - for (Field f : fieldToPropertyId.keySet()) { + for (LegacyField f : fieldToPropertyId.keySet()) { Property.Transactional property = (Property.Transactional) f .getPropertyDataSource(); if (property == null) { @@ -563,13 +563,13 @@ public class FieldGroup implements Serializable { } private void commitTransactions() { - for (Field f : fieldToPropertyId.keySet()) { + for (LegacyField f : fieldToPropertyId.keySet()) { ((Property.Transactional) f.getPropertyDataSource()).commit(); } } private void rollbackTransactions() { - for (Field f : fieldToPropertyId.keySet()) { + for (LegacyField f : fieldToPropertyId.keySet()) { try { ((Property.Transactional) f.getPropertyDataSource()) .rollback(); @@ -616,7 +616,7 @@ public class FieldGroup implements Serializable { * */ public void discard() { - for (Field f : fieldToPropertyId.keySet()) { + for (LegacyField f : fieldToPropertyId.keySet()) { try { f.discard(); } catch (Exception e) { @@ -635,7 +635,7 @@ public class FieldGroup implements Serializable { * @return The field that is bound to the property id or null if no field is * bound to that property id */ - public Field getField(Object propertyId) { + public LegacyField getField(Object propertyId) { return propertyIdToField.get(propertyId); } @@ -647,7 +647,7 @@ public class FieldGroup implements Serializable { * @return The property id that is bound to the field or null if the field * is not bound to any property id by this FieldBinder */ - public Object getPropertyId(Field field) { + public Object getPropertyId(LegacyField field) { return fieldToPropertyId.get(field); } @@ -751,14 +751,14 @@ public class FieldGroup implements Serializable { /** * Checks the validity of the bound fields. *

- * Call the {@link Field#validate()} for the fields to get the individual + * Call the {@link LegacyField#validate()} for the fields to get the individual * error messages. * * @return true if all bound fields are valid, false otherwise. */ public boolean isValid() { try { - for (Field field : getFields()) { + for (LegacyField field : getFields()) { field.validate(); } return true; @@ -773,7 +773,7 @@ public class FieldGroup implements Serializable { * @return true if at least one field has been modified, false otherwise */ public boolean isModified() { - for (Field field : getFields()) { + for (LegacyField field : getFields()) { if (field.isModified()) { return true; } @@ -807,7 +807,7 @@ public class FieldGroup implements Serializable { * Binds member fields found in the given object. *

* This method processes all (Java) member fields whose type extends - * {@link Field} and that can be mapped to a property id. Property id + * {@link LegacyField} and that can be mapped to a property id. Property id * mapping is done based on the field name or on a @{@link PropertyId} * annotation on the field. All non-null fields for which a property id can * be determined are bound to the property id. @@ -847,7 +847,7 @@ public class FieldGroup implements Serializable { * that have not been initialized. *

* This method processes all (Java) member fields whose type extends - * {@link Field} and that can be mapped to a property id. Property ids are + * {@link LegacyField} and that can be mapped to a property id. Property ids are * searched in the following order: @{@link PropertyId} annotations, exact * field name matches and the case-insensitive matching that ignores * underscores. Fields that are not initialized (null) are built using the @@ -892,7 +892,7 @@ public class FieldGroup implements Serializable { * member fields that have not been initialized. *

* This method processes all (Java) member fields whose type extends - * {@link Field} and that can be mapped to a property id. Property ids are + * {@link LegacyField} and that can be mapped to a property id. Property ids are * searched in the following order: @{@link PropertyId} annotations, exact * field name matches and the case-insensitive matching that ignores * underscores. Fields that are not initialized (null) are built using the @@ -912,7 +912,7 @@ public class FieldGroup implements Serializable { for (java.lang.reflect.Field memberField : getFieldsInDeclareOrder(objectClass)) { - if (!Field.class.isAssignableFrom(memberField.getType())) { + if (!LegacyField.class.isAssignableFrom(memberField.getType())) { // Process next field continue; } @@ -920,7 +920,7 @@ public class FieldGroup implements Serializable { PropertyId propertyIdAnnotation = memberField .getAnnotation(PropertyId.class); - Class fieldType = (Class) memberField + Class fieldType = (Class) memberField .getType(); Object propertyId = null; @@ -950,11 +950,11 @@ public class FieldGroup implements Serializable { continue; } - Field field; + LegacyField field; try { // Get the field from the object - field = (Field) ReflectTools.getJavaFieldValue( - objectWithMemberFields, memberField, Field.class); + field = (LegacyField) ReflectTools.getJavaFieldValue( + objectWithMemberFields, memberField, LegacyField.class); } catch (Exception e) { // If we cannot determine the value, just skip the field and try // the next one @@ -972,7 +972,7 @@ public class FieldGroup implements Serializable { .createCaptionByPropertyId(propertyId); } - // Create the component (Field) + // Create the component (LegacyField) field = build(caption, propertyType, fieldType); // Store it in the field @@ -1089,12 +1089,12 @@ public class FieldGroup implements Serializable { * @return a map with all the invalid value exceptions. Can be empty but * not null */ - public Map, InvalidValueException> getInvalidFields() { + public Map, InvalidValueException> getInvalidFields() { if (getCause() instanceof FieldGroupInvalidValueException) { return ((FieldGroupInvalidValueException) getCause()) .getInvalidFields(); } - return new HashMap, InvalidValueException>(); + return new HashMap, InvalidValueException>(); } /** @@ -1144,7 +1144,7 @@ public class FieldGroup implements Serializable { * If there is a problem while building or binding * @return The created and bound field */ - public Field buildAndBind(Object propertyId) throws BindException { + public LegacyField buildAndBind(Object propertyId) throws BindException { String caption = DefaultFieldFactory .createCaptionByPropertyId(propertyId); return buildAndBind(caption, propertyId); @@ -1161,11 +1161,11 @@ public class FieldGroup implements Serializable { * finder. * @throws BindException * If there is a problem while building or binding - * @return The created and bound field. Can be any type of {@link Field}. + * @return The created and bound field. Can be any type of {@link LegacyField}. */ - public Field buildAndBind(String caption, Object propertyId) + public LegacyField buildAndBind(String caption, Object propertyId) throws BindException { - return buildAndBind(caption, propertyId, Field.class); + return buildAndBind(caption, propertyId, LegacyField.class); } /** @@ -1179,10 +1179,10 @@ public class FieldGroup implements Serializable { * finder. * @throws BindException * If the field could not be created - * @return The created and bound field. Can be any type of {@link Field}. + * @return The created and bound field. Can be any type of {@link LegacyField}. */ - public T buildAndBind(String caption, Object propertyId, + public T buildAndBind(String caption, Object propertyId, Class fieldType) throws BindException { Class type = getPropertyType(propertyId); @@ -1196,8 +1196,8 @@ public class FieldGroup implements Serializable { * Creates a field based on the given data type. *

* The data type is the type that we want to edit using the field. The field - * type is the type of field we want to create, can be {@link Field} if any - * Field is good. + * type is the type of field we want to create, can be {@link LegacyField} if any + * LegacyField is good. *

* * @param caption @@ -1206,11 +1206,11 @@ public class FieldGroup implements Serializable { * The data model type that we want to edit using the field * @param fieldType * The type of field that we want to create - * @return A Field capable of editing the given type + * @return A LegacyField capable of editing the given type * @throws BindException * If the field could not be created */ - protected T build(String caption, Class dataType, + protected T build(String caption, Class dataType, Class fieldType) throws BindException { T field = getFieldFactory().createField(dataType, fieldType); if (field == null) { @@ -1224,7 +1224,7 @@ public class FieldGroup implements Serializable { } /** - * Returns an array containing Field objects reflecting all the fields of + * Returns an array containing LegacyField objects reflecting all the fields of * the class or interface represented by this Class object. The elements in * the array returned are sorted in declare order from sub class to super * class. @@ -1252,9 +1252,9 @@ public class FieldGroup implements Serializable { * @since 7.4 */ public void clear() { - for (Field f : getFields()) { - if (f instanceof AbstractField) { - ((AbstractField) f).clear(); + for (LegacyField f : getFields()) { + if (f instanceof LegacyAbstractField) { + ((LegacyAbstractField) f).clear(); } } diff --git a/server/src/main/java/com/vaadin/data/fieldgroup/FieldGroupFieldFactory.java b/server/src/main/java/com/vaadin/data/fieldgroup/FieldGroupFieldFactory.java index 4aad08ba8d..fb2a579093 100644 --- a/server/src/main/java/com/vaadin/data/fieldgroup/FieldGroupFieldFactory.java +++ b/server/src/main/java/com/vaadin/data/fieldgroup/FieldGroupFieldFactory.java @@ -17,10 +17,10 @@ package com.vaadin.data.fieldgroup; import java.io.Serializable; -import com.vaadin.ui.Field; +import com.vaadin.legacy.ui.LegacyField; /** - * Factory interface for creating new Field-instances based on the data type + * Factory interface for creating new LegacyField-instances based on the data type * that should be edited. * * @author Vaadin Ltd. @@ -33,10 +33,10 @@ public interface FieldGroupFieldFactory extends Serializable { * @param dataType * The type that we want to edit using the field * @param fieldType - * The type of field we want to create. If set to {@link Field} + * The type of field we want to create. If set to {@link LegacyField} * then any type of field is accepted * @return A field that can be assigned to the given fieldType and that is * capable of editing the given type of data */ - T createField(Class dataType, Class fieldType); + T createField(Class dataType, Class fieldType); } diff --git a/server/src/main/java/com/vaadin/data/fieldgroup/PropertyId.java b/server/src/main/java/com/vaadin/data/fieldgroup/PropertyId.java index e7fe50305e..c8be515c6d 100644 --- a/server/src/main/java/com/vaadin/data/fieldgroup/PropertyId.java +++ b/server/src/main/java/com/vaadin/data/fieldgroup/PropertyId.java @@ -21,13 +21,13 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * Defines the custom property name to be bound to a {@link Field} using + * Defines the custom property name to be bound to a {@link LegacyField} using * {@link FieldGroup} or {@link BeanFieldGroup}. *

* The automatic data binding in FieldGroup and BeanFieldGroup relies on a * naming convention by default: properties of an item are bound to similarly * named field components in given a editor object. If you want to map a - * property with a different name (ID) to a {@link com.vaadin.client.ui.Field}, + * property with a different name (ID) to a {@link com.vaadin.client.ui.LegacyField}, * you can use this annotation for the member fields, with the name (ID) of the * desired property as the parameter. *

diff --git a/server/src/main/java/com/vaadin/event/FieldEvents.java b/server/src/main/java/com/vaadin/event/FieldEvents.java index 364ac76ffd..c6109a79d2 100644 --- a/server/src/main/java/com/vaadin/event/FieldEvents.java +++ b/server/src/main/java/com/vaadin/event/FieldEvents.java @@ -19,17 +19,17 @@ package com.vaadin.event; import java.io.Serializable; import java.lang.reflect.Method; +import com.vaadin.legacy.ui.LegacyField; +import com.vaadin.legacy.ui.LegacyField.ValueChangeEvent; import com.vaadin.shared.EventId; import com.vaadin.shared.communication.FieldRpc.FocusAndBlurServerRpc; import com.vaadin.ui.Component; import com.vaadin.ui.Component.Event; -import com.vaadin.ui.Field; -import com.vaadin.ui.Field.ValueChangeEvent; import com.vaadin.ui.TextField; import com.vaadin.util.ReflectTools; /** - * Interface that serves as a wrapper for {@link Field} related events. + * Interface that serves as a wrapper for {@link LegacyField} related events. */ public interface FieldEvents { @@ -53,7 +53,7 @@ public interface FieldEvents { public interface FocusNotifier extends Serializable { /** * Adds a FocusListener to the Component which gets fired - * when a Field receives keyboard focus. + * when a LegacyField receives keyboard focus. * * @param listener * @see FocusListener @@ -105,7 +105,7 @@ public interface FieldEvents { public interface BlurNotifier extends Serializable { /** * Adds a BlurListener to the Component which gets fired - * when a Field loses keyboard focus. + * when a LegacyField loses keyboard focus. * * @param listener * @see BlurListener @@ -139,7 +139,7 @@ public interface FieldEvents { /** * FocusEvent class for holding additional event information. - * Fired when a Field receives keyboard focus. + * Fired when a LegacyField receives keyboard focus. * * @since 6.2 */ @@ -158,7 +158,7 @@ public interface FieldEvents { /** * FocusListener interface for listening for - * FocusEvent fired by a Field. + * FocusEvent fired by a LegacyField. * * @see FocusEvent * @since 6.2 @@ -179,7 +179,7 @@ public interface FieldEvents { /** * BlurEvent class for holding additional event information. - * Fired when a Field loses keyboard focus. + * Fired when a LegacyField loses keyboard focus. * * @since 6.2 */ @@ -198,7 +198,7 @@ public interface FieldEvents { /** * BlurListener interface for listening for - * BlurEvent fired by a Field. + * BlurEvent fired by a LegacyField. * * @see BlurEvent * @since 6.2 @@ -281,7 +281,7 @@ public interface FieldEvents { } /** - * An interface implemented by a {@link Field} supporting + * An interface implemented by a {@link LegacyField} supporting * {@link TextChangeEvent}s. An example a {@link TextField} supports * {@link TextChangeListener}s. */ diff --git a/server/src/main/java/com/vaadin/legacy/ui/LegacyAbstractField.java b/server/src/main/java/com/vaadin/legacy/ui/LegacyAbstractField.java new file mode 100644 index 0000000000..d1b013a64a --- /dev/null +++ b/server/src/main/java/com/vaadin/legacy/ui/LegacyAbstractField.java @@ -0,0 +1,1863 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.vaadin.legacy.ui; + +import java.io.Serializable; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Locale; +import java.util.logging.Logger; + +import org.jsoup.nodes.Attributes; +import org.jsoup.nodes.Element; + +import com.vaadin.data.Buffered; +import com.vaadin.data.Property; +import com.vaadin.data.Validatable; +import com.vaadin.data.Validator; +import com.vaadin.data.Validator.InvalidValueException; +import com.vaadin.data.util.LegacyPropertyHelper; +import com.vaadin.data.util.converter.Converter; +import com.vaadin.data.util.converter.Converter.ConversionException; +import com.vaadin.data.util.converter.ConverterUtil; +import com.vaadin.event.Action; +import com.vaadin.event.ShortcutAction; +import com.vaadin.event.ShortcutListener; +import com.vaadin.server.AbstractErrorMessage; +import com.vaadin.server.CompositeErrorMessage; +import com.vaadin.server.ErrorMessage; +import com.vaadin.shared.AbstractFieldState; +import com.vaadin.shared.util.SharedUtil; +import com.vaadin.ui.AbstractComponent; +import com.vaadin.ui.Component; +import com.vaadin.ui.declarative.DesignAttributeHandler; +import com.vaadin.ui.declarative.DesignContext; + +/** + *

+ * Abstract field component for implementing buffered property editors. The + * field may hold an internal value, or it may be connected to any data source + * that implements the {@link com.vaadin.data.Property}interface. + * LegacyAbstractField implements that interface itself, too, so + * accessing the Property value represented by it is straightforward. + *

+ * + *

+ * LegacyAbstractField also provides the {@link com.vaadin.data.Buffered} interface + * for buffering the data source value. By default the LegacyField is in write + * through-mode and {@link #setWriteThrough(boolean)}should be called to enable + * buffering. + *

+ * + *

+ * The class also supports {@link com.vaadin.data.Validator validators} to make + * sure the value contained in the field is valid. + *

+ * + * @author Vaadin Ltd. + * @since 3.0 + */ +@SuppressWarnings("serial") +public abstract class LegacyAbstractField extends AbstractComponent implements + LegacyField, Property.ReadOnlyStatusChangeListener, + Property.ReadOnlyStatusChangeNotifier, Action.ShortcutNotifier { + + /* Private members */ + + /** + * Value of the abstract field. + */ + private T value; + + /** + * A converter used to convert from the data model type to the field type + * and vice versa. + */ + private Converter converter = null; + /** + * Connected data-source. + */ + private Property dataSource = null; + + /** + * The list of validators. + */ + private LinkedList validators = null; + + /** + * True if field is in buffered mode, false otherwise + */ + private boolean buffered; + + /** + * Flag to indicate that the field is currently committing its value to the + * datasource. + */ + private boolean committingValueToDataSource = false; + + /** + * Current source exception. + */ + private Buffered.SourceException currentBufferedSourceException = null; + + /** + * Are the invalid values allowed in fields ? + */ + private boolean invalidAllowed = true; + + /** + * Are the invalid values committed ? + */ + private boolean invalidCommitted = false; + + /** + * The error message for the exception that is thrown when the field is + * required but empty. + */ + private String requiredError = ""; + + /** + * The error message that is shown when the field value cannot be converted. + */ + private String conversionError = "Could not convert value to {0}"; + + /** + * Is automatic validation enabled. + */ + private boolean validationVisible = true; + + private boolean valueWasModifiedByDataSourceDuringCommit; + + /** + * Whether this field is currently registered as listening to events from + * its data source. + * + * @see #setPropertyDataSource(Property) + * @see #addPropertyListeners() + * @see #removePropertyListeners() + */ + private boolean isListeningToPropertyEvents = false; + + /** + * The locale used when setting the value. + */ + private Locale valueLocale = null; + + /* Component basics */ + + /* + * Paints the field. Don't add a JavaDoc comment here, we use the default + * documentation from the implemented interface. + */ + + /** + * Returns true if the error indicator be hidden when painting the component + * even when there are errors. + * + * This is a mostly internal method, but can be overridden in subclasses + * e.g. if the error indicator should also be shown for empty fields in some + * cases. + * + * @return true to hide the error indicator, false to use the normal logic + * to show it when there are errors + */ + protected boolean shouldHideErrors() { + // getErrorMessage() can still return something else than null based on + // validation etc. + return isRequired() && isEmpty() && getComponentError() == null; + } + + /** + * Returns the type of the LegacyField. The methods getValue and + * setValue must be compatible with this type: one must be able + * to safely cast the value returned from getValue to the given + * type and pass any variable assignable to this type as an argument to + * setValue. + * + * @return the type of the LegacyField + */ + @Override + public abstract Class getType(); + + /** + * The abstract field is read only also if the data source is in read only + * mode. + */ + @Override + public boolean isReadOnly() { + return super.isReadOnly() + || (dataSource != null && dataSource.isReadOnly()); + } + + /** + * Changes the readonly state and throw read-only status change events. + * + * @see com.vaadin.ui.Component#setReadOnly(boolean) + */ + @Override + public void setReadOnly(boolean readOnly) { + super.setReadOnly(readOnly); + fireReadOnlyStatusChange(); + } + + /** + * Tests if the invalid data is committed to datasource. + * + * @see com.vaadin.data.BufferedValidatable#isInvalidCommitted() + */ + @Override + public boolean isInvalidCommitted() { + return invalidCommitted; + } + + /** + * Sets if the invalid data should be committed to datasource. + * + * @see com.vaadin.data.BufferedValidatable#setInvalidCommitted(boolean) + */ + @Override + public void setInvalidCommitted(boolean isCommitted) { + invalidCommitted = isCommitted; + } + + /* + * Saves the current value to the data source Don't add a JavaDoc comment + * here, we use the default documentation from the implemented interface. + */ + @Override + public void commit() throws Buffered.SourceException, + InvalidValueException { + if (dataSource != null && !dataSource.isReadOnly()) { + if ((isInvalidCommitted() || isValid())) { + try { + + // Commits the value to datasource. + valueWasModifiedByDataSourceDuringCommit = false; + committingValueToDataSource = true; + getPropertyDataSource().setValue(getConvertedValue()); + } catch (final Throwable e) { + + // Sets the buffering state. + SourceException sourceException = new Buffered.SourceException( + this, e); + setCurrentBufferedSourceException(sourceException); + + // Throws the source exception. + throw sourceException; + } finally { + committingValueToDataSource = false; + } + } else { + /* + * An invalid value and we don't allow them, throw the exception + */ + validate(); + } + } + + // The abstract field is not modified anymore + if (isModified()) { + setModified(false); + } + + // If successful, remove set the buffering state to be ok + if (getCurrentBufferedSourceException() != null) { + setCurrentBufferedSourceException(null); + } + + if (valueWasModifiedByDataSourceDuringCommit) { + valueWasModifiedByDataSourceDuringCommit = false; + fireValueChange(false); + } + + } + + /* + * Updates the value from the data source. Don't add a JavaDoc comment here, + * we use the default documentation from the implemented interface. + */ + @Override + public void discard() throws Buffered.SourceException { + updateValueFromDataSource(); + } + + /** + * Gets the value from the data source. This is only here because of clarity + * in the code that handles both the data model value and the field value. + * + * @return The value of the property data source + */ + private Object getDataSourceValue() { + return dataSource.getValue(); + } + + /** + * Returns the field value. This is always identical to {@link #getValue()} + * and only here because of clarity in the code that handles both the data + * model value and the field value. + * + * @return The value of the field + */ + private T getFieldValue() { + // Give the value from abstract buffers if the field if possible + if (dataSource == null || isBuffered() || isModified()) { + return getInternalValue(); + } + + // There is no buffered value so use whatever the data model provides + return convertFromModel(getDataSourceValue()); + } + + /* + * Has the field been modified since the last commit()? Don't add a JavaDoc + * comment here, we use the default documentation from the implemented + * interface. + */ + @Override + public boolean isModified() { + return getState(false).modified; + } + + private void setModified(boolean modified) { + getState().modified = modified; + } + + /** + * Sets the buffered mode of this LegacyField. + *

+ * When the field is in buffered mode, changes will not be committed to the + * property data source until {@link #commit()} is called. + *

+ *

+ * Setting buffered mode from true to false will commit any pending changes. + *

+ *

+ * + *

+ * + * @since 7.0.0 + * @param buffered + * true if buffered mode should be turned on, false otherwise + */ + @Override + public void setBuffered(boolean buffered) { + if (this.buffered == buffered) { + return; + } + this.buffered = buffered; + if (!buffered) { + commit(); + } + } + + /** + * Checks the buffered mode of this LegacyField. + * + * @return true if buffered mode is on, false otherwise + */ + @Override + public boolean isBuffered() { + return buffered; + } + + /** + * Returns a string representation of this object. The returned string + * representation depends on if the legacy Property toString mode is enabled + * or disabled. + *

+ * If legacy Property toString mode is enabled, returns the value of this + * LegacyField converted to a String. + *

+ *

+ * If legacy Property toString mode is disabled, the string representation + * has no special meaning + *

+ * + * @see LegacyPropertyHelper#isLegacyToStringEnabled() + * + * @return A string representation of the value value stored in the Property + * or a string representation of the Property object. + * @deprecated As of 7.0. Use {@link #getValue()} to get the value of the + * field, {@link #getConvertedValue()} to get the field value + * converted to the data model type or + * {@link #getPropertyDataSource()} .getValue() to get the value + * of the data source. + */ + @Deprecated + @Override + public String toString() { + if (!LegacyPropertyHelper.isLegacyToStringEnabled()) { + return super.toString(); + } else { + return LegacyPropertyHelper.legacyPropertyToString(this); + } + } + + /* Property interface implementation */ + + /** + * Gets the current value of the field. + * + *

+ * This is the visible, modified and possible invalid value the user have + * entered to the field. + *

+ * + *

+ * Note that the object returned is compatible with getType(). For example, + * if the type is String, this returns Strings even when the underlying + * datasource is of some other type. In order to access the converted value, + * use {@link #getConvertedValue()} and to access the value of the property + * data source, use {@link Property#getValue()} for the property data + * source. + *

+ * + *

+ * Since Vaadin 7.0, no implicit conversions between other data types and + * String are performed, but a converter is used if set. + *

+ * + * @return the current value of the field. + */ + @Override + public T getValue() { + return getFieldValue(); + } + + /** + * Sets the value of the field. + * + * @param newFieldValue + * the New value of the field. + * @throws Property.ReadOnlyException + */ + @Override + public void setValue(T newFieldValue) throws Property.ReadOnlyException, + Converter.ConversionException { + setValue(newFieldValue, false); + } + + /** + * Sets the value of the field. + * + * @param newFieldValue + * the New value of the field. + * @param repaintIsNotNeeded + * True iff caller is sure that repaint is not needed. + * @throws Property.ReadOnlyException + * @throws Converter.ConversionException + * @throws InvalidValueException + */ + protected void setValue(T newFieldValue, boolean repaintIsNotNeeded) { + setValue(newFieldValue, repaintIsNotNeeded, false); + } + + /** + * Sets the value of the field. + * + * @since 7.5.7 + * @param newFieldValue + * the New value of the field. + * @param repaintIsNotNeeded + * True iff caller is sure that repaint is not needed. + * @param ignoreReadOnly + * True iff if the read-only check should be ignored + * @throws Property.ReadOnlyException + * @throws Converter.ConversionException + * @throws InvalidValueException + */ + protected void setValue(T newFieldValue, boolean repaintIsNotNeeded, + boolean ignoreReadOnly) throws Property.ReadOnlyException, + Converter.ConversionException, InvalidValueException { + + if (!SharedUtil.equals(newFieldValue, getInternalValue())) { + + // Read only fields can not be changed + if (!ignoreReadOnly && isReadOnly()) { + throw new Property.ReadOnlyException(); + } + try { + T doubleConvertedFieldValue = convertFromModel(convertToModel( + newFieldValue)); + if (!SharedUtil + .equals(newFieldValue, doubleConvertedFieldValue)) { + newFieldValue = doubleConvertedFieldValue; + repaintIsNotNeeded = false; + } + } catch (Throwable t) { + // Ignore exceptions in the conversion at this stage. Any + // conversion error will be handled later by validate(). + } + + // Repaint is needed even when the client thinks that it knows the + // new state if validity of the component may change + if (repaintIsNotNeeded + && (isRequired() || hasValidators() + || getConverter() != null)) { + repaintIsNotNeeded = false; + } + + if (!isInvalidAllowed()) { + /* + * If invalid values are not allowed the value must be validated + * before it is set. If validation fails, the + * InvalidValueException is thrown and the internal value is not + * updated. + */ + validate(newFieldValue); + } + + // Changes the value + setInternalValue(newFieldValue); + setModified(dataSource != null); + + valueWasModifiedByDataSourceDuringCommit = false; + // In not buffering, try to commit + if (!isBuffered() && dataSource != null + && (isInvalidCommitted() || isValid())) { + try { + + // Commits the value to datasource + committingValueToDataSource = true; + getPropertyDataSource().setValue( + convertToModel(newFieldValue)); + + // The buffer is now unmodified + setModified(false); + + } catch (final Throwable e) { + + // Sets the buffering state + currentBufferedSourceException = new Buffered.SourceException( + this, e); + markAsDirty(); + + // Throws the source exception + throw currentBufferedSourceException; + } finally { + committingValueToDataSource = false; + } + } + + // If successful, remove set the buffering state to be ok + if (getCurrentBufferedSourceException() != null) { + setCurrentBufferedSourceException(null); + } + + if (valueWasModifiedByDataSourceDuringCommit) { + /* + * Value was modified by datasource. Force repaint even if + * repaint was not requested. + */ + valueWasModifiedByDataSourceDuringCommit = repaintIsNotNeeded = false; + } + + // Fires the value change + fireValueChange(repaintIsNotNeeded); + + } + } + + @Deprecated + static boolean equals(Object value1, Object value2) { + return SharedUtil.equals(value1, value2); + } + + /* External data source */ + + /** + * Gets the current data source of the field, if any. + * + * @return the current data source as a Property, or null if + * none defined. + */ + @Override + public Property getPropertyDataSource() { + return dataSource; + } + + /** + *

+ * Sets the specified Property as the data source for the field. All + * uncommitted changes are replaced with a value from the new data source. + *

+ * + *

+ * If the datasource has any validators, the same validators are added to + * the field. Because the default behavior of the field is to allow invalid + * values, but not to allow committing them, this only adds visual error + * messages to fields and do not allow committing them as long as the value + * is invalid. After the value is valid, the error message is not shown and + * the commit can be done normally. + *

+ * + *

+ * If the data source implements + * {@link com.vaadin.data.Property.ValueChangeNotifier} and/or + * {@link com.vaadin.data.Property.ReadOnlyStatusChangeNotifier}, the field + * registers itself as a listener and updates itself according to the events + * it receives. To avoid memory leaks caused by references to a field no + * longer in use, the listener registrations are removed on + * {@link LegacyAbstractField#detach() detach} and re-added on + * {@link LegacyAbstractField#attach() attach}. + *

+ * + *

+ * Note: before 6.5 we actually called discard() method in the beginning of + * the method. This was removed to simplify implementation, avoid excess + * calls to backing property and to avoid odd value change events that were + * previously fired (developer expects 0-1 value change events if this + * method is called). Some complex field implementations might now need to + * override this method to do housekeeping similar to discard(). + *

+ * + * @param newDataSource + * the new data source Property. + */ + @Override + public void setPropertyDataSource(Property newDataSource) { + + // Saves the old value + final Object oldValue = getInternalValue(); + + // Stop listening to the old data source + removePropertyListeners(); + + // Sets the new data source + dataSource = newDataSource; + getState().propertyReadOnly = dataSource == null ? false : dataSource + .isReadOnly(); + + // Check if the current converter is compatible. + if (newDataSource != null + && !ConverterUtil.canConverterPossiblyHandle(getConverter(), + getType(), newDataSource.getType())) { + // There is no converter set or there is no way the current + // converter can be compatible. + setConverter(newDataSource.getType()); + } + // Gets the value from source. This requires that a valid converter has + // been set. + try { + if (dataSource != null) { + T fieldValue = convertFromModel(getDataSourceValue()); + setInternalValue(fieldValue); + } + setModified(false); + if (getCurrentBufferedSourceException() != null) { + setCurrentBufferedSourceException(null); + } + } catch (final Throwable e) { + setCurrentBufferedSourceException(new Buffered.SourceException( + this, e)); + setModified(true); + throw getCurrentBufferedSourceException(); + } + + // Listen to new data source if possible + addPropertyListeners(); + + // Copy the validators from the data source + if (dataSource instanceof Validatable) { + final Collection validators = ((Validatable) dataSource) + .getValidators(); + if (validators != null) { + for (final Iterator i = validators.iterator(); i + .hasNext();) { + addValidator(i.next()); + } + } + } + + // Fires value change if the value has changed + T value = getInternalValue(); + if ((value != oldValue) + && ((value != null && !value.equals(oldValue)) + || value == null)) { + fireValueChange(false); + } + } + + /** + * Retrieves a converter for the field from the converter factory defined + * for the application. Clears the converter if no application reference is + * available or if the factory returns null. + * + * @param datamodelType + * The type of the data model that we want to be able to convert + * from + */ + public void setConverter(Class datamodelType) { + Converter c = (Converter) ConverterUtil.getConverter( + getType(), datamodelType, getSession()); + setConverter(c); + } + + /** + * Convert the given value from the data source type to the UI type. + * + * @param newValue + * The data source value to convert. + * @return The converted value that is compatible with the UI type or the + * original value if its type is compatible and no converter is set. + * @throws Converter.ConversionException + * if there is no converter and the type is not compatible with + * the data source type. + */ + private T convertFromModel(Object newValue) { + return convertFromModel(newValue, getLocale()); + } + + /** + * Convert the given value from the data source type to the UI type. + * + * @param newValue + * The data source value to convert. + * @return The converted value that is compatible with the UI type or the + * original value if its type is compatible and no converter is set. + * @throws Converter.ConversionException + * if there is no converter and the type is not compatible with + * the data source type. + */ + private T convertFromModel(Object newValue, Locale locale) { + return ConverterUtil.convertFromModel(newValue, getType(), + getConverter(), locale); + } + + /** + * Convert the given value from the UI type to the data source type. + * + * @param fieldValue + * The value to convert. Typically returned by + * {@link #getFieldValue()} + * @return The converted value that is compatible with the data source type. + * @throws Converter.ConversionException + * if there is no converter and the type is not compatible with + * the data source type. + */ + private Object convertToModel(T fieldValue) + throws Converter.ConversionException { + return convertToModel(fieldValue, getLocale()); + } + + /** + * Convert the given value from the UI type to the data source type. + * + * @param fieldValue + * The value to convert. Typically returned by + * {@link #getFieldValue()} + * @param locale + * The locale to use for the conversion + * @return The converted value that is compatible with the data source type. + * @throws Converter.ConversionException + * if there is no converter and the type is not compatible with + * the data source type. + */ + private Object convertToModel(T fieldValue, Locale locale) + throws Converter.ConversionException { + Class modelType = getModelType(); + try { + return ConverterUtil.convertToModel(fieldValue, + (Class) modelType, getConverter(), locale); + } catch (ConversionException e) { + throw new ConversionException(getConversionError(modelType, e), e); + } + } + + /** + * Retrieves the type of the currently used data model. If the field has no + * data source then the model type of the converter is used. + * + * @since 7.1 + * @return The type of the currently used data model or null if no data + * source or converter is set. + */ + protected Class getModelType() { + Property pd = getPropertyDataSource(); + if (pd != null) { + return pd.getType(); + } else if (getConverter() != null) { + return getConverter().getModelType(); + } + return null; + } + + /** + * Returns the conversion error with {0} replaced by the data source type + * and {1} replaced by the exception (localized) message. + * + * @since 7.1 + * @param dataSourceType + * the type of the data source + * @param e + * a conversion exception which can provide additional + * information + * @return The value conversion error string with parameters replaced. + */ + protected String getConversionError(Class dataSourceType, + ConversionException e) { + String conversionError = getConversionError(); + + if (conversionError != null) { + if (dataSourceType != null) { + conversionError = conversionError.replace("{0}", + dataSourceType.getSimpleName()); + } + if (e != null) { + conversionError = conversionError.replace("{1}", + e.getLocalizedMessage()); + } + } + return conversionError; + } + + /** + * Returns the current value (as returned by {@link #getValue()}) converted + * to the data source type. + *

+ * This returns the same as {@link LegacyAbstractField#getValue()} if no converter + * has been set. The value is not necessarily the same as the data source + * value e.g. if the field is in buffered mode and has been modified. + *

+ * + * @return The converted value that is compatible with the data source type + */ + public Object getConvertedValue() { + return convertToModel(getFieldValue()); + } + + /** + * Sets the value of the field using a value of the data source type. The + * value given is converted to the field type and then assigned to the + * field. This will update the property data source in the same way as when + * {@link #setValue(Object)} is called. + * + * @param value + * The value to set. Must be the same type as the data source. + */ + public void setConvertedValue(Object value) { + setValue(convertFromModel(value)); + } + + /* Validation */ + + /** + * Adds a new validator for the field's value. All validators added to a + * field are checked each time the its value changes. + * + * @param validator + * the new validator to be added. + */ + @Override + public void addValidator(Validator validator) { + if (validators == null) { + validators = new LinkedList(); + } + validators.add(validator); + markAsDirty(); + } + + /** + * Gets the validators of the field. + * + * @return An unmodifiable collection that holds all validators for the + * field. + */ + @Override + public Collection getValidators() { + if (validators == null) { + return Collections.emptyList(); + } else { + return Collections.unmodifiableCollection(validators); + } + } + + private boolean hasValidators() { + return validators != null && !validators.isEmpty(); + } + + /** + * Removes the validator from the field. + * + * @param validator + * the validator to remove. + */ + @Override + public void removeValidator(Validator validator) { + if (validators != null) { + validators.remove(validator); + } + markAsDirty(); + } + + /** + * Removes all validators from the field. + */ + @Override + public void removeAllValidators() { + if (validators != null) { + validators.clear(); + } + markAsDirty(); + } + + /** + * Tests the current value against registered validators if the field is not + * empty. If the field is empty it is considered valid if it is not required + * and invalid otherwise. Validators are never checked for empty fields. + * + * In most cases, {@link #validate()} should be used instead of + * {@link #isValid()} to also get the error message. + * + * @return true if all registered validators claim that the + * current value is valid or if the field is empty and not required, + * false otherwise. + */ + @Override + public boolean isValid() { + + try { + validate(); + return true; + } catch (InvalidValueException e) { + return false; + } + } + + /** + * Checks the validity of the LegacyField. + * + * A field is invalid if it is set as required (using + * {@link #setRequired(boolean)} and is empty, if one or several of the + * validators added to the field indicate it is invalid or if the value + * cannot be converted provided a converter has been set. + * + * The "required" validation is a built-in validation feature. If the field + * is required and empty this method throws an EmptyValueException with the + * error message set using {@link #setRequiredError(String)}. + * + * @see com.vaadin.data.Validatable#validate() + */ + @Override + public void validate() throws Validator.InvalidValueException { + + if (isRequired() && isEmpty()) { + throw new Validator.EmptyValueException(requiredError); + } + validate(getFieldValue()); + } + + /** + * Validates that the given value pass the validators for the field. + *

+ * This method does not check the requiredness of the field. + * + * @param fieldValue + * The value to check + * @throws Validator.InvalidValueException + * if one or several validators fail + */ + protected void validate(T fieldValue) + throws Validator.InvalidValueException { + + Object valueToValidate = fieldValue; + + // If there is a converter we start by converting the value as we want + // to validate the converted value + if (getConverter() != null) { + try { + valueToValidate = getConverter().convertToModel(fieldValue, + getModelType(), getLocale()); + } catch (ConversionException e) { + throw new InvalidValueException(getConversionError( + getConverter().getModelType(), e)); + } + } + + List validationExceptions = new ArrayList(); + if (validators != null) { + // Gets all the validation errors + for (Validator v : validators) { + try { + v.validate(valueToValidate); + } catch (final Validator.InvalidValueException e) { + validationExceptions.add(e); + } + } + } + + // If there were no errors + if (validationExceptions.isEmpty()) { + return; + } + + // If only one error occurred, throw it forwards + if (validationExceptions.size() == 1) { + throw validationExceptions.get(0); + } + + InvalidValueException[] exceptionArray = validationExceptions + .toArray(new InvalidValueException[validationExceptions + .size()]); + + // Create a composite validator and include all exceptions + throw new Validator.InvalidValueException(null, exceptionArray); + } + + /** + * Fields allow invalid values by default. In most cases this is wanted, + * because the field otherwise visually forget the user input immediately. + * + * @return true iff the invalid values are allowed. + * @see com.vaadin.data.Validatable#isInvalidAllowed() + */ + @Override + public boolean isInvalidAllowed() { + return invalidAllowed; + } + + /** + * Fields allow invalid values by default. In most cases this is wanted, + * because the field otherwise visually forget the user input immediately. + *

+ * In common setting where the user wants to assure the correctness of the + * datasource, but allow temporarily invalid contents in the field, the user + * should add the validators to datasource, that should not allow invalid + * values. The validators are automatically copied to the field when the + * datasource is set. + *

+ * + * @see com.vaadin.data.Validatable#setInvalidAllowed(boolean) + */ + @Override + public void setInvalidAllowed(boolean invalidAllowed) + throws UnsupportedOperationException { + this.invalidAllowed = invalidAllowed; + } + + /** + * Error messages shown by the fields are composites of the error message + * thrown by the superclasses (that is the component error message), + * validation errors and buffered source errors. + * + * @see com.vaadin.ui.AbstractComponent#getErrorMessage() + */ + @Override + public ErrorMessage getErrorMessage() { + + /* + * Check validation errors only if automatic validation is enabled. + * Empty, required fields will generate a validation error containing + * the requiredError string. For these fields the exclamation mark will + * be hidden but the error must still be sent to the client. + */ + Validator.InvalidValueException validationError = null; + if (isValidationVisible()) { + try { + validate(); + } catch (Validator.InvalidValueException e) { + if (!e.isInvisible()) { + validationError = e; + } + } + } + + // Check if there are any systems errors + final ErrorMessage superError = super.getErrorMessage(); + + // Return if there are no errors at all + if (superError == null && validationError == null + && getCurrentBufferedSourceException() == null) { + return null; + } + + // Throw combination of the error types + return new CompositeErrorMessage( + new ErrorMessage[] { + superError, + AbstractErrorMessage + .getErrorMessageForException(validationError), + AbstractErrorMessage + .getErrorMessageForException( + getCurrentBufferedSourceException()) }); + + } + + /* Value change events */ + + private static final Method VALUE_CHANGE_METHOD; + + static { + try { + VALUE_CHANGE_METHOD = Property.ValueChangeListener.class + .getDeclaredMethod("valueChange", + new Class[] { Property.ValueChangeEvent.class }); + } catch (final java.lang.NoSuchMethodException e) { + // This should never happen + throw new java.lang.RuntimeException( + "Internal error finding methods in LegacyAbstractField"); + } + } + + /* + * Adds a value change listener for the field. Don't add a JavaDoc comment + * here, we use the default documentation from the implemented interface. + */ + @Override + public void addValueChangeListener(Property.ValueChangeListener listener) { + addListener(LegacyAbstractField.ValueChangeEvent.class, listener, + VALUE_CHANGE_METHOD); + // ensure "automatic immediate handling" works + markAsDirty(); + } + + /** + * @deprecated As of 7.0, replaced by + * {@link #addValueChangeListener(com.vaadin.data.Property.ValueChangeListener)} + **/ + @Override + @Deprecated + public void addListener(Property.ValueChangeListener listener) { + addValueChangeListener(listener); + } + + /* + * Removes a value change listener from the field. Don't add a JavaDoc + * comment here, we use the default documentation from the implemented + * interface. + */ + @Override + public void removeValueChangeListener( + Property.ValueChangeListener listener) { + removeListener(LegacyAbstractField.ValueChangeEvent.class, listener, + VALUE_CHANGE_METHOD); + // ensure "automatic immediate handling" works + markAsDirty(); + } + + /** + * @deprecated As of 7.0, replaced by + * {@link #removeValueChangeListener(com.vaadin.data.Property.ValueChangeListener)} + **/ + @Override + @Deprecated + public void removeListener(Property.ValueChangeListener listener) { + removeValueChangeListener(listener); + } + + /** + * Emits the value change event. The value contained in the field is + * validated before the event is created. + */ + protected void fireValueChange(boolean repaintIsNotNeeded) { + fireEvent(new LegacyAbstractField.ValueChangeEvent(this)); + if (!repaintIsNotNeeded) { + markAsDirty(); + } + } + + /* Read-only status change events */ + + private static final Method READ_ONLY_STATUS_CHANGE_METHOD; + + static { + try { + READ_ONLY_STATUS_CHANGE_METHOD = Property.ReadOnlyStatusChangeListener.class + .getDeclaredMethod( + "readOnlyStatusChange", + new Class[] { + Property.ReadOnlyStatusChangeEvent.class }); + } catch (final java.lang.NoSuchMethodException e) { + // This should never happen + throw new java.lang.RuntimeException( + "Internal error finding methods in LegacyAbstractField"); + } + } + + /** + * React to read only status changes of the property by requesting a + * repaint. + * + * @see Property.ReadOnlyStatusChangeListener + */ + @Override + public void readOnlyStatusChange(Property.ReadOnlyStatusChangeEvent event) { + boolean readOnly = event.getProperty().isReadOnly(); + + boolean shouldFireChange = isReadOnly() != readOnly + || getState().propertyReadOnly != readOnly; + + getState().propertyReadOnly = readOnly; + + if (shouldFireChange) { + fireReadOnlyStatusChange(); + } + } + + /** + * An Event object specifying the Property whose read-only + * status has changed. + * + * @author Vaadin Ltd. + * @since 3.0 + */ + public static class ReadOnlyStatusChangeEvent extends Component.Event + implements Property.ReadOnlyStatusChangeEvent, Serializable { + + /** + * New instance of text change event. + * + * @param source + * the Source of the event. + */ + public ReadOnlyStatusChangeEvent(LegacyAbstractField source) { + super(source); + } + + /** + * Property where the event occurred. + * + * @return the Source of the event. + */ + @Override + public Property getProperty() { + return (Property) getSource(); + } + } + + /* + * Adds a read-only status change listener for the field. Don't add a + * JavaDoc comment here, we use the default documentation from the + * implemented interface. + */ + @Override + public void addReadOnlyStatusChangeListener( + Property.ReadOnlyStatusChangeListener listener) { + addListener(Property.ReadOnlyStatusChangeEvent.class, listener, + READ_ONLY_STATUS_CHANGE_METHOD); + } + + /** + * @deprecated As of 7.0, replaced by + * {@link #addReadOnlyStatusChangeListener(com.vaadin.data.Property.ReadOnlyStatusChangeListener)} + **/ + @Override + @Deprecated + public void addListener(Property.ReadOnlyStatusChangeListener listener) { + addReadOnlyStatusChangeListener(listener); + } + + /* + * Removes a read-only status change listener from the field. Don't add a + * JavaDoc comment here, we use the default documentation from the + * implemented interface. + */ + @Override + public void removeReadOnlyStatusChangeListener( + Property.ReadOnlyStatusChangeListener listener) { + removeListener(Property.ReadOnlyStatusChangeEvent.class, listener, + READ_ONLY_STATUS_CHANGE_METHOD); + } + + /** + * @deprecated As of 7.0, replaced by + * {@link #removeReadOnlyStatusChangeListener(com.vaadin.data.Property.ReadOnlyStatusChangeListener)} + **/ + @Override + @Deprecated + public void removeListener(Property.ReadOnlyStatusChangeListener listener) { + removeReadOnlyStatusChangeListener(listener); + } + + /** + * Emits the read-only status change event. The value contained in the field + * is validated before the event is created. + */ + protected void fireReadOnlyStatusChange() { + fireEvent(new LegacyAbstractField.ReadOnlyStatusChangeEvent(this)); + } + + /** + * This method listens to data source value changes and passes the changes + * forwards. + * + * Changes are not forwarded to the listeners of the field during internal + * operations of the field to avoid duplicate notifications. + * + * @param event + * the value change event telling the data source contents have + * changed. + */ + @Override + public void valueChange(Property.ValueChangeEvent event) { + if (!isBuffered()) { + if (committingValueToDataSource) { + boolean propertyNotifiesOfTheBufferedValue = SharedUtil.equals( + event.getProperty().getValue(), getInternalValue()); + if (!propertyNotifiesOfTheBufferedValue) { + /* + * Property (or chained property like PropertyFormatter) now + * reports different value than the one the field has just + * committed to it. In this case we respect the property + * value. + * + * Still, we don't fire value change yet, but instead + * postpone it until "commit" is done. See setValue(Object, + * boolean) and commit(). + */ + readValueFromProperty(event); + valueWasModifiedByDataSourceDuringCommit = true; + } + } else if (!isModified()) { + readValueFromProperty(event); + fireValueChange(false); + } + } + } + + private void readValueFromProperty(Property.ValueChangeEvent event) { + setInternalValue(convertFromModel(event.getProperty().getValue())); + } + + /** + * {@inheritDoc} + */ + @Override + public void focus() { + super.focus(); + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.ui.Component.Focusable#getTabIndex() + */ + @Override + public int getTabIndex() { + return getState(false).tabIndex; + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.ui.Component.Focusable#setTabIndex(int) + */ + @Override + public void setTabIndex(int tabIndex) { + getState().tabIndex = tabIndex; + } + + /** + * Returns the internal field value, which might not match the data source + * value e.g. if the field has been modified and is not in write-through + * mode. + * + * This method can be overridden by subclasses together with + * {@link #setInternalValue(Object)} to compute internal field value at + * runtime. When doing so, typically also {@link #isModified()} needs to be + * overridden and care should be taken in the management of the empty state + * and buffering support. + * + * @return internal field value + */ + protected T getInternalValue() { + return value; + } + + /** + * Sets the internal field value. This is purely used by LegacyAbstractField to + * change the internal LegacyField value. It does not trigger valuechange events. + * It can be overridden by the inheriting classes to update all dependent + * variables. + * + * Subclasses can also override {@link #getInternalValue()} if necessary. + * + * @param newValue + * the new value to be set. + */ + protected void setInternalValue(T newValue) { + value = newValue; + valueLocale = getLocale(); + if (validators != null && !validators.isEmpty()) { + markAsDirty(); + } + } + + /** + * Notifies the component that it is connected to an application. + * + * @see com.vaadin.ui.Component#attach() + */ + @Override + public void attach() { + super.attach(); + + localeMightHaveChanged(); + if (!isListeningToPropertyEvents) { + addPropertyListeners(); + if (!isModified() && !isBuffered()) { + // Update value from data source + updateValueFromDataSource(); + } + } + } + + @Override + public void setLocale(Locale locale) { + super.setLocale(locale); + localeMightHaveChanged(); + } + + private void localeMightHaveChanged() { + if (!SharedUtil.equals(valueLocale, getLocale())) { + // The locale HAS actually changed + + if (dataSource != null && !isModified()) { + // When we have a data source and the internal value is directly + // read from that we want to update the value + T newInternalValue = convertFromModel(getPropertyDataSource() + .getValue()); + if (!SharedUtil.equals(newInternalValue, getInternalValue())) { + setInternalValue(newInternalValue); + fireValueChange(false); + } + } else if (dataSource == null && converter != null) { + /* + * No data source but a converter has been set. The same issues + * as above but we cannot use propertyDataSource. Convert the + * current value back to a model value using the old locale and + * then convert back using the new locale. If this does not + * match the field value we need to set the converted value + * again. + */ + Object convertedValue = convertToModel(getInternalValue(), + valueLocale); + T newinternalValue = convertFromModel(convertedValue); + if (!SharedUtil.equals(getInternalValue(), newinternalValue)) { + setInternalValue(newinternalValue); + fireValueChange(false); + } + } + } + } + + @Override + public void detach() { + super.detach(); + // Stop listening to data source events on detach to avoid a potential + // memory leak. See #6155. + removePropertyListeners(); + } + + /** + * Is this field required. Required fields must filled by the user. + * + * If the field is required, it is visually indicated in the user interface. + * Furthermore, setting field to be required implicitly adds "non-empty" + * validator and thus isValid() == false or any isEmpty() fields. In those + * cases validation errors are not painted as it is obvious that the user + * must fill in the required fields. + * + * On the other hand, for the non-required fields isValid() == true if the + * field isEmpty() regardless of any attached validators. + * + * + * @return true if the field is required, otherwise + * false. + */ + @Override + public boolean isRequired() { + return getState(false).required; + } + + /** + * Sets the field required. Required fields must filled by the user. + * + * If the field is required, it is visually indicated in the user interface. + * Furthermore, setting field to be required implicitly adds "non-empty" + * validator and thus isValid() == false or any isEmpty() fields. In those + * cases validation errors are not painted as it is obvious that the user + * must fill in the required fields. + * + * On the other hand, for the non-required fields isValid() == true if the + * field isEmpty() regardless of any attached validators. + * + * @param required + * Is the field required. + */ + @Override + public void setRequired(boolean required) { + getState().required = required; + } + + /** + * Set the error that is show if this field is required, but empty. When + * setting requiredMessage to be "" or null, no error pop-up or exclamation + * mark is shown for a empty required field. This faults to "". Even in + * those cases isValid() returns false for empty required fields. + * + * @param requiredMessage + * Message to be shown when this field is required, but empty. + */ + @Override + public void setRequiredError(String requiredMessage) { + requiredError = requiredMessage; + markAsDirty(); + } + + @Override + public String getRequiredError() { + return requiredError; + } + + /** + * Gets the error that is shown if the field value cannot be converted to + * the data source type. + * + * @return The error that is shown if conversion of the field value fails + */ + public String getConversionError() { + return conversionError; + } + + /** + * Sets the error that is shown if the field value cannot be converted to + * the data source type. If {0} is present in the message, it will be + * replaced by the simple name of the data source type. If {1} is present in + * the message, it will be replaced by the ConversionException message. + * + * @param valueConversionError + * Message to be shown when conversion of the value fails + */ + public void setConversionError(String valueConversionError) { + this.conversionError = valueConversionError; + markAsDirty(); + } + + @Override + public boolean isEmpty() { + return (getFieldValue() == null); + } + + @Override + public void clear() { + setValue(null); + } + + /** + * Is automatic, visible validation enabled? + * + * If automatic validation is enabled, any validators connected to this + * component are evaluated while painting the component and potential error + * messages are sent to client. If the automatic validation is turned off, + * isValid() and validate() methods still work, but one must show the + * validation in their own code. + * + * @return True, if automatic validation is enabled. + */ + public boolean isValidationVisible() { + return validationVisible; + } + + /** + * Enable or disable automatic, visible validation. + * + * If automatic validation is enabled, any validators connected to this + * component are evaluated while painting the component and potential error + * messages are sent to client. If the automatic validation is turned off, + * isValid() and validate() methods still work, but one must show the + * validation in their own code. + * + * @param validateAutomatically + * True, if automatic validation is enabled. + */ + public void setValidationVisible(boolean validateAutomatically) { + if (validationVisible != validateAutomatically) { + markAsDirty(); + validationVisible = validateAutomatically; + } + } + + /** + * Sets the current buffered source exception. + * + * @param currentBufferedSourceException + */ + public void setCurrentBufferedSourceException( + Buffered.SourceException currentBufferedSourceException) { + this.currentBufferedSourceException = currentBufferedSourceException; + markAsDirty(); + } + + /** + * Gets the current buffered source exception. + * + * @return The current source exception + */ + protected Buffered.SourceException getCurrentBufferedSourceException() { + return currentBufferedSourceException; + } + + /** + * A ready-made {@link ShortcutListener} that focuses the given + * {@link Focusable} (usually a {@link LegacyField}) when the keyboard shortcut is + * invoked. + * + */ + public static class FocusShortcut extends ShortcutListener { + protected Focusable focusable; + + /** + * Creates a keyboard shortcut for focusing the given {@link Focusable} + * using the shorthand notation defined in {@link ShortcutAction}. + * + * @param focusable + * to focused when the shortcut is invoked + * @param shorthandCaption + * caption with keycode and modifiers indicated + */ + public FocusShortcut(Focusable focusable, String shorthandCaption) { + super(shorthandCaption); + this.focusable = focusable; + } + + /** + * Creates a keyboard shortcut for focusing the given {@link Focusable}. + * + * @param focusable + * to focused when the shortcut is invoked + * @param keyCode + * keycode that invokes the shortcut + * @param modifiers + * modifiers required to invoke the shortcut + */ + public FocusShortcut(Focusable focusable, int keyCode, + int... modifiers) { + super(null, keyCode, modifiers); + this.focusable = focusable; + } + + /** + * Creates a keyboard shortcut for focusing the given {@link Focusable}. + * + * @param focusable + * to focused when the shortcut is invoked + * @param keyCode + * keycode that invokes the shortcut + */ + public FocusShortcut(Focusable focusable, int keyCode) { + this(focusable, keyCode, null); + } + + @Override + public void handleAction(Object sender, Object target) { + focusable.focus(); + } + } + + private void updateValueFromDataSource() { + if (dataSource != null) { + + // Gets the correct value from datasource + T newFieldValue; + try { + + // Discards buffer by overwriting from datasource + newFieldValue = convertFromModel(getDataSourceValue()); + + // If successful, remove set the buffering state to be ok + if (getCurrentBufferedSourceException() != null) { + setCurrentBufferedSourceException(null); + } + } catch (final Throwable e) { + // FIXME: What should really be done here if conversion fails? + + // Sets the buffering state + currentBufferedSourceException = new Buffered.SourceException( + this, e); + markAsDirty(); + + // Throws the source exception + throw currentBufferedSourceException; + } + + final boolean wasModified = isModified(); + setModified(false); + + // If the new value differs from the previous one + if (!SharedUtil.equals(newFieldValue, getInternalValue())) { + setInternalValue(newFieldValue); + fireValueChange(false); + } else if (wasModified) { + // If the value did not change, but the modification status did + markAsDirty(); + } + } + } + + /** + * Gets the converter used to convert the property data source value to the + * field value. + * + * @return The converter or null if none is set. + */ + public Converter getConverter() { + return converter; + } + + /** + * Sets the converter used to convert the field value to property data + * source type. The converter must have a presentation type that matches the + * field type. + * + * @param converter + * The new converter to use. + */ + public void setConverter(Converter converter) { + this.converter = (Converter) converter; + markAsDirty(); + } + + @Override + protected AbstractFieldState getState() { + return (AbstractFieldState) super.getState(); + } + + @Override + protected AbstractFieldState getState(boolean markAsDirty) { + return (AbstractFieldState) super.getState(markAsDirty); + } + + @Override + public void beforeClientResponse(boolean initial) { + super.beforeClientResponse(initial); + + // Hide the error indicator if needed + getState().hideErrors = shouldHideErrors(); + } + + /** + * Registers this as an event listener for events sent by the data source + * (if any). Does nothing if + * isListeningToPropertyEvents == true. + */ + private void addPropertyListeners() { + if (!isListeningToPropertyEvents) { + if (dataSource instanceof Property.ValueChangeNotifier) { + ((Property.ValueChangeNotifier) dataSource).addListener(this); + } + if (dataSource instanceof Property.ReadOnlyStatusChangeNotifier) { + ((Property.ReadOnlyStatusChangeNotifier) dataSource) + .addListener(this); + } + isListeningToPropertyEvents = true; + } + } + + /** + * Stops listening to events sent by the data source (if any). Does nothing + * if isListeningToPropertyEvents == false. + */ + private void removePropertyListeners() { + if (isListeningToPropertyEvents) { + if (dataSource instanceof Property.ValueChangeNotifier) { + ((Property.ValueChangeNotifier) dataSource) + .removeListener(this); + } + if (dataSource instanceof Property.ReadOnlyStatusChangeNotifier) { + ((Property.ReadOnlyStatusChangeNotifier) dataSource) + .removeListener(this); + } + isListeningToPropertyEvents = false; + } + } + + /** + * {@inheritDoc} + *

+ * Fields are automatically set to immediate if validators have been added. + */ + @Override + public boolean isImmediate() { + if (getExplicitImmediateValue() != null) { + return getExplicitImmediateValue(); + } + // Make field immediate when there is some kind of validation present + // (validator or required). This will avoid the UI being in a wrong + // state, e.g. user entered valid data but old validation error is still + // shown + return super.isImmediate() || !getValidators().isEmpty() + || isRequired(); + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.ui.AbstractComponent#readDesign(org.jsoup.nodes .Element, + * com.vaadin.ui.declarative.DesignContext) + */ + @Override + public void readDesign(Element design, DesignContext designContext) { + super.readDesign(design, designContext); + Attributes attr = design.attributes(); + if (design.hasAttr("readonly")) { + setReadOnly(DesignAttributeHandler.readAttribute("readonly", attr, + Boolean.class)); + } + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.ui.AbstractComponent#getCustomAttributes() + */ + @Override + protected Collection getCustomAttributes() { + Collection attributes = super.getCustomAttributes(); + attributes.add("readonly"); + // must be handled by subclasses + attributes.add("value"); + attributes.add("converted-value"); + return attributes; + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.ui.AbstractComponent#writeDesign(org.jsoup.nodes.Element + * , com.vaadin.ui.declarative.DesignContext) + */ + @Override + public void writeDesign(Element design, DesignContext designContext) { + super.writeDesign(design, designContext); + LegacyAbstractField def = (LegacyAbstractField) designContext + .getDefaultInstance(this); + Attributes attr = design.attributes(); + // handle readonly + DesignAttributeHandler.writeAttribute("readonly", attr, + super.isReadOnly(), def.isReadOnly(), Boolean.class); + } + + private static final Logger getLogger() { + return Logger.getLogger(LegacyAbstractField.class.getName()); + } +} diff --git a/server/src/main/java/com/vaadin/legacy/ui/LegacyField.java b/server/src/main/java/com/vaadin/legacy/ui/LegacyField.java new file mode 100644 index 0000000000..a3ac84871d --- /dev/null +++ b/server/src/main/java/com/vaadin/legacy/ui/LegacyField.java @@ -0,0 +1,140 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.vaadin.legacy.ui; + +import com.vaadin.data.BufferedValidatable; +import com.vaadin.data.Property; +import com.vaadin.ui.Component; +import com.vaadin.ui.Component.Event; +import com.vaadin.ui.Component.Focusable; + +/** + * LegacyField interface is implemented by all classes (field components) that have a + * value that the user can change through the user interface. + * + * LegacyField components are built upon the framework defined in the LegacyField interface + * and the {@link com.vaadin.LegacyAbstractField} base class. + * + * The LegacyField interface inherits the {@link com.vaadin.ui.Component} + * superinterface and also the {@link com.vaadin.ui.Property} interface to have + * a value for the field. + * + * + * @author Vaadin Ltd. + * + * @param T + * the type of values in the field, which might not be the same type + * as that of the data source if converters are used + * + * @author IT Mill Ltd. + */ +public interface LegacyField extends Component, BufferedValidatable, Property, + Property.ValueChangeNotifier, Property.ValueChangeListener, + Property.Editor, Focusable { + + /** + * Is this field required. + * + * Required fields must filled by the user. + * + * @return true if the field is required,otherwise + * false. + * @since 3.1 + */ + public boolean isRequired(); + + /** + * Sets the field required. Required fields must filled by the user. + * + * @param required + * Is the field required. + * @since 3.1 + */ + public void setRequired(boolean required); + + /** + * Sets the error message to be displayed if a required field is empty. + * + * @param requiredMessage + * Error message. + * @since 5.2.6 + */ + public void setRequiredError(String requiredMessage); + + /** + * Gets the error message that is to be displayed if a required field is + * empty. + * + * @return Error message. + * @since 5.2.6 + */ + public String getRequiredError(); + + /** + * An Event object specifying the LegacyField whose value has been + * changed. + * + * @author Vaadin Ltd. + * @since 3.0 + */ + @SuppressWarnings("serial") + public static class ValueChangeEvent extends Component.Event implements + Property.ValueChangeEvent { + + /** + * Constructs a new event object with the specified source field object. + * + * @param source + * the field that caused the event. + */ + public ValueChangeEvent(LegacyField source) { + super(source); + } + + /** + * Gets the Property which triggered the event. + * + * @return the Source Property of the event. + */ + @Override + public Property getProperty() { + return (Property) getSource(); + } + } + + /** + * Is the field empty? + * + * In general, "empty" state is same as null. As an exception, TextField + * also treats empty string as "empty". + * + * @since 7.4 + * @return true if the field is empty, false otherwise + */ + public boolean isEmpty(); + + /** + * Clears the value of the field. + *

+ * The field value is typically reset to the initial value of the field. + * Calling {@link #isEmpty()} on a cleared field must always returns true. + * + * @since 7.4 + */ + public void clear(); + +} diff --git a/server/src/main/java/com/vaadin/server/VaadinSession.java b/server/src/main/java/com/vaadin/server/VaadinSession.java index 304dd4bec6..d99bd75de8 100644 --- a/server/src/main/java/com/vaadin/server/VaadinSession.java +++ b/server/src/main/java/com/vaadin/server/VaadinSession.java @@ -51,8 +51,8 @@ import com.vaadin.data.util.converter.Converter; import com.vaadin.data.util.converter.ConverterFactory; import com.vaadin.data.util.converter.DefaultConverterFactory; import com.vaadin.event.EventRouter; +import com.vaadin.legacy.ui.LegacyAbstractField; import com.vaadin.shared.communication.PushMode; -import com.vaadin.ui.AbstractField; import com.vaadin.ui.Table; import com.vaadin.ui.UI; import com.vaadin.util.CurrentInstance; @@ -615,7 +615,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { *

*

* The {@link Converter} for an individual field can be overridden using - * {@link AbstractField#setConverter(Converter)} and for individual property + * {@link LegacyAbstractField#setConverter(Converter)} and for individual property * ids in a {@link Table} using * {@link Table#setConverter(Object, Converter)}. *

diff --git a/server/src/main/java/com/vaadin/ui/AbstractComponent.java b/server/src/main/java/com/vaadin/ui/AbstractComponent.java index 8fa1f523ff..24f1ef098b 100644 --- a/server/src/main/java/com/vaadin/ui/AbstractComponent.java +++ b/server/src/main/java/com/vaadin/ui/AbstractComponent.java @@ -39,6 +39,8 @@ import com.vaadin.event.ConnectorActionManager; import com.vaadin.event.ContextClickEvent; import com.vaadin.event.ContextClickEvent.ContextClickListener; import com.vaadin.event.ContextClickEvent.ContextClickNotifier; +import com.vaadin.legacy.ui.LegacyField; +import com.vaadin.legacy.ui.LegacyField.ValueChangeEvent; import com.vaadin.event.ShortcutListener; import com.vaadin.server.AbstractClientConnector; import com.vaadin.server.AbstractErrorMessage.ContentMode; @@ -59,7 +61,6 @@ import com.vaadin.shared.EventId; import com.vaadin.shared.MouseEventDetails; import com.vaadin.shared.ui.ComponentStateUtil; import com.vaadin.shared.util.SharedUtil; -import com.vaadin.ui.Field.ValueChangeEvent; import com.vaadin.ui.declarative.DesignAttributeHandler; import com.vaadin.ui.declarative.DesignContext; import com.vaadin.util.ReflectTools; @@ -1345,7 +1346,7 @@ public abstract class AbstractComponent extends AbstractClientConnector /** * Gets the {@link ActionManager} used to manage the - * {@link ShortcutListener}s added to this {@link Field}. + * {@link ShortcutListener}s added to this {@link LegacyField}. * * @return the ActionManager in use */ diff --git a/server/src/main/java/com/vaadin/ui/AbstractField.java b/server/src/main/java/com/vaadin/ui/AbstractField.java deleted file mode 100644 index 6d25076526..0000000000 --- a/server/src/main/java/com/vaadin/ui/AbstractField.java +++ /dev/null @@ -1,1852 +0,0 @@ -/* - * Copyright 2000-2014 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.ui; - -import java.io.Serializable; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Locale; -import java.util.logging.Logger; - -import org.jsoup.nodes.Attributes; -import org.jsoup.nodes.Element; - -import com.vaadin.data.Buffered; -import com.vaadin.data.Property; -import com.vaadin.data.Validatable; -import com.vaadin.data.Validator; -import com.vaadin.data.Validator.InvalidValueException; -import com.vaadin.data.util.LegacyPropertyHelper; -import com.vaadin.data.util.converter.Converter; -import com.vaadin.data.util.converter.Converter.ConversionException; -import com.vaadin.data.util.converter.ConverterUtil; -import com.vaadin.event.Action; -import com.vaadin.event.ShortcutAction; -import com.vaadin.event.ShortcutListener; -import com.vaadin.server.AbstractErrorMessage; -import com.vaadin.server.CompositeErrorMessage; -import com.vaadin.server.ErrorMessage; -import com.vaadin.shared.AbstractFieldState; -import com.vaadin.shared.util.SharedUtil; -import com.vaadin.ui.declarative.DesignAttributeHandler; -import com.vaadin.ui.declarative.DesignContext; - -/** - *

- * Abstract field component for implementing buffered property editors. The - * field may hold an internal value, or it may be connected to any data source - * that implements the {@link com.vaadin.data.Property}interface. - * AbstractField implements that interface itself, too, so - * accessing the Property value represented by it is straightforward. - *

- * - *

- * AbstractField also provides the {@link com.vaadin.data.Buffered} interface - * for buffering the data source value. By default the Field is in write - * through-mode and {@link #setWriteThrough(boolean)}should be called to enable - * buffering. - *

- * - *

- * The class also supports {@link com.vaadin.data.Validator validators} to make - * sure the value contained in the field is valid. - *

- * - * @author Vaadin Ltd. - * @since 3.0 - */ -@SuppressWarnings("serial") -public abstract class AbstractField extends AbstractComponent implements - Field, Property.ReadOnlyStatusChangeListener, - Property.ReadOnlyStatusChangeNotifier, Action.ShortcutNotifier { - - /* Private members */ - - /** - * Value of the abstract field. - */ - private T value; - - /** - * A converter used to convert from the data model type to the field type - * and vice versa. - */ - private Converter converter = null; - /** - * Connected data-source. - */ - private Property dataSource = null; - - /** - * The list of validators. - */ - private LinkedList validators = null; - - /** - * True if field is in buffered mode, false otherwise - */ - private boolean buffered; - - /** - * Flag to indicate that the field is currently committing its value to the - * datasource. - */ - private boolean committingValueToDataSource = false; - - /** - * Current source exception. - */ - private Buffered.SourceException currentBufferedSourceException = null; - - /** - * Are the invalid values allowed in fields ? - */ - private boolean invalidAllowed = true; - - /** - * Are the invalid values committed ? - */ - private boolean invalidCommitted = false; - - /** - * The error message for the exception that is thrown when the field is - * required but empty. - */ - private String requiredError = ""; - - /** - * The error message that is shown when the field value cannot be converted. - */ - private String conversionError = "Could not convert value to {0}"; - - /** - * Is automatic validation enabled. - */ - private boolean validationVisible = true; - - private boolean valueWasModifiedByDataSourceDuringCommit; - - /** - * Whether this field is currently registered as listening to events from - * its data source. - * - * @see #setPropertyDataSource(Property) - * @see #addPropertyListeners() - * @see #removePropertyListeners() - */ - private boolean isListeningToPropertyEvents = false; - - /** - * The locale used when setting the value. - */ - private Locale valueLocale = null; - - /* Component basics */ - - /* - * Paints the field. Don't add a JavaDoc comment here, we use the default - * documentation from the implemented interface. - */ - - /** - * Returns true if the error indicator be hidden when painting the component - * even when there are errors. - * - * This is a mostly internal method, but can be overridden in subclasses - * e.g. if the error indicator should also be shown for empty fields in some - * cases. - * - * @return true to hide the error indicator, false to use the normal logic - * to show it when there are errors - */ - protected boolean shouldHideErrors() { - // getErrorMessage() can still return something else than null based on - // validation etc. - return isRequired() && isEmpty() && getComponentError() == null; - } - - /** - * Returns the type of the Field. The methods getValue and - * setValue must be compatible with this type: one must be able - * to safely cast the value returned from getValue to the given - * type and pass any variable assignable to this type as an argument to - * setValue. - * - * @return the type of the Field - */ - @Override - public abstract Class getType(); - - /** - * The abstract field is read only also if the data source is in read only - * mode. - */ - @Override - public boolean isReadOnly() { - return super.isReadOnly() - || (dataSource != null && dataSource.isReadOnly()); - } - - /** - * Changes the readonly state and throw read-only status change events. - * - * @see com.vaadin.ui.Component#setReadOnly(boolean) - */ - @Override - public void setReadOnly(boolean readOnly) { - super.setReadOnly(readOnly); - fireReadOnlyStatusChange(); - } - - /** - * Tests if the invalid data is committed to datasource. - * - * @see com.vaadin.data.BufferedValidatable#isInvalidCommitted() - */ - @Override - public boolean isInvalidCommitted() { - return invalidCommitted; - } - - /** - * Sets if the invalid data should be committed to datasource. - * - * @see com.vaadin.data.BufferedValidatable#setInvalidCommitted(boolean) - */ - @Override - public void setInvalidCommitted(boolean isCommitted) { - invalidCommitted = isCommitted; - } - - /* - * Saves the current value to the data source Don't add a JavaDoc comment - * here, we use the default documentation from the implemented interface. - */ - @Override - public void commit() throws Buffered.SourceException, InvalidValueException { - if (dataSource != null && !dataSource.isReadOnly()) { - if ((isInvalidCommitted() || isValid())) { - try { - - // Commits the value to datasource. - valueWasModifiedByDataSourceDuringCommit = false; - committingValueToDataSource = true; - getPropertyDataSource().setValue(getConvertedValue()); - } catch (final Throwable e) { - - // Sets the buffering state. - SourceException sourceException = new Buffered.SourceException( - this, e); - setCurrentBufferedSourceException(sourceException); - - // Throws the source exception. - throw sourceException; - } finally { - committingValueToDataSource = false; - } - } else { - /* - * An invalid value and we don't allow them, throw the exception - */ - validate(); - } - } - - // The abstract field is not modified anymore - if (isModified()) { - setModified(false); - } - - // If successful, remove set the buffering state to be ok - if (getCurrentBufferedSourceException() != null) { - setCurrentBufferedSourceException(null); - } - - if (valueWasModifiedByDataSourceDuringCommit) { - valueWasModifiedByDataSourceDuringCommit = false; - fireValueChange(false); - } - - } - - /* - * Updates the value from the data source. Don't add a JavaDoc comment here, - * we use the default documentation from the implemented interface. - */ - @Override - public void discard() throws Buffered.SourceException { - updateValueFromDataSource(); - } - - /** - * Gets the value from the data source. This is only here because of clarity - * in the code that handles both the data model value and the field value. - * - * @return The value of the property data source - */ - private Object getDataSourceValue() { - return dataSource.getValue(); - } - - /** - * Returns the field value. This is always identical to {@link #getValue()} - * and only here because of clarity in the code that handles both the data - * model value and the field value. - * - * @return The value of the field - */ - private T getFieldValue() { - // Give the value from abstract buffers if the field if possible - if (dataSource == null || isBuffered() || isModified()) { - return getInternalValue(); - } - - // There is no buffered value so use whatever the data model provides - return convertFromModel(getDataSourceValue()); - } - - /* - * Has the field been modified since the last commit()? Don't add a JavaDoc - * comment here, we use the default documentation from the implemented - * interface. - */ - @Override - public boolean isModified() { - return getState(false).modified; - } - - private void setModified(boolean modified) { - getState().modified = modified; - } - - /** - * Sets the buffered mode of this Field. - *

- * When the field is in buffered mode, changes will not be committed to the - * property data source until {@link #commit()} is called. - *

- *

- * Setting buffered mode from true to false will commit any pending changes. - *

- *

- * - *

- * - * @since 7.0.0 - * @param buffered - * true if buffered mode should be turned on, false otherwise - */ - @Override - public void setBuffered(boolean buffered) { - if (this.buffered == buffered) { - return; - } - this.buffered = buffered; - if (!buffered) { - commit(); - } - } - - /** - * Checks the buffered mode of this Field. - * - * @return true if buffered mode is on, false otherwise - */ - @Override - public boolean isBuffered() { - return buffered; - } - - /** - * Returns a string representation of this object. The returned string - * representation depends on if the legacy Property toString mode is enabled - * or disabled. - *

- * If legacy Property toString mode is enabled, returns the value of this - * Field converted to a String. - *

- *

- * If legacy Property toString mode is disabled, the string representation - * has no special meaning - *

- * - * @see LegacyPropertyHelper#isLegacyToStringEnabled() - * - * @return A string representation of the value value stored in the Property - * or a string representation of the Property object. - * @deprecated As of 7.0. Use {@link #getValue()} to get the value of the - * field, {@link #getConvertedValue()} to get the field value - * converted to the data model type or - * {@link #getPropertyDataSource()} .getValue() to get the value - * of the data source. - */ - @Deprecated - @Override - public String toString() { - if (!LegacyPropertyHelper.isLegacyToStringEnabled()) { - return super.toString(); - } else { - return LegacyPropertyHelper.legacyPropertyToString(this); - } - } - - /* Property interface implementation */ - - /** - * Gets the current value of the field. - * - *

- * This is the visible, modified and possible invalid value the user have - * entered to the field. - *

- * - *

- * Note that the object returned is compatible with getType(). For example, - * if the type is String, this returns Strings even when the underlying - * datasource is of some other type. In order to access the converted value, - * use {@link #getConvertedValue()} and to access the value of the property - * data source, use {@link Property#getValue()} for the property data - * source. - *

- * - *

- * Since Vaadin 7.0, no implicit conversions between other data types and - * String are performed, but a converter is used if set. - *

- * - * @return the current value of the field. - */ - @Override - public T getValue() { - return getFieldValue(); - } - - /** - * Sets the value of the field. - * - * @param newFieldValue - * the New value of the field. - * @throws Property.ReadOnlyException - */ - @Override - public void setValue(T newFieldValue) throws Property.ReadOnlyException, - Converter.ConversionException { - setValue(newFieldValue, false); - } - - /** - * Sets the value of the field. - * - * @param newFieldValue - * the New value of the field. - * @param repaintIsNotNeeded - * True iff caller is sure that repaint is not needed. - * @throws Property.ReadOnlyException - * @throws Converter.ConversionException - * @throws InvalidValueException - */ - protected void setValue(T newFieldValue, boolean repaintIsNotNeeded) { - setValue(newFieldValue, repaintIsNotNeeded, false); - } - - /** - * Sets the value of the field. - * - * @since 7.5.7 - * @param newFieldValue - * the New value of the field. - * @param repaintIsNotNeeded - * True iff caller is sure that repaint is not needed. - * @param ignoreReadOnly - * True iff if the read-only check should be ignored - * @throws Property.ReadOnlyException - * @throws Converter.ConversionException - * @throws InvalidValueException - */ - protected void setValue(T newFieldValue, boolean repaintIsNotNeeded, - boolean ignoreReadOnly) throws Property.ReadOnlyException, - Converter.ConversionException, InvalidValueException { - - if (!SharedUtil.equals(newFieldValue, getInternalValue())) { - - // Read only fields can not be changed - if (!ignoreReadOnly && isReadOnly()) { - throw new Property.ReadOnlyException(); - } - try { - T doubleConvertedFieldValue = convertFromModel(convertToModel(newFieldValue)); - if (!SharedUtil - .equals(newFieldValue, doubleConvertedFieldValue)) { - newFieldValue = doubleConvertedFieldValue; - repaintIsNotNeeded = false; - } - } catch (Throwable t) { - // Ignore exceptions in the conversion at this stage. Any - // conversion error will be handled later by validate(). - } - - // Repaint is needed even when the client thinks that it knows the - // new state if validity of the component may change - if (repaintIsNotNeeded - && (isRequired() || hasValidators() || getConverter() != null)) { - repaintIsNotNeeded = false; - } - - if (!isInvalidAllowed()) { - /* - * If invalid values are not allowed the value must be validated - * before it is set. If validation fails, the - * InvalidValueException is thrown and the internal value is not - * updated. - */ - validate(newFieldValue); - } - - // Changes the value - setInternalValue(newFieldValue); - setModified(dataSource != null); - - valueWasModifiedByDataSourceDuringCommit = false; - // In not buffering, try to commit - if (!isBuffered() && dataSource != null - && (isInvalidCommitted() || isValid())) { - try { - - // Commits the value to datasource - committingValueToDataSource = true; - getPropertyDataSource().setValue( - convertToModel(newFieldValue)); - - // The buffer is now unmodified - setModified(false); - - } catch (final Throwable e) { - - // Sets the buffering state - currentBufferedSourceException = new Buffered.SourceException( - this, e); - markAsDirty(); - - // Throws the source exception - throw currentBufferedSourceException; - } finally { - committingValueToDataSource = false; - } - } - - // If successful, remove set the buffering state to be ok - if (getCurrentBufferedSourceException() != null) { - setCurrentBufferedSourceException(null); - } - - if (valueWasModifiedByDataSourceDuringCommit) { - /* - * Value was modified by datasource. Force repaint even if - * repaint was not requested. - */ - valueWasModifiedByDataSourceDuringCommit = repaintIsNotNeeded = false; - } - - // Fires the value change - fireValueChange(repaintIsNotNeeded); - - } - } - - @Deprecated - static boolean equals(Object value1, Object value2) { - return SharedUtil.equals(value1, value2); - } - - /* External data source */ - - /** - * Gets the current data source of the field, if any. - * - * @return the current data source as a Property, or null if - * none defined. - */ - @Override - public Property getPropertyDataSource() { - return dataSource; - } - - /** - *

- * Sets the specified Property as the data source for the field. All - * uncommitted changes are replaced with a value from the new data source. - *

- * - *

- * If the datasource has any validators, the same validators are added to - * the field. Because the default behavior of the field is to allow invalid - * values, but not to allow committing them, this only adds visual error - * messages to fields and do not allow committing them as long as the value - * is invalid. After the value is valid, the error message is not shown and - * the commit can be done normally. - *

- * - *

- * If the data source implements - * {@link com.vaadin.data.Property.ValueChangeNotifier} and/or - * {@link com.vaadin.data.Property.ReadOnlyStatusChangeNotifier}, the field - * registers itself as a listener and updates itself according to the events - * it receives. To avoid memory leaks caused by references to a field no - * longer in use, the listener registrations are removed on - * {@link AbstractField#detach() detach} and re-added on - * {@link AbstractField#attach() attach}. - *

- * - *

- * Note: before 6.5 we actually called discard() method in the beginning of - * the method. This was removed to simplify implementation, avoid excess - * calls to backing property and to avoid odd value change events that were - * previously fired (developer expects 0-1 value change events if this - * method is called). Some complex field implementations might now need to - * override this method to do housekeeping similar to discard(). - *

- * - * @param newDataSource - * the new data source Property. - */ - @Override - public void setPropertyDataSource(Property newDataSource) { - - // Saves the old value - final Object oldValue = getInternalValue(); - - // Stop listening to the old data source - removePropertyListeners(); - - // Sets the new data source - dataSource = newDataSource; - getState().propertyReadOnly = dataSource == null ? false : dataSource - .isReadOnly(); - - // Check if the current converter is compatible. - if (newDataSource != null - && !ConverterUtil.canConverterPossiblyHandle(getConverter(), - getType(), newDataSource.getType())) { - // There is no converter set or there is no way the current - // converter can be compatible. - setConverter(newDataSource.getType()); - } - // Gets the value from source. This requires that a valid converter has - // been set. - try { - if (dataSource != null) { - T fieldValue = convertFromModel(getDataSourceValue()); - setInternalValue(fieldValue); - } - setModified(false); - if (getCurrentBufferedSourceException() != null) { - setCurrentBufferedSourceException(null); - } - } catch (final Throwable e) { - setCurrentBufferedSourceException(new Buffered.SourceException( - this, e)); - setModified(true); - throw getCurrentBufferedSourceException(); - } - - // Listen to new data source if possible - addPropertyListeners(); - - // Copy the validators from the data source - if (dataSource instanceof Validatable) { - final Collection validators = ((Validatable) dataSource) - .getValidators(); - if (validators != null) { - for (final Iterator i = validators.iterator(); i - .hasNext();) { - addValidator(i.next()); - } - } - } - - // Fires value change if the value has changed - T value = getInternalValue(); - if ((value != oldValue) - && ((value != null && !value.equals(oldValue)) || value == null)) { - fireValueChange(false); - } - } - - /** - * Retrieves a converter for the field from the converter factory defined - * for the application. Clears the converter if no application reference is - * available or if the factory returns null. - * - * @param datamodelType - * The type of the data model that we want to be able to convert - * from - */ - public void setConverter(Class datamodelType) { - Converter c = (Converter) ConverterUtil.getConverter( - getType(), datamodelType, getSession()); - setConverter(c); - } - - /** - * Convert the given value from the data source type to the UI type. - * - * @param newValue - * The data source value to convert. - * @return The converted value that is compatible with the UI type or the - * original value if its type is compatible and no converter is set. - * @throws Converter.ConversionException - * if there is no converter and the type is not compatible with - * the data source type. - */ - private T convertFromModel(Object newValue) { - return convertFromModel(newValue, getLocale()); - } - - /** - * Convert the given value from the data source type to the UI type. - * - * @param newValue - * The data source value to convert. - * @return The converted value that is compatible with the UI type or the - * original value if its type is compatible and no converter is set. - * @throws Converter.ConversionException - * if there is no converter and the type is not compatible with - * the data source type. - */ - private T convertFromModel(Object newValue, Locale locale) { - return ConverterUtil.convertFromModel(newValue, getType(), - getConverter(), locale); - } - - /** - * Convert the given value from the UI type to the data source type. - * - * @param fieldValue - * The value to convert. Typically returned by - * {@link #getFieldValue()} - * @return The converted value that is compatible with the data source type. - * @throws Converter.ConversionException - * if there is no converter and the type is not compatible with - * the data source type. - */ - private Object convertToModel(T fieldValue) - throws Converter.ConversionException { - return convertToModel(fieldValue, getLocale()); - } - - /** - * Convert the given value from the UI type to the data source type. - * - * @param fieldValue - * The value to convert. Typically returned by - * {@link #getFieldValue()} - * @param locale - * The locale to use for the conversion - * @return The converted value that is compatible with the data source type. - * @throws Converter.ConversionException - * if there is no converter and the type is not compatible with - * the data source type. - */ - private Object convertToModel(T fieldValue, Locale locale) - throws Converter.ConversionException { - Class modelType = getModelType(); - try { - return ConverterUtil.convertToModel(fieldValue, - (Class) modelType, getConverter(), locale); - } catch (ConversionException e) { - throw new ConversionException(getConversionError(modelType, e), e); - } - } - - /** - * Retrieves the type of the currently used data model. If the field has no - * data source then the model type of the converter is used. - * - * @since 7.1 - * @return The type of the currently used data model or null if no data - * source or converter is set. - */ - protected Class getModelType() { - Property pd = getPropertyDataSource(); - if (pd != null) { - return pd.getType(); - } else if (getConverter() != null) { - return getConverter().getModelType(); - } - return null; - } - - /** - * Returns the conversion error with {0} replaced by the data source type - * and {1} replaced by the exception (localized) message. - * - * @since 7.1 - * @param dataSourceType - * the type of the data source - * @param e - * a conversion exception which can provide additional - * information - * @return The value conversion error string with parameters replaced. - */ - protected String getConversionError(Class dataSourceType, - ConversionException e) { - String conversionError = getConversionError(); - - if (conversionError != null) { - if (dataSourceType != null) { - conversionError = conversionError.replace("{0}", - dataSourceType.getSimpleName()); - } - if (e != null) { - conversionError = conversionError.replace("{1}", - e.getLocalizedMessage()); - } - } - return conversionError; - } - - /** - * Returns the current value (as returned by {@link #getValue()}) converted - * to the data source type. - *

- * This returns the same as {@link AbstractField#getValue()} if no converter - * has been set. The value is not necessarily the same as the data source - * value e.g. if the field is in buffered mode and has been modified. - *

- * - * @return The converted value that is compatible with the data source type - */ - public Object getConvertedValue() { - return convertToModel(getFieldValue()); - } - - /** - * Sets the value of the field using a value of the data source type. The - * value given is converted to the field type and then assigned to the - * field. This will update the property data source in the same way as when - * {@link #setValue(Object)} is called. - * - * @param value - * The value to set. Must be the same type as the data source. - */ - public void setConvertedValue(Object value) { - setValue(convertFromModel(value)); - } - - /* Validation */ - - /** - * Adds a new validator for the field's value. All validators added to a - * field are checked each time the its value changes. - * - * @param validator - * the new validator to be added. - */ - @Override - public void addValidator(Validator validator) { - if (validators == null) { - validators = new LinkedList(); - } - validators.add(validator); - markAsDirty(); - } - - /** - * Gets the validators of the field. - * - * @return An unmodifiable collection that holds all validators for the - * field. - */ - @Override - public Collection getValidators() { - if (validators == null) { - return Collections.emptyList(); - } else { - return Collections.unmodifiableCollection(validators); - } - } - - private boolean hasValidators() { - return validators != null && !validators.isEmpty(); - } - - /** - * Removes the validator from the field. - * - * @param validator - * the validator to remove. - */ - @Override - public void removeValidator(Validator validator) { - if (validators != null) { - validators.remove(validator); - } - markAsDirty(); - } - - /** - * Removes all validators from the field. - */ - @Override - public void removeAllValidators() { - if (validators != null) { - validators.clear(); - } - markAsDirty(); - } - - /** - * Tests the current value against registered validators if the field is not - * empty. If the field is empty it is considered valid if it is not required - * and invalid otherwise. Validators are never checked for empty fields. - * - * In most cases, {@link #validate()} should be used instead of - * {@link #isValid()} to also get the error message. - * - * @return true if all registered validators claim that the - * current value is valid or if the field is empty and not required, - * false otherwise. - */ - @Override - public boolean isValid() { - - try { - validate(); - return true; - } catch (InvalidValueException e) { - return false; - } - } - - /** - * Checks the validity of the Field. - * - * A field is invalid if it is set as required (using - * {@link #setRequired(boolean)} and is empty, if one or several of the - * validators added to the field indicate it is invalid or if the value - * cannot be converted provided a converter has been set. - * - * The "required" validation is a built-in validation feature. If the field - * is required and empty this method throws an EmptyValueException with the - * error message set using {@link #setRequiredError(String)}. - * - * @see com.vaadin.data.Validatable#validate() - */ - @Override - public void validate() throws Validator.InvalidValueException { - - if (isRequired() && isEmpty()) { - throw new Validator.EmptyValueException(requiredError); - } - validate(getFieldValue()); - } - - /** - * Validates that the given value pass the validators for the field. - *

- * This method does not check the requiredness of the field. - * - * @param fieldValue - * The value to check - * @throws Validator.InvalidValueException - * if one or several validators fail - */ - protected void validate(T fieldValue) - throws Validator.InvalidValueException { - - Object valueToValidate = fieldValue; - - // If there is a converter we start by converting the value as we want - // to validate the converted value - if (getConverter() != null) { - try { - valueToValidate = getConverter().convertToModel(fieldValue, - getModelType(), getLocale()); - } catch (ConversionException e) { - throw new InvalidValueException(getConversionError( - getConverter().getModelType(), e)); - } - } - - List validationExceptions = new ArrayList(); - if (validators != null) { - // Gets all the validation errors - for (Validator v : validators) { - try { - v.validate(valueToValidate); - } catch (final Validator.InvalidValueException e) { - validationExceptions.add(e); - } - } - } - - // If there were no errors - if (validationExceptions.isEmpty()) { - return; - } - - // If only one error occurred, throw it forwards - if (validationExceptions.size() == 1) { - throw validationExceptions.get(0); - } - - InvalidValueException[] exceptionArray = validationExceptions - .toArray(new InvalidValueException[validationExceptions.size()]); - - // Create a composite validator and include all exceptions - throw new Validator.InvalidValueException(null, exceptionArray); - } - - /** - * Fields allow invalid values by default. In most cases this is wanted, - * because the field otherwise visually forget the user input immediately. - * - * @return true iff the invalid values are allowed. - * @see com.vaadin.data.Validatable#isInvalidAllowed() - */ - @Override - public boolean isInvalidAllowed() { - return invalidAllowed; - } - - /** - * Fields allow invalid values by default. In most cases this is wanted, - * because the field otherwise visually forget the user input immediately. - *

- * In common setting where the user wants to assure the correctness of the - * datasource, but allow temporarily invalid contents in the field, the user - * should add the validators to datasource, that should not allow invalid - * values. The validators are automatically copied to the field when the - * datasource is set. - *

- * - * @see com.vaadin.data.Validatable#setInvalidAllowed(boolean) - */ - @Override - public void setInvalidAllowed(boolean invalidAllowed) - throws UnsupportedOperationException { - this.invalidAllowed = invalidAllowed; - } - - /** - * Error messages shown by the fields are composites of the error message - * thrown by the superclasses (that is the component error message), - * validation errors and buffered source errors. - * - * @see com.vaadin.ui.AbstractComponent#getErrorMessage() - */ - @Override - public ErrorMessage getErrorMessage() { - - /* - * Check validation errors only if automatic validation is enabled. - * Empty, required fields will generate a validation error containing - * the requiredError string. For these fields the exclamation mark will - * be hidden but the error must still be sent to the client. - */ - Validator.InvalidValueException validationError = null; - if (isValidationVisible()) { - try { - validate(); - } catch (Validator.InvalidValueException e) { - if (!e.isInvisible()) { - validationError = e; - } - } - } - - // Check if there are any systems errors - final ErrorMessage superError = super.getErrorMessage(); - - // Return if there are no errors at all - if (superError == null && validationError == null - && getCurrentBufferedSourceException() == null) { - return null; - } - - // Throw combination of the error types - return new CompositeErrorMessage( - new ErrorMessage[] { - superError, - AbstractErrorMessage - .getErrorMessageForException(validationError), - AbstractErrorMessage - .getErrorMessageForException(getCurrentBufferedSourceException()) }); - - } - - /* Value change events */ - - private static final Method VALUE_CHANGE_METHOD; - - static { - try { - VALUE_CHANGE_METHOD = Property.ValueChangeListener.class - .getDeclaredMethod("valueChange", - new Class[] { Property.ValueChangeEvent.class }); - } catch (final java.lang.NoSuchMethodException e) { - // This should never happen - throw new java.lang.RuntimeException( - "Internal error finding methods in AbstractField"); - } - } - - /* - * Adds a value change listener for the field. Don't add a JavaDoc comment - * here, we use the default documentation from the implemented interface. - */ - @Override - public void addValueChangeListener(Property.ValueChangeListener listener) { - addListener(AbstractField.ValueChangeEvent.class, listener, - VALUE_CHANGE_METHOD); - // ensure "automatic immediate handling" works - markAsDirty(); - } - - /** - * @deprecated As of 7.0, replaced by - * {@link #addValueChangeListener(com.vaadin.data.Property.ValueChangeListener)} - **/ - @Override - @Deprecated - public void addListener(Property.ValueChangeListener listener) { - addValueChangeListener(listener); - } - - /* - * Removes a value change listener from the field. Don't add a JavaDoc - * comment here, we use the default documentation from the implemented - * interface. - */ - @Override - public void removeValueChangeListener(Property.ValueChangeListener listener) { - removeListener(AbstractField.ValueChangeEvent.class, listener, - VALUE_CHANGE_METHOD); - // ensure "automatic immediate handling" works - markAsDirty(); - } - - /** - * @deprecated As of 7.0, replaced by - * {@link #removeValueChangeListener(com.vaadin.data.Property.ValueChangeListener)} - **/ - @Override - @Deprecated - public void removeListener(Property.ValueChangeListener listener) { - removeValueChangeListener(listener); - } - - /** - * Emits the value change event. The value contained in the field is - * validated before the event is created. - */ - protected void fireValueChange(boolean repaintIsNotNeeded) { - fireEvent(new AbstractField.ValueChangeEvent(this)); - if (!repaintIsNotNeeded) { - markAsDirty(); - } - } - - /* Read-only status change events */ - - private static final Method READ_ONLY_STATUS_CHANGE_METHOD; - - static { - try { - READ_ONLY_STATUS_CHANGE_METHOD = Property.ReadOnlyStatusChangeListener.class - .getDeclaredMethod( - "readOnlyStatusChange", - new Class[] { Property.ReadOnlyStatusChangeEvent.class }); - } catch (final java.lang.NoSuchMethodException e) { - // This should never happen - throw new java.lang.RuntimeException( - "Internal error finding methods in AbstractField"); - } - } - - /** - * React to read only status changes of the property by requesting a - * repaint. - * - * @see Property.ReadOnlyStatusChangeListener - */ - @Override - public void readOnlyStatusChange(Property.ReadOnlyStatusChangeEvent event) { - boolean readOnly = event.getProperty().isReadOnly(); - - boolean shouldFireChange = isReadOnly() != readOnly - || getState().propertyReadOnly != readOnly; - - getState().propertyReadOnly = readOnly; - - if (shouldFireChange) { - fireReadOnlyStatusChange(); - } - } - - /** - * An Event object specifying the Property whose read-only - * status has changed. - * - * @author Vaadin Ltd. - * @since 3.0 - */ - public static class ReadOnlyStatusChangeEvent extends Component.Event - implements Property.ReadOnlyStatusChangeEvent, Serializable { - - /** - * New instance of text change event. - * - * @param source - * the Source of the event. - */ - public ReadOnlyStatusChangeEvent(AbstractField source) { - super(source); - } - - /** - * Property where the event occurred. - * - * @return the Source of the event. - */ - @Override - public Property getProperty() { - return (Property) getSource(); - } - } - - /* - * Adds a read-only status change listener for the field. Don't add a - * JavaDoc comment here, we use the default documentation from the - * implemented interface. - */ - @Override - public void addReadOnlyStatusChangeListener( - Property.ReadOnlyStatusChangeListener listener) { - addListener(Property.ReadOnlyStatusChangeEvent.class, listener, - READ_ONLY_STATUS_CHANGE_METHOD); - } - - /** - * @deprecated As of 7.0, replaced by - * {@link #addReadOnlyStatusChangeListener(com.vaadin.data.Property.ReadOnlyStatusChangeListener)} - **/ - @Override - @Deprecated - public void addListener(Property.ReadOnlyStatusChangeListener listener) { - addReadOnlyStatusChangeListener(listener); - } - - /* - * Removes a read-only status change listener from the field. Don't add a - * JavaDoc comment here, we use the default documentation from the - * implemented interface. - */ - @Override - public void removeReadOnlyStatusChangeListener( - Property.ReadOnlyStatusChangeListener listener) { - removeListener(Property.ReadOnlyStatusChangeEvent.class, listener, - READ_ONLY_STATUS_CHANGE_METHOD); - } - - /** - * @deprecated As of 7.0, replaced by - * {@link #removeReadOnlyStatusChangeListener(com.vaadin.data.Property.ReadOnlyStatusChangeListener)} - **/ - @Override - @Deprecated - public void removeListener(Property.ReadOnlyStatusChangeListener listener) { - removeReadOnlyStatusChangeListener(listener); - } - - /** - * Emits the read-only status change event. The value contained in the field - * is validated before the event is created. - */ - protected void fireReadOnlyStatusChange() { - fireEvent(new AbstractField.ReadOnlyStatusChangeEvent(this)); - } - - /** - * This method listens to data source value changes and passes the changes - * forwards. - * - * Changes are not forwarded to the listeners of the field during internal - * operations of the field to avoid duplicate notifications. - * - * @param event - * the value change event telling the data source contents have - * changed. - */ - @Override - public void valueChange(Property.ValueChangeEvent event) { - if (!isBuffered()) { - if (committingValueToDataSource) { - boolean propertyNotifiesOfTheBufferedValue = SharedUtil.equals( - event.getProperty().getValue(), getInternalValue()); - if (!propertyNotifiesOfTheBufferedValue) { - /* - * Property (or chained property like PropertyFormatter) now - * reports different value than the one the field has just - * committed to it. In this case we respect the property - * value. - * - * Still, we don't fire value change yet, but instead - * postpone it until "commit" is done. See setValue(Object, - * boolean) and commit(). - */ - readValueFromProperty(event); - valueWasModifiedByDataSourceDuringCommit = true; - } - } else if (!isModified()) { - readValueFromProperty(event); - fireValueChange(false); - } - } - } - - private void readValueFromProperty(Property.ValueChangeEvent event) { - setInternalValue(convertFromModel(event.getProperty().getValue())); - } - - /** - * {@inheritDoc} - */ - @Override - public void focus() { - super.focus(); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.Component.Focusable#getTabIndex() - */ - @Override - public int getTabIndex() { - return getState(false).tabIndex; - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.Component.Focusable#setTabIndex(int) - */ - @Override - public void setTabIndex(int tabIndex) { - getState().tabIndex = tabIndex; - } - - /** - * Returns the internal field value, which might not match the data source - * value e.g. if the field has been modified and is not in write-through - * mode. - * - * This method can be overridden by subclasses together with - * {@link #setInternalValue(Object)} to compute internal field value at - * runtime. When doing so, typically also {@link #isModified()} needs to be - * overridden and care should be taken in the management of the empty state - * and buffering support. - * - * @return internal field value - */ - protected T getInternalValue() { - return value; - } - - /** - * Sets the internal field value. This is purely used by AbstractField to - * change the internal Field value. It does not trigger valuechange events. - * It can be overridden by the inheriting classes to update all dependent - * variables. - * - * Subclasses can also override {@link #getInternalValue()} if necessary. - * - * @param newValue - * the new value to be set. - */ - protected void setInternalValue(T newValue) { - value = newValue; - valueLocale = getLocale(); - if (validators != null && !validators.isEmpty()) { - markAsDirty(); - } - } - - /** - * Notifies the component that it is connected to an application. - * - * @see com.vaadin.ui.Component#attach() - */ - @Override - public void attach() { - super.attach(); - - localeMightHaveChanged(); - if (!isListeningToPropertyEvents) { - addPropertyListeners(); - if (!isModified() && !isBuffered()) { - // Update value from data source - updateValueFromDataSource(); - } - } - } - - @Override - public void setLocale(Locale locale) { - super.setLocale(locale); - localeMightHaveChanged(); - } - - private void localeMightHaveChanged() { - if (!SharedUtil.equals(valueLocale, getLocale())) { - // The locale HAS actually changed - - if (dataSource != null && !isModified()) { - // When we have a data source and the internal value is directly - // read from that we want to update the value - T newInternalValue = convertFromModel(getPropertyDataSource() - .getValue()); - if (!SharedUtil.equals(newInternalValue, getInternalValue())) { - setInternalValue(newInternalValue); - fireValueChange(false); - } - } else if (dataSource == null && converter != null) { - /* - * No data source but a converter has been set. The same issues - * as above but we cannot use propertyDataSource. Convert the - * current value back to a model value using the old locale and - * then convert back using the new locale. If this does not - * match the field value we need to set the converted value - * again. - */ - Object convertedValue = convertToModel(getInternalValue(), - valueLocale); - T newinternalValue = convertFromModel(convertedValue); - if (!SharedUtil.equals(getInternalValue(), newinternalValue)) { - setInternalValue(newinternalValue); - fireValueChange(false); - } - } - } - } - - @Override - public void detach() { - super.detach(); - // Stop listening to data source events on detach to avoid a potential - // memory leak. See #6155. - removePropertyListeners(); - } - - /** - * Is this field required. Required fields must filled by the user. - * - * If the field is required, it is visually indicated in the user interface. - * Furthermore, setting field to be required implicitly adds "non-empty" - * validator and thus isValid() == false or any isEmpty() fields. In those - * cases validation errors are not painted as it is obvious that the user - * must fill in the required fields. - * - * On the other hand, for the non-required fields isValid() == true if the - * field isEmpty() regardless of any attached validators. - * - * - * @return true if the field is required, otherwise - * false. - */ - @Override - public boolean isRequired() { - return getState(false).required; - } - - /** - * Sets the field required. Required fields must filled by the user. - * - * If the field is required, it is visually indicated in the user interface. - * Furthermore, setting field to be required implicitly adds "non-empty" - * validator and thus isValid() == false or any isEmpty() fields. In those - * cases validation errors are not painted as it is obvious that the user - * must fill in the required fields. - * - * On the other hand, for the non-required fields isValid() == true if the - * field isEmpty() regardless of any attached validators. - * - * @param required - * Is the field required. - */ - @Override - public void setRequired(boolean required) { - getState().required = required; - } - - /** - * Set the error that is show if this field is required, but empty. When - * setting requiredMessage to be "" or null, no error pop-up or exclamation - * mark is shown for a empty required field. This faults to "". Even in - * those cases isValid() returns false for empty required fields. - * - * @param requiredMessage - * Message to be shown when this field is required, but empty. - */ - @Override - public void setRequiredError(String requiredMessage) { - requiredError = requiredMessage; - markAsDirty(); - } - - @Override - public String getRequiredError() { - return requiredError; - } - - /** - * Gets the error that is shown if the field value cannot be converted to - * the data source type. - * - * @return The error that is shown if conversion of the field value fails - */ - public String getConversionError() { - return conversionError; - } - - /** - * Sets the error that is shown if the field value cannot be converted to - * the data source type. If {0} is present in the message, it will be - * replaced by the simple name of the data source type. If {1} is present in - * the message, it will be replaced by the ConversionException message. - * - * @param valueConversionError - * Message to be shown when conversion of the value fails - */ - public void setConversionError(String valueConversionError) { - this.conversionError = valueConversionError; - markAsDirty(); - } - - @Override - public boolean isEmpty() { - return (getFieldValue() == null); - } - - @Override - public void clear() { - setValue(null); - } - - /** - * Is automatic, visible validation enabled? - * - * If automatic validation is enabled, any validators connected to this - * component are evaluated while painting the component and potential error - * messages are sent to client. If the automatic validation is turned off, - * isValid() and validate() methods still work, but one must show the - * validation in their own code. - * - * @return True, if automatic validation is enabled. - */ - public boolean isValidationVisible() { - return validationVisible; - } - - /** - * Enable or disable automatic, visible validation. - * - * If automatic validation is enabled, any validators connected to this - * component are evaluated while painting the component and potential error - * messages are sent to client. If the automatic validation is turned off, - * isValid() and validate() methods still work, but one must show the - * validation in their own code. - * - * @param validateAutomatically - * True, if automatic validation is enabled. - */ - public void setValidationVisible(boolean validateAutomatically) { - if (validationVisible != validateAutomatically) { - markAsDirty(); - validationVisible = validateAutomatically; - } - } - - /** - * Sets the current buffered source exception. - * - * @param currentBufferedSourceException - */ - public void setCurrentBufferedSourceException( - Buffered.SourceException currentBufferedSourceException) { - this.currentBufferedSourceException = currentBufferedSourceException; - markAsDirty(); - } - - /** - * Gets the current buffered source exception. - * - * @return The current source exception - */ - protected Buffered.SourceException getCurrentBufferedSourceException() { - return currentBufferedSourceException; - } - - /** - * A ready-made {@link ShortcutListener} that focuses the given - * {@link Focusable} (usually a {@link Field}) when the keyboard shortcut is - * invoked. - * - */ - public static class FocusShortcut extends ShortcutListener { - protected Focusable focusable; - - /** - * Creates a keyboard shortcut for focusing the given {@link Focusable} - * using the shorthand notation defined in {@link ShortcutAction}. - * - * @param focusable - * to focused when the shortcut is invoked - * @param shorthandCaption - * caption with keycode and modifiers indicated - */ - public FocusShortcut(Focusable focusable, String shorthandCaption) { - super(shorthandCaption); - this.focusable = focusable; - } - - /** - * Creates a keyboard shortcut for focusing the given {@link Focusable}. - * - * @param focusable - * to focused when the shortcut is invoked - * @param keyCode - * keycode that invokes the shortcut - * @param modifiers - * modifiers required to invoke the shortcut - */ - public FocusShortcut(Focusable focusable, int keyCode, int... modifiers) { - super(null, keyCode, modifiers); - this.focusable = focusable; - } - - /** - * Creates a keyboard shortcut for focusing the given {@link Focusable}. - * - * @param focusable - * to focused when the shortcut is invoked - * @param keyCode - * keycode that invokes the shortcut - */ - public FocusShortcut(Focusable focusable, int keyCode) { - this(focusable, keyCode, null); - } - - @Override - public void handleAction(Object sender, Object target) { - focusable.focus(); - } - } - - private void updateValueFromDataSource() { - if (dataSource != null) { - - // Gets the correct value from datasource - T newFieldValue; - try { - - // Discards buffer by overwriting from datasource - newFieldValue = convertFromModel(getDataSourceValue()); - - // If successful, remove set the buffering state to be ok - if (getCurrentBufferedSourceException() != null) { - setCurrentBufferedSourceException(null); - } - } catch (final Throwable e) { - // FIXME: What should really be done here if conversion fails? - - // Sets the buffering state - currentBufferedSourceException = new Buffered.SourceException( - this, e); - markAsDirty(); - - // Throws the source exception - throw currentBufferedSourceException; - } - - final boolean wasModified = isModified(); - setModified(false); - - // If the new value differs from the previous one - if (!SharedUtil.equals(newFieldValue, getInternalValue())) { - setInternalValue(newFieldValue); - fireValueChange(false); - } else if (wasModified) { - // If the value did not change, but the modification status did - markAsDirty(); - } - } - } - - /** - * Gets the converter used to convert the property data source value to the - * field value. - * - * @return The converter or null if none is set. - */ - public Converter getConverter() { - return converter; - } - - /** - * Sets the converter used to convert the field value to property data - * source type. The converter must have a presentation type that matches the - * field type. - * - * @param converter - * The new converter to use. - */ - public void setConverter(Converter converter) { - this.converter = (Converter) converter; - markAsDirty(); - } - - @Override - protected AbstractFieldState getState() { - return (AbstractFieldState) super.getState(); - } - - @Override - protected AbstractFieldState getState(boolean markAsDirty) { - return (AbstractFieldState) super.getState(markAsDirty); - } - - @Override - public void beforeClientResponse(boolean initial) { - super.beforeClientResponse(initial); - - // Hide the error indicator if needed - getState().hideErrors = shouldHideErrors(); - } - - /** - * Registers this as an event listener for events sent by the data source - * (if any). Does nothing if - * isListeningToPropertyEvents == true. - */ - private void addPropertyListeners() { - if (!isListeningToPropertyEvents) { - if (dataSource instanceof Property.ValueChangeNotifier) { - ((Property.ValueChangeNotifier) dataSource).addListener(this); - } - if (dataSource instanceof Property.ReadOnlyStatusChangeNotifier) { - ((Property.ReadOnlyStatusChangeNotifier) dataSource) - .addListener(this); - } - isListeningToPropertyEvents = true; - } - } - - /** - * Stops listening to events sent by the data source (if any). Does nothing - * if isListeningToPropertyEvents == false. - */ - private void removePropertyListeners() { - if (isListeningToPropertyEvents) { - if (dataSource instanceof Property.ValueChangeNotifier) { - ((Property.ValueChangeNotifier) dataSource) - .removeListener(this); - } - if (dataSource instanceof Property.ReadOnlyStatusChangeNotifier) { - ((Property.ReadOnlyStatusChangeNotifier) dataSource) - .removeListener(this); - } - isListeningToPropertyEvents = false; - } - } - - /** - * {@inheritDoc} - *

- * Fields are automatically set to immediate if validators have been added. - */ - @Override - public boolean isImmediate() { - if (getExplicitImmediateValue() != null) { - return getExplicitImmediateValue(); - } - // Make field immediate when there is some kind of validation present - // (validator or required). This will avoid the UI being in a wrong - // state, e.g. user entered valid data but old validation error is still - // shown - return super.isImmediate() || !getValidators().isEmpty() - || isRequired(); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.AbstractComponent#readDesign(org.jsoup.nodes .Element, - * com.vaadin.ui.declarative.DesignContext) - */ - @Override - public void readDesign(Element design, DesignContext designContext) { - super.readDesign(design, designContext); - Attributes attr = design.attributes(); - if (design.hasAttr("readonly")) { - setReadOnly(DesignAttributeHandler.readAttribute("readonly", attr, - Boolean.class)); - } - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.AbstractComponent#getCustomAttributes() - */ - @Override - protected Collection getCustomAttributes() { - Collection attributes = super.getCustomAttributes(); - attributes.add("readonly"); - // must be handled by subclasses - attributes.add("value"); - attributes.add("converted-value"); - return attributes; - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.AbstractComponent#writeDesign(org.jsoup.nodes.Element - * , com.vaadin.ui.declarative.DesignContext) - */ - @Override - public void writeDesign(Element design, DesignContext designContext) { - super.writeDesign(design, designContext); - AbstractField def = (AbstractField) designContext - .getDefaultInstance(this); - Attributes attr = design.attributes(); - // handle readonly - DesignAttributeHandler.writeAttribute("readonly", attr, - super.isReadOnly(), def.isReadOnly(), Boolean.class); - } - - private static final Logger getLogger() { - return Logger.getLogger(AbstractField.class.getName()); - } -} diff --git a/server/src/main/java/com/vaadin/ui/AbstractSelect.java b/server/src/main/java/com/vaadin/ui/AbstractSelect.java index 882458c531..bf0e7274f4 100644 --- a/server/src/main/java/com/vaadin/ui/AbstractSelect.java +++ b/server/src/main/java/com/vaadin/ui/AbstractSelect.java @@ -47,6 +47,7 @@ import com.vaadin.event.dd.TargetDetailsImpl; import com.vaadin.event.dd.acceptcriteria.ClientSideCriterion; import com.vaadin.event.dd.acceptcriteria.ContainsDataFlavor; import com.vaadin.event.dd.acceptcriteria.TargetDetailIs; +import com.vaadin.legacy.ui.LegacyAbstractField; import com.vaadin.server.KeyMapper; import com.vaadin.server.PaintException; import com.vaadin.server.PaintTarget; @@ -78,7 +79,7 @@ import com.vaadin.ui.declarative.DesignFormatter; */ @SuppressWarnings("serial") // TODO currently cannot specify type more precisely in case of multi-select -public abstract class AbstractSelect extends AbstractField implements +public abstract class AbstractSelect extends LegacyAbstractField implements Container, Container.Viewer, Container.PropertySetChangeListener, Container.PropertySetChangeNotifier, Container.ItemSetChangeNotifier, Container.ItemSetChangeListener, LegacyComponent { @@ -646,7 +647,7 @@ public abstract class AbstractSelect extends AbstractField implements /** * Gets the selected item id or in multiselect mode a set of selected ids. * - * @see com.vaadin.ui.AbstractField#getValue() + * @see com.vaadin.legacy.ui.LegacyAbstractField#getValue() */ @Override public Object getValue() { @@ -686,7 +687,7 @@ public abstract class AbstractSelect extends AbstractField implements * * @param newValue * the New selected item or collection of selected items. - * @see com.vaadin.ui.AbstractField#setValue(java.lang.Object) + * @see com.vaadin.legacy.ui.LegacyAbstractField#setValue(java.lang.Object) */ @Override public void setValue(Object newValue) throws Property.ReadOnlyException { @@ -713,7 +714,7 @@ public abstract class AbstractSelect extends AbstractField implements * True if caller is sure that repaint is not needed. * @param ignoreReadOnly * True if read-only check should be omitted. - * @see com.vaadin.ui.AbstractField#setValue(java.lang.Object, + * @see com.vaadin.legacy.ui.LegacyAbstractField#setValue(java.lang.Object, * java.lang.Boolean) */ @Override @@ -1788,7 +1789,7 @@ public abstract class AbstractSelect extends AbstractField implements * For multi-selectable fields, also an empty collection of values is * considered to be an empty field. * - * @see AbstractField#isEmpty(). + * @see LegacyAbstractField#isEmpty(). */ @Override public boolean isEmpty() { @@ -1875,7 +1876,7 @@ public abstract class AbstractSelect extends AbstractField implements /** * Notifies the component that it is connected to an application. * - * @see com.vaadin.ui.AbstractField#attach() + * @see com.vaadin.legacy.ui.LegacyAbstractField#attach() */ @Override public void attach() { diff --git a/server/src/main/java/com/vaadin/ui/AbstractTextField.java b/server/src/main/java/com/vaadin/ui/AbstractTextField.java index 5fbe60937a..c3b911a56b 100644 --- a/server/src/main/java/com/vaadin/ui/AbstractTextField.java +++ b/server/src/main/java/com/vaadin/ui/AbstractTextField.java @@ -31,6 +31,7 @@ import com.vaadin.event.FieldEvents.FocusNotifier; import com.vaadin.event.FieldEvents.TextChangeEvent; import com.vaadin.event.FieldEvents.TextChangeListener; import com.vaadin.event.FieldEvents.TextChangeNotifier; +import com.vaadin.legacy.ui.LegacyAbstractField; import com.vaadin.server.PaintException; import com.vaadin.server.PaintTarget; import com.vaadin.shared.ui.textfield.AbstractTextFieldState; @@ -38,7 +39,7 @@ import com.vaadin.shared.ui.textfield.TextFieldConstants; import com.vaadin.ui.declarative.DesignAttributeHandler; import com.vaadin.ui.declarative.DesignContext; -public abstract class AbstractTextField extends AbstractField implements +public abstract class AbstractTextField extends LegacyAbstractField implements BlurNotifier, FocusNotifier, TextChangeNotifier, LegacyComponent { /** @@ -457,7 +458,7 @@ public abstract class AbstractTextField extends AbstractField implements * Make sure w reset lastKnownTextContent field on value change. The * clearing must happen here as well because TextChangeListener can * revert the original value. Client must respect the value in this - * case. AbstractField optimizes value change if the existing value is + * case. LegacyAbstractField optimizes value change if the existing value is * reset. Also we need to force repaint if the flag is on. */ if (lastKnownTextContent != null) { diff --git a/server/src/main/java/com/vaadin/ui/CheckBox.java b/server/src/main/java/com/vaadin/ui/CheckBox.java index 8b31edcbb4..e9e9b0d4b9 100644 --- a/server/src/main/java/com/vaadin/ui/CheckBox.java +++ b/server/src/main/java/com/vaadin/ui/CheckBox.java @@ -27,13 +27,14 @@ import com.vaadin.event.FieldEvents.BlurListener; import com.vaadin.event.FieldEvents.FocusAndBlurServerRpcImpl; import com.vaadin.event.FieldEvents.FocusEvent; import com.vaadin.event.FieldEvents.FocusListener; +import com.vaadin.legacy.ui.LegacyAbstractField; import com.vaadin.shared.MouseEventDetails; import com.vaadin.shared.ui.checkbox.CheckBoxServerRpc; import com.vaadin.shared.ui.checkbox.CheckBoxState; import com.vaadin.ui.declarative.DesignAttributeHandler; import com.vaadin.ui.declarative.DesignContext; -public class CheckBox extends AbstractField { +public class CheckBox extends LegacyAbstractField { private CheckBoxServerRpc rpc = new CheckBoxServerRpc() { @@ -129,8 +130,8 @@ public class CheckBox extends AbstractField { } /* - * Overridden to keep the shared state in sync with the AbstractField - * internal value. Should be removed once AbstractField is refactored to use + * Overridden to keep the shared state in sync with the LegacyAbstractField + * internal value. Should be removed once LegacyAbstractField is refactored to use * shared state. * * See tickets #10921 and #11064. diff --git a/server/src/main/java/com/vaadin/ui/Component.java b/server/src/main/java/com/vaadin/ui/Component.java index 5db48806c3..0e8b385128 100644 --- a/server/src/main/java/com/vaadin/ui/Component.java +++ b/server/src/main/java/com/vaadin/ui/Component.java @@ -24,6 +24,7 @@ import org.jsoup.nodes.Element; import com.vaadin.event.ConnectorEvent; import com.vaadin.event.ConnectorEventListener; import com.vaadin.event.FieldEvents; +import com.vaadin.legacy.ui.LegacyField; import com.vaadin.server.ClientConnector; import com.vaadin.server.ErrorMessage; import com.vaadin.server.Resource; @@ -378,7 +379,7 @@ public interface Component extends ClientConnector, Sizeable, Serializable { /** * Tests whether the component is in the read-only mode. The user can not - * change the value of a read-only component. As only {@link Field} + * change the value of a read-only component. As only {@link LegacyField} * components normally have a value that can be input or changed by the * user, this is mostly relevant only to field components, though not * restricted to them. @@ -405,7 +406,7 @@ public interface Component extends ClientConnector, Sizeable, Serializable { * can not change the value of a read-only component. * *

- * As only {@link Field} components normally have a value that can be input + * As only {@link LegacyField} components normally have a value that can be input * or changed by the user, this is mostly relevant only to field components, * though not restricted to them. *

@@ -1021,13 +1022,13 @@ public interface Component extends ClientConnector, Sizeable, Serializable { /** * A sub-interface implemented by components that can obtain input focus. - * This includes all {@link Field} components as well as some other + * This includes all {@link LegacyField} components as well as some other * components, such as {@link Upload}. * *

* Focus can be set with {@link #focus()}. This interface does not provide * an accessor that would allow finding out the currently focused component; - * focus information can be acquired for some (but not all) {@link Field} + * focus information can be acquired for some (but not all) {@link LegacyField} * components through the {@link com.vaadin.event.FieldEvents.FocusListener} * and {@link com.vaadin.event.FieldEvents.BlurListener} interfaces. *

@@ -1061,7 +1062,7 @@ public interface Component extends ClientConnector, Sizeable, Serializable { *

* Notice that this interface does not provide an accessor that would * allow finding out the currently focused component. Focus information - * can be acquired for some (but not all) {@link Field} components + * can be acquired for some (but not all) {@link LegacyField} components * through the {@link com.vaadin.event.FieldEvents.FocusListener} and * {@link com.vaadin.event.FieldEvents.BlurListener} interfaces. *

diff --git a/server/src/main/java/com/vaadin/ui/CustomField.java b/server/src/main/java/com/vaadin/ui/CustomField.java index 12f00ac23f..311a2069a3 100644 --- a/server/src/main/java/com/vaadin/ui/CustomField.java +++ b/server/src/main/java/com/vaadin/ui/CustomField.java @@ -20,9 +20,11 @@ import java.io.Serializable; import java.util.Iterator; import com.vaadin.data.Property; +import com.vaadin.legacy.ui.LegacyField; +import com.vaadin.legacy.ui.LegacyAbstractField; /** - * A {@link Field} whose UI content can be constructed by the user, enabling the + * A {@link LegacyField} whose UI content can be constructed by the user, enabling the * creation of e.g. form fields by composing Vaadin components. Customization of * both the visual presentation and the logic of the field is possible. * @@ -43,7 +45,7 @@ import com.vaadin.data.Property; * * @since 7.0 */ -public abstract class CustomField extends AbstractField implements +public abstract class CustomField extends LegacyAbstractField implements HasComponents { /** diff --git a/server/src/main/java/com/vaadin/ui/DateField.java b/server/src/main/java/com/vaadin/ui/DateField.java index 052539cd28..6ceae9962c 100644 --- a/server/src/main/java/com/vaadin/ui/DateField.java +++ b/server/src/main/java/com/vaadin/ui/DateField.java @@ -38,6 +38,8 @@ import com.vaadin.event.FieldEvents.BlurEvent; import com.vaadin.event.FieldEvents.BlurListener; import com.vaadin.event.FieldEvents.FocusEvent; import com.vaadin.event.FieldEvents.FocusListener; +import com.vaadin.legacy.ui.LegacyAbstractField; +import com.vaadin.legacy.ui.LegacyField; import com.vaadin.server.PaintException; import com.vaadin.server.PaintTarget; import com.vaadin.shared.ui.datefield.DateFieldConstants; @@ -52,20 +54,20 @@ import com.vaadin.ui.declarative.DesignContext; * compatible with java.util.Date. *

*

- * Since DateField extends AbstractField it implements - * the {@link com.vaadin.data.Buffered}interface. + * Since DateField extends LegacyAbstractField it + * implements the {@link com.vaadin.data.Buffered}interface. *

*

* A DateField is in write-through mode by default, so - * {@link com.vaadin.ui.AbstractField#setWriteThrough(boolean)}must be called to - * enable buffering. + * {@link com.vaadin.legacy.ui.LegacyAbstractField#setWriteThrough(boolean)}must + * be called to enable buffering. *

* * @author Vaadin Ltd. * @since 3.0 */ @SuppressWarnings("serial") -public class DateField extends AbstractField implements +public class DateField extends LegacyAbstractField implements FieldEvents.BlurNotifier, FieldEvents.FocusNotifier, LegacyComponent { /** @@ -152,7 +154,7 @@ public class DateField extends AbstractField implements private TimeZone timeZone = null; - private static Map variableNameForResolution = new HashMap(); + private static Map variableNameForResolution = new HashMap<>(); private String dateOutOfRangeMessage = "Date is out of allowed range"; @@ -485,7 +487,7 @@ public class DateField extends AbstractField implements || variables.containsKey("min") || variables.containsKey("sec") || variables.containsKey("msec") || variables - .containsKey("dateString"))) { + .containsKey("dateString"))) { // Old and new dates final Date oldDate = getValue(); @@ -497,7 +499,7 @@ public class DateField extends AbstractField implements // Gets the new date in parts boolean hasChanges = false; - Map calendarFieldChanges = new HashMap(); + Map calendarFieldChanges = new HashMap<>(); for (Resolution r : Resolution .getResolutionsHigherOrEqualTo(resolution)) { @@ -543,7 +545,8 @@ public class DateField extends AbstractField implements newDate = cal.getTime(); } - if (newDate == null && dateString != null && !"".equals(dateString)) { + if (newDate == null && dateString != null && !"".equals( + dateString)) { try { Date parsedDate = handleUnparsableDateString(dateString); setValue(parsedDate, true); @@ -731,7 +734,7 @@ public class DateField extends AbstractField implements Form f = (Form) parenOfDateField; Collection visibleItemProperties = f.getItemPropertyIds(); for (Object fieldId : visibleItemProperties) { - Field field = f.getField(fieldId); + LegacyField field = f.getField(fieldId); if (equals(field)) { /* * this datefield is logically in a form. Do the same @@ -813,7 +816,8 @@ public class DateField extends AbstractField implements // Start by a zeroed calendar to avoid having values for lower // resolution variables e.g. time when resolution is day int min, field; - for (Resolution r : Resolution.getResolutionsLowerThan(resolution)) { + for (Resolution r : Resolution.getResolutionsLowerThan( + resolution)) { field = r.getCalendarField(); min = calendar.getActualMinimum(field); calendar.set(field, min); @@ -981,7 +985,7 @@ public class DateField extends AbstractField implements * invalid if it contains text typed in by the user that couldn't be parsed * into a Date value. * - * @see com.vaadin.ui.AbstractField#validate() + * @see com.vaadin.legacy.ui.LegacyAbstractField#validate() */ @Override public void validate() throws InvalidValueException { diff --git a/server/src/main/java/com/vaadin/ui/DefaultFieldFactory.java b/server/src/main/java/com/vaadin/ui/DefaultFieldFactory.java index 535943bcd5..85ad1743ea 100644 --- a/server/src/main/java/com/vaadin/ui/DefaultFieldFactory.java +++ b/server/src/main/java/com/vaadin/ui/DefaultFieldFactory.java @@ -20,6 +20,7 @@ import java.util.Date; import com.vaadin.data.Container; import com.vaadin.data.Item; import com.vaadin.data.Property; +import com.vaadin.legacy.ui.LegacyField; import com.vaadin.shared.util.SharedUtil; /** @@ -49,21 +50,21 @@ public class DefaultFieldFactory implements FormFieldFactory, TableFieldFactory } @Override - public Field createField(Item item, Object propertyId, + public LegacyField createField(Item item, Object propertyId, Component uiContext) { Class type = item.getItemProperty(propertyId).getType(); - Field field = createFieldByPropertyType(type); + LegacyField field = createFieldByPropertyType(type); field.setCaption(createCaptionByPropertyId(propertyId)); return field; } @Override - public Field createField(Container container, Object itemId, + public LegacyField createField(Container container, Object itemId, Object propertyId, Component uiContext) { Property containerProperty = container.getContainerProperty(itemId, propertyId); Class type = containerProperty.getType(); - Field field = createFieldByPropertyType(type); + LegacyField field = createFieldByPropertyType(type); field.setCaption(createCaptionByPropertyId(propertyId)); return field; } @@ -93,9 +94,9 @@ public class DefaultFieldFactory implements FormFieldFactory, TableFieldFactory * * @param type * the type of the property - * @return the most suitable generic {@link Field} for given type + * @return the most suitable generic {@link LegacyField} for given type */ - public static Field createFieldByPropertyType(Class type) { + public static LegacyField createFieldByPropertyType(Class type) { // Null typed properties can not be edited if (type == null) { return null; diff --git a/server/src/main/java/com/vaadin/ui/Field.java b/server/src/main/java/com/vaadin/ui/Field.java deleted file mode 100644 index 8a9acd570f..0000000000 --- a/server/src/main/java/com/vaadin/ui/Field.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright 2000-2014 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.ui; - -import com.vaadin.data.BufferedValidatable; -import com.vaadin.data.Property; -import com.vaadin.ui.Component.Focusable; - -/** - * Field interface is implemented by all classes (field components) that have a - * value that the user can change through the user interface. - * - * Field components are built upon the framework defined in the Field interface - * and the {@link com.vaadin.AbstractField} base class. - * - * The Field interface inherits the {@link com.vaadin.ui.Component} - * superinterface and also the {@link com.vaadin.ui.Property} interface to have - * a value for the field. - * - * - * @author Vaadin Ltd. - * - * @param T - * the type of values in the field, which might not be the same type - * as that of the data source if converters are used - * - * @author IT Mill Ltd. - */ -public interface Field extends Component, BufferedValidatable, Property, - Property.ValueChangeNotifier, Property.ValueChangeListener, - Property.Editor, Focusable { - - /** - * Is this field required. - * - * Required fields must filled by the user. - * - * @return true if the field is required,otherwise - * false. - * @since 3.1 - */ - public boolean isRequired(); - - /** - * Sets the field required. Required fields must filled by the user. - * - * @param required - * Is the field required. - * @since 3.1 - */ - public void setRequired(boolean required); - - /** - * Sets the error message to be displayed if a required field is empty. - * - * @param requiredMessage - * Error message. - * @since 5.2.6 - */ - public void setRequiredError(String requiredMessage); - - /** - * Gets the error message that is to be displayed if a required field is - * empty. - * - * @return Error message. - * @since 5.2.6 - */ - public String getRequiredError(); - - /** - * An Event object specifying the Field whose value has been - * changed. - * - * @author Vaadin Ltd. - * @since 3.0 - */ - @SuppressWarnings("serial") - public static class ValueChangeEvent extends Component.Event implements - Property.ValueChangeEvent { - - /** - * Constructs a new event object with the specified source field object. - * - * @param source - * the field that caused the event. - */ - public ValueChangeEvent(Field source) { - super(source); - } - - /** - * Gets the Property which triggered the event. - * - * @return the Source Property of the event. - */ - @Override - public Property getProperty() { - return (Property) getSource(); - } - } - - /** - * Is the field empty? - * - * In general, "empty" state is same as null. As an exception, TextField - * also treats empty string as "empty". - * - * @since 7.4 - * @return true if the field is empty, false otherwise - */ - public boolean isEmpty(); - - /** - * Clears the value of the field. - *

- * The field value is typically reset to the initial value of the field. - * Calling {@link #isEmpty()} on a cleared field must always returns true. - * - * @since 7.4 - */ - public void clear(); - -} diff --git a/server/src/main/java/com/vaadin/ui/Form.java b/server/src/main/java/com/vaadin/ui/Form.java index 45532756e5..606f6ee5f9 100644 --- a/server/src/main/java/com/vaadin/ui/Form.java +++ b/server/src/main/java/com/vaadin/ui/Form.java @@ -36,6 +36,8 @@ import com.vaadin.event.Action; import com.vaadin.event.Action.Handler; import com.vaadin.event.Action.ShortcutNotifier; import com.vaadin.event.ActionManager; +import com.vaadin.legacy.ui.LegacyAbstractField; +import com.vaadin.legacy.ui.LegacyField; import com.vaadin.server.AbstractErrorMessage; import com.vaadin.server.CompositeErrorMessage; import com.vaadin.server.ErrorMessage; @@ -48,7 +50,7 @@ import com.vaadin.shared.ui.form.FormState; * Form component provides easy way of creating and managing sets fields. * *

- * Form is a container for fields implementing {@link Field} + * Form is a container for fields implementing {@link LegacyField} * interface. It provides support for any layouts and provides buffering * interface for easy connection of commit and discard buttons. All the form * fields can be customized by adding validators, setting captions and icons, @@ -76,7 +78,7 @@ import com.vaadin.shared.ui.form.FormState; * more flexibility. */ @Deprecated -public class Form extends AbstractField implements Item.Editor, +public class Form extends LegacyAbstractField implements Item.Editor, Buffered, Item, Validatable, Action.Notifier, HasComponents, LegacyComponent { @@ -90,7 +92,7 @@ public class Form extends AbstractField implements Item.Editor, /** * Ordered list of property ids in this editor. */ - private final LinkedList propertyIds = new LinkedList(); + private final LinkedList propertyIds = new LinkedList<>(); /** * Current buffered source exception. @@ -105,12 +107,12 @@ public class Form extends AbstractField implements Item.Editor, /** * Mapping from propertyName to corresponding field. */ - private final HashMap> fields = new HashMap>(); + private final HashMap> fields = new HashMap<>(); /** * Form may act as an Item, its own properties are stored here. */ - private final HashMap> ownProperties = new HashMap>(); + private final HashMap> ownProperties = new HashMap<>(); /** * Field factory for this form. @@ -131,7 +133,8 @@ public class Form extends AbstractField implements Item.Editor, */ private final ValueChangeListener fieldValueChangeListener = new ValueChangeListener() { @Override - public void valueChange(com.vaadin.data.Property.ValueChangeEvent event) { + public void valueChange( + com.vaadin.data.Property.ValueChangeEvent event) { markAsDirty(); } }; @@ -147,9 +150,9 @@ public class Form extends AbstractField implements Item.Editor, /** * Keeps track of the Actions added to this component, and manages the - * painting and handling as well. Note that the extended AbstractField is a - * {@link ShortcutNotifier} and has a actionManager that delegates actions - * to the containing window. This one does not delegate. + * painting and handling as well. Note that the extended LegacyAbstractField + * is a {@link ShortcutNotifier} and has a actionManager that delegates + * actions to the containing window. This one does not delegate. */ private ActionManager ownActionManager = new ActionManager(this); @@ -236,7 +239,8 @@ public class Form extends AbstractField implements Item.Editor, // getErrorMessage() recursively instead of validate(). ErrorMessage validationError = null; if (isValidationVisible()) { - for (final Iterator i = propertyIds.iterator(); i.hasNext();) { + for (final Iterator i = propertyIds.iterator(); i + .hasNext();) { Object f = fields.get(i.next()); if (f instanceof AbstractComponent) { AbstractComponent field = (AbstractComponent) f; @@ -248,7 +252,8 @@ public class Form extends AbstractField implements Item.Editor, validationError = new UserError(field.getCaption()); } break; - } else if (f instanceof Field && !((Field) f).isValid()) { + } else if (f instanceof LegacyField && !((LegacyField) f) + .isValid()) { // Something is wrong with the field, but no proper // error is given. Generate one. validationError = new UserError(field.getCaption()); @@ -270,7 +275,8 @@ public class Form extends AbstractField implements Item.Editor, getComponentError(), validationError, AbstractErrorMessage - .getErrorMessageForException(currentBufferedSourceException) }); + .getErrorMessageForException( + currentBufferedSourceException) }); } /** @@ -308,7 +314,8 @@ public class Form extends AbstractField implements Item.Editor, * use the default one from the interface. */ @Override - public void commit() throws Buffered.SourceException, InvalidValueException { + public void commit() throws Buffered.SourceException, + InvalidValueException { LinkedList problems = null; @@ -329,14 +336,14 @@ public class Form extends AbstractField implements Item.Editor, // Try to commit all for (final Iterator i = propertyIds.iterator(); i.hasNext();) { try { - final Field f = (fields.get(i.next())); + final LegacyField f = (fields.get(i.next())); // Commit only non-readonly fields. if (!f.isReadOnly()) { f.commit(); } } catch (final Buffered.SourceException e) { if (problems == null) { - problems = new LinkedList(); + problems = new LinkedList<>(); } problems.add(e); } @@ -380,7 +387,7 @@ public class Form extends AbstractField implements Item.Editor, (fields.get(i.next())).discard(); } catch (final Buffered.SourceException e) { if (problems == null) { - problems = new LinkedList(); + problems = new LinkedList<>(); } problems.add(e); } @@ -416,7 +423,7 @@ public class Form extends AbstractField implements Item.Editor, @Override public boolean isModified() { for (final Iterator i = propertyIds.iterator(); i.hasNext();) { - final Field f = fields.get(i.next()); + final LegacyField f = fields.get(i.next()); if (f != null && f.isModified()) { return true; } @@ -433,7 +440,8 @@ public class Form extends AbstractField implements Item.Editor, public void setBuffered(boolean buffered) { if (buffered != this.buffered) { this.buffered = buffered; - for (final Iterator i = propertyIds.iterator(); i.hasNext();) { + for (final Iterator i = propertyIds.iterator(); i + .hasNext();) { (fields.get(i.next())).setBuffered(buffered); } } @@ -461,7 +469,7 @@ public class Form extends AbstractField implements Item.Editor, ownProperties.put(id, property); // Gets suitable field - final Field field = fieldFactory.createField(this, id, this); + final LegacyField field = fieldFactory.createField(this, id, this); if (field == null) { return false; } @@ -484,7 +492,7 @@ public class Form extends AbstractField implements Item.Editor, * *

* This field is added to the layout using the - * {@link #attachField(Object, Field)} method. + * {@link #attachField(Object, LegacyField)} method. *

* * @param propertyId @@ -492,7 +500,7 @@ public class Form extends AbstractField implements Item.Editor, * @param field * the field which should be added to the form. */ - public void addField(Object propertyId, Field field) { + public void addField(Object propertyId, LegacyField field) { registerField(propertyId, field); attachField(propertyId, field); markAsDirty(); @@ -510,9 +518,9 @@ public class Form extends AbstractField implements Item.Editor, * @param propertyId * the Property id of the field. * @param field - * the Field that should be registered + * the LegacyField that should be registered */ - private void registerField(Object propertyId, Field field) { + private void registerField(Object propertyId, LegacyField field) { if (propertyId == null || field == null) { return; } @@ -550,7 +558,7 @@ public class Form extends AbstractField implements Item.Editor, * @param propertyId * @param field */ - protected void attachField(Object propertyId, Field field) { + protected void attachField(Object propertyId, LegacyField field) { if (propertyId == null || field == null) { return; } @@ -577,7 +585,7 @@ public class Form extends AbstractField implements Item.Editor, */ @Override public Property getItemProperty(Object id) { - final Field field = fields.get(id); + final LegacyField field = fields.get(id); if (field == null) { // field does not exist or it is not (yet) created for this property return ownProperties.get(id); @@ -597,7 +605,7 @@ public class Form extends AbstractField implements Item.Editor, * @param propertyId * the id of the property. */ - public Field getField(Object propertyId) { + public LegacyField getField(Object propertyId) { return fields.get(propertyId); } @@ -616,7 +624,7 @@ public class Form extends AbstractField implements Item.Editor, public boolean removeItemProperty(Object id) { ownProperties.remove(id); - final Field field = fields.get(id); + final LegacyField field = fields.get(id); if (field != null) { propertyIds.remove(id); @@ -640,7 +648,7 @@ public class Form extends AbstractField implements Item.Editor, * @param field * the field to be detached from the forms layout. */ - protected void detachField(final Field field) { + protected void detachField(final LegacyField field) { Component p = field.getParent(); if (p instanceof ComponentContainer) { ((ComponentContainer) p).removeComponent(field); @@ -701,7 +709,8 @@ public class Form extends AbstractField implements Item.Editor, * * @see com.vaadin.data.Item.Viewer#setItemDataSource(Item) */ - public void setItemDataSource(Item newDataSource, Collection propertyIds) { + public void setItemDataSource(Item newDataSource, + Collection propertyIds) { if (getLayout() instanceof GridLayout) { GridLayout gl = (GridLayout) getLayout(); @@ -733,7 +742,8 @@ public class Form extends AbstractField implements Item.Editor, final Object id = i.next(); final Property property = itemDatasource.getItemProperty(id); if (id != null && property != null) { - final Field f = fieldFactory.createField(itemDatasource, id, + final LegacyField f = fieldFactory.createField( + itemDatasource, id, this); if (f != null) { bindPropertyToField(id, property, f); @@ -745,7 +755,7 @@ public class Form extends AbstractField implements Item.Editor, /** * Binds an item property to a field. The default behavior is to bind - * property straight to Field. If Property.Viewer type property (e.g. + * property straight to LegacyField. If Property.Viewer type property (e.g. * PropertyFormatter) is already set for field, the property is bound to * that Property.Viewer. * @@ -755,7 +765,7 @@ public class Form extends AbstractField implements Item.Editor, * @since 6.7.3 */ protected void bindPropertyToField(final Object propertyId, - final Property property, final Field field) { + final Property property, final LegacyField field) { // check if field has a property that is Viewer set. In that case we // expect developer has e.g. PropertyFormatter that he wishes to use and // assign the property to the Viewer instead. @@ -808,7 +818,7 @@ public class Form extends AbstractField implements Item.Editor, if (getLayout() != null) { final Object[] properties = propertyIds.toArray(); for (int i = 0; i < properties.length; i++) { - Field f = getField(properties[i]); + LegacyField f = getField(properties[i]); detachField(f); if (layout instanceof CustomLayout) { ((CustomLayout) layout).addComponent(f, @@ -857,10 +867,11 @@ public class Form extends AbstractField implements Item.Editor, } // Gets the old field - final Field oldField = fields.get(propertyId); + final LegacyField oldField = fields.get(propertyId); if (oldField == null) { - throw new IllegalArgumentException("Field with given propertyid '" - + propertyId.toString() + "' can not be found."); + throw new IllegalArgumentException( + "Field with given propertyid '" + + propertyId.toString() + "' can not be found."); } final Object value = oldField.getPropertyDataSource() == null ? oldField .getValue() : oldField.getPropertyDataSource().getValue(); @@ -877,8 +888,9 @@ public class Form extends AbstractField implements Item.Editor, } if (value != null && !found) { if (value instanceof Collection) { - for (final Iterator it = ((Collection) value).iterator(); it - .hasNext();) { + for (final Iterator it = ((Collection) value) + .iterator(); it + .hasNext();) { final Object val = it.next(); found = false; for (int i = 0; i < values.length && !found; i++) { @@ -1000,7 +1012,7 @@ public class Form extends AbstractField implements Item.Editor, * * @param fieldFactory * the new factory used to create the fields. - * @see Field + * @see LegacyField * @see FormFieldFactory */ public void setFormFieldFactory(FormFieldFactory fieldFactory) { @@ -1019,7 +1031,7 @@ public class Form extends AbstractField implements Item.Editor, /** * Gets the field type. * - * @see com.vaadin.ui.AbstractField#getType() + * @see com.vaadin.legacy.ui.LegacyAbstractField#getType() */ @Override public Class getType() { @@ -1032,9 +1044,9 @@ public class Form extends AbstractField implements Item.Editor, /** * Sets the internal value. * - * This is relevant when the Form is used as Field. + * This is relevant when the Form is used as LegacyField. * - * @see com.vaadin.ui.AbstractField#setInternalValue(java.lang.Object) + * @see com.vaadin.legacy.ui.LegacyAbstractField#setInternalValue(java.lang.Object) */ @Override protected void setInternalValue(Object newValue) { @@ -1056,14 +1068,14 @@ public class Form extends AbstractField implements Item.Editor, * non-read-only fields, the first one of them is returned. Otherwise, the * field for the first property (or null if none) is returned. * - * @return the Field. + * @return the LegacyField. */ - private Field getFirstFocusableField() { + private LegacyField getFirstFocusableField() { Collection itemPropertyIds = getItemPropertyIds(); if (itemPropertyIds != null && itemPropertyIds.size() > 0) { for (Object id : itemPropertyIds) { if (id != null) { - Field field = getField(id); + LegacyField field = getField(id); if (field.isConnectorEnabled() && !field.isReadOnly()) { return field; } @@ -1094,7 +1106,7 @@ public class Form extends AbstractField implements Item.Editor, if (data instanceof Item) { item = (Item) data; } else if (data != null) { - item = new BeanItem(data); + item = new BeanItem<>(data); } // Sets the datasource to form @@ -1138,7 +1150,7 @@ public class Form extends AbstractField implements Item.Editor, * the visibleProperties to set. */ public void setVisibleItemProperties(Object... visibleProperties) { - LinkedList v = new LinkedList(); + LinkedList v = new LinkedList<>(); for (int i = 0; i < visibleProperties.length; i++) { v.add(visibleProperties[i]); } @@ -1152,7 +1164,7 @@ public class Form extends AbstractField implements Item.Editor, */ @Override public void focus() { - final Field f = getFirstFocusableField(); + final LegacyField f = getFirstFocusableField(); if (f != null) { f.focus(); } @@ -1166,7 +1178,8 @@ public class Form extends AbstractField implements Item.Editor, @Override public void setTabIndex(int tabIndex) { super.setTabIndex(tabIndex); - for (final Iterator i = getItemPropertyIds().iterator(); i.hasNext();) { + for (final Iterator i = getItemPropertyIds().iterator(); i + .hasNext();) { (getField(i.next())).setTabIndex(tabIndex); } } @@ -1178,8 +1191,9 @@ public class Form extends AbstractField implements Item.Editor, @Override public void setImmediate(boolean immediate) { super.setImmediate(immediate); - for (Iterator> i = fields.values().iterator(); i.hasNext();) { - Field f = i.next(); + for (Iterator> i = fields.values().iterator(); i + .hasNext();) { + LegacyField f = i.next(); if (f instanceof AbstractComponent) { ((AbstractComponent) f).setImmediate(immediate); } @@ -1195,10 +1209,11 @@ public class Form extends AbstractField implements Item.Editor, @Override public boolean isEmpty() { - for (Iterator> i = fields.values().iterator(); i.hasNext();) { - Field f = i.next(); - if (f instanceof AbstractField) { - if (!((AbstractField) f).isEmpty()) { + for (Iterator> i = fields.values().iterator(); i + .hasNext();) { + LegacyField f = i.next(); + if (f instanceof LegacyAbstractField) { + if (!((LegacyAbstractField) f).isEmpty()) { return false; } } @@ -1214,10 +1229,11 @@ public class Form extends AbstractField implements Item.Editor, */ @Override public void clear() { - for (Iterator> i = fields.values().iterator(); i.hasNext();) { - Field f = i.next(); - if (f instanceof AbstractField) { - ((AbstractField) f).clear(); + for (Iterator> i = fields.values().iterator(); i + .hasNext();) { + LegacyField f = i.next(); + if (f instanceof LegacyAbstractField) { + ((LegacyAbstractField) f).clear(); } } } @@ -1279,9 +1295,10 @@ public class Form extends AbstractField implements Item.Editor, * Gets the {@link ActionManager} responsible for handling {@link Action}s * added to this Form.
* Note that Form has another ActionManager inherited from - * {@link AbstractField}. The ownActionManager handles Actions attached to - * this Form specifically, while the ActionManager in AbstractField - * delegates to the containing Window (i.e global Actions). + * {@link LegacyAbstractField}. The ownActionManager handles Actions + * attached to this Form specifically, while the ActionManager in + * LegacyAbstractField delegates to the containing Window (i.e global + * Actions). * * @return */ diff --git a/server/src/main/java/com/vaadin/ui/FormFieldFactory.java b/server/src/main/java/com/vaadin/ui/FormFieldFactory.java index 124e0fcb9a..5483b7a904 100644 --- a/server/src/main/java/com/vaadin/ui/FormFieldFactory.java +++ b/server/src/main/java/com/vaadin/ui/FormFieldFactory.java @@ -19,6 +19,7 @@ import java.io.Serializable; import com.vaadin.data.Item; import com.vaadin.data.fieldgroup.FieldGroup; +import com.vaadin.legacy.ui.LegacyField; /** * Factory interface for creating new Field-instances based on {@link Item}, @@ -49,7 +50,8 @@ public interface FormFieldFactory extends Serializable { * is {@link Form}. uiContext will not necessary be the parent * component of the field, but the one that is responsible for * creating it. - * @return Field the field suitable for editing the specified data. + * @return the field suitable for editing the specified data. */ - Field createField(Item item, Object propertyId, Component uiContext); + LegacyField createField(Item item, Object propertyId, + Component uiContext); } diff --git a/server/src/main/java/com/vaadin/ui/Grid.java b/server/src/main/java/com/vaadin/ui/Grid.java index 388d74aeee..09a3eecb73 100644 --- a/server/src/main/java/com/vaadin/ui/Grid.java +++ b/server/src/main/java/com/vaadin/ui/Grid.java @@ -73,6 +73,7 @@ import com.vaadin.event.SelectionEvent.SelectionNotifier; import com.vaadin.event.SortEvent; import com.vaadin.event.SortEvent.SortListener; import com.vaadin.event.SortEvent.SortNotifier; +import com.vaadin.legacy.ui.LegacyField; import com.vaadin.server.AbstractClientConnector; import com.vaadin.server.AbstractExtension; import com.vaadin.server.EncodeResult; @@ -157,14 +158,14 @@ import elemental.json.JsonValue; *

Selection Modes and Models

*

* Grid supports three selection {@link SelectionMode modes} (single, - * multi, none), and comes bundled with one - * {@link SelectionModel model} for each of the modes. The distinction - * between a selection mode and selection model is as follows: a mode - * essentially says whether you can have one, many or no rows selected. The - * model, however, has the behavioral details of each. A single selection model - * may require that the user deselects one row before selecting another one. A - * variant of a multiselect might have a configurable maximum of rows that may - * be selected. And so on. + * multi, none), and comes bundled with one {@link SelectionModel + * model} for each of the modes. The distinction between a selection mode + * and selection model is as follows: a mode essentially says whether + * you can have one, many or no rows selected. The model, however, has the + * behavioral details of each. A single selection model may require that the + * user deselects one row before selecting another one. A variant of a + * multiselect might have a configurable maximum of rows that may be selected. + * And so on. *

*

  * Grid grid = new Grid(myContainer);
@@ -319,19 +320,19 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
          * client. Details components get destroyed once they scroll out of
          * view.
          */
-        private final Map itemIdToDetailsComponent = new HashMap();
+        private final Map itemIdToDetailsComponent = new HashMap<>();
 
         /**
          * Set of item ids that got null from DetailsGenerator when
          * {@link DetailsGenerator#getDetails(RowReference)} was called.
          */
-        private final Set emptyDetails = new HashSet();
+        private final Set emptyDetails = new HashSet<>();
 
         /**
          * Set of item IDs for all open details rows. Contains even the ones
          * that are not currently visible on the client.
          */
-        private final Set openDetails = new HashSet();
+        private final Set openDetails = new HashSet<>();
 
         public DetailComponentManager(Grid grid) {
             this(grid, DetailsGenerator.NULL);
@@ -416,7 +417,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
          * Recreates all visible details components.
          */
         public void refreshDetails() {
-            Set visibleItemIds = new HashSet(
+            Set visibleItemIds = new HashSet<>(
                     itemIdToDetailsComponent.keySet());
             for (Object itemId : visibleItemIds) {
                 destroyDetails(itemId);
@@ -540,7 +541,8 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
         }
 
         @Override
-        protected  T build(String caption, Class dataType,
+        protected  T build(String caption,
+                Class dataType,
                 Class fieldType) throws BindException {
             T field = super.build(caption, dataType, fieldType);
             if (field instanceof CheckBox) {
@@ -573,7 +575,8 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
         }
 
         @Override
-        public  T createField(Class type, Class fieldType) {
+        public  T createField(Class type,
+                Class fieldType) {
             T f = super.createField(type, fieldType);
             if (f != null) {
                 f.setWidth("100%");
@@ -691,7 +694,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
 
         private CommitException cause;
 
-        private Set errorColumns = new HashSet();
+        private Set errorColumns = new HashSet<>();
 
         private String userErrorMessage;
 
@@ -980,17 +983,17 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
 
         @Override
         public void commitError(CommitErrorEvent event) {
-            Map, InvalidValueException> invalidFields = event
+            Map, InvalidValueException> invalidFields = event
                     .getCause().getInvalidFields();
 
             if (!invalidFields.isEmpty()) {
                 Object firstErrorPropertyId = null;
-                Field firstErrorField = null;
+                LegacyField firstErrorField = null;
 
                 FieldGroup fieldGroup = event.getCause().getFieldGroup();
                 for (Column column : getColumns()) {
                     Object propertyId = column.getPropertyId();
-                    Field field = fieldGroup.getField(propertyId);
+                    LegacyField field = fieldGroup.getField(propertyId);
                     if (invalidFields.keySet().contains(field)) {
                         event.addErrorColumn(column);
 
@@ -1018,10 +1021,10 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
         }
 
         private Object getFirstPropertyId(FieldGroup fieldGroup,
-                Set> keySet) {
+                Set> keySet) {
             for (Column c : getColumns()) {
                 Object propertyId = c.getPropertyId();
-                Field f = fieldGroup.getField(propertyId);
+                LegacyField f = fieldGroup.getField(propertyId);
                 if (keySet.contains(f)) {
                     return propertyId;
                 }
@@ -1339,7 +1342,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
      */
     public static abstract class AbstractSelectionModel extends
             AbstractGridExtension implements SelectionModel, DataGenerator {
-        protected final LinkedHashSet selection = new LinkedHashSet();
+        protected final LinkedHashSet selection = new LinkedHashSet<>();
 
         @Override
         public boolean isSelected(final Object itemId) {
@@ -1348,7 +1351,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
 
         @Override
         public Collection getSelectedRows() {
-            return new ArrayList(selection);
+            return new ArrayList<>(selection);
         }
 
         @Override
@@ -1586,7 +1589,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
 
                 @Override
                 public void select(List rowKeys) {
-                    List items = new ArrayList();
+                    List items = new ArrayList<>();
                     for (String rowKey : rowKeys) {
                         items.add(getItemId(rowKey));
                     }
@@ -1595,7 +1598,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
 
                 @Override
                 public void deselect(List rowKeys) {
-                    List items = new ArrayList();
+                    List items = new ArrayList<>();
                     for (String rowKey : rowKeys) {
                         items.add(getItemId(rowKey));
                     }
@@ -1649,7 +1652,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
             final boolean selectionWillChange = !selection.containsAll(itemIds)
                     && selection.size() < selectionLimit;
             if (selectionWillChange) {
-                final HashSet oldSelection = new HashSet(
+                final HashSet oldSelection = new HashSet<>(
                         selection);
                 if (selection.size() + itemIds.size() >= selectionLimit) {
                     // Add one at a time if there's a risk of overflow
@@ -1728,7 +1731,8 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
             return deselect(itemIds, true);
         }
 
-        protected boolean deselect(final Collection itemIds, boolean refresh) {
+        protected boolean deselect(final Collection itemIds,
+                boolean refresh) {
             if (itemIds == null) {
                 throw new IllegalArgumentException("itemIds may not be null");
             }
@@ -1736,7 +1740,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
             final boolean hasCommonElements = !Collections.disjoint(itemIds,
                     selection);
             if (hasCommonElements) {
-                final HashSet oldSelection = new HashSet(
+                final HashSet oldSelection = new HashSet<>(
                         selection);
                 selection.removeAll(itemIds);
                 fireSelectionEvent(oldSelection, selection);
@@ -1820,7 +1824,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
             checkItemIdsExist(itemIds);
 
             boolean changed = false;
-            Set selectedRows = new HashSet(itemIds);
+            Set selectedRows = new HashSet<>(itemIds);
             final Collection oldSelection = getSelectedRows();
             Set added = getDifference(selectedRows, selection);
             if (!added.isEmpty()) {
@@ -1861,7 +1865,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
          */
         private static Set getDifference(Set set1,
                 Set set2) {
-            Set diff = new HashSet(set1);
+            Set diff = new HashSet<>(set1);
             diff.removeAll(set2);
             return diff;
         }
@@ -2162,7 +2166,8 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
 
             if (cellDescriptionGenerator != null
                     && cellDescriptions.keys().length > 0) {
-                rowData.put(GridState.JSONKEY_CELLDESCRIPTION, cellDescriptions);
+                rowData.put(GridState.JSONKEY_CELLDESCRIPTION,
+                        cellDescriptions);
             }
 
             if (cellStyleGenerator != null && cellStyles.keys().length > 0) {
@@ -2229,8 +2234,8 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
 
             private RowState rowState = new RowState();
             protected StaticSection section;
-            private Map cells = new LinkedHashMap();
-            private Map, CELLTYPE> cellGroups = new HashMap, CELLTYPE>();
+            private Map cells = new LinkedHashMap<>();
+            private Map, CELLTYPE> cellGroups = new HashMap<>();
 
             protected StaticRow(StaticSection section) {
                 this.section = section;
@@ -2238,7 +2243,8 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
 
             protected void addCell(Object propertyId) {
                 CELLTYPE cell = createCell();
-                cell.setColumnId(section.grid.getColumn(propertyId).getState().id);
+                cell.setColumnId(section.grid.getColumn(propertyId)
+                        .getState().id);
                 cells.put(propertyId, cell);
                 rowState.cells.add(cell.getCellState());
             }
@@ -2314,7 +2320,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
             public CELLTYPE join(Object... propertyIds) {
                 assert propertyIds.length > 1 : "You need to merge at least 2 properties";
 
-                Set cells = new HashSet();
+                Set cells = new HashSet<>();
                 for (int i = 0; i < propertyIds.length; ++i) {
                     cells.add(getCell(propertyIds[i]));
                 }
@@ -2332,7 +2338,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
             public CELLTYPE join(CELLTYPE... cells) {
                 assert cells.length > 1 : "You need to merge at least 2 cells";
 
-                return join(new HashSet(Arrays.asList(cells)));
+                return join(new HashSet<>(Arrays.asList(cells)));
             }
 
             protected CELLTYPE join(Set cells) {
@@ -2349,7 +2355,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
                 // Create new cell data for the group
                 CELLTYPE newCell = createCell();
 
-                Set columnGroup = new HashSet();
+                Set columnGroup = new HashSet<>();
                 for (CELLTYPE cell : cells) {
                     columnGroup.add(cell.getColumnId());
                 }
@@ -2398,7 +2404,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
              */
             protected void writeDesign(Element trElement,
                     DesignContext designContext) {
-                Set visited = new HashSet();
+                Set visited = new HashSet<>();
                 for (Grid.Column column : section.grid.getColumns()) {
                     CELLTYPE cell = getCell(column.getPropertyId());
                     if (visited.contains(cell)) {
@@ -2450,7 +2456,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
                     int colspan = DesignAttributeHandler.readAttribute(
                             "colspan", element.attributes(), 1, int.class);
 
-                    Set cells = new HashSet();
+                    Set cells = new HashSet<>();
                     for (int c = 0; c < colspan; ++c) {
                         cells.add(getCell(section.grid.getColumns()
                                 .get(columnIndex + c).getPropertyId()));
@@ -2687,7 +2693,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
         }
 
         protected Grid grid;
-        protected List rows = new ArrayList();
+        protected List rows = new ArrayList<>();
 
         /**
          * Sets the visibility of the whole section.
@@ -3106,7 +3112,8 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
         }
 
         @Override
-        protected void readDesign(Element trElement, DesignContext designContext) {
+        protected void readDesign(Element trElement,
+                DesignContext designContext) {
             super.readDesign(trElement, designContext);
 
             boolean defaultRow = DesignAttributeHandler.readAttribute(
@@ -3656,7 +3663,8 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
                                     + toString()
                                     + " sortable. The Container of Grid does not implement Sortable");
                 } else if (!((Sortable) grid.datasource)
-                        .getSortableContainerPropertyIds().contains(propertyId)) {
+                        .getSortableContainerPropertyIds().contains(
+                                propertyId)) {
                     throw new IllegalStateException(
                             "Can't set column "
                                     + toString()
@@ -3786,8 +3794,8 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
         /**
          * Sets the maximum width for this column.
          * 

- * This defines the maximum allowed pixel width of the column - * when it is set to expand. + * This defines the maximum allowed pixel width of the column when + * it is set to expand. * * @param pixels * the maximum width @@ -3882,7 +3890,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, * the editor field * @return this column */ - public Column setEditorField(Field editor) { + public Column setEditorField(LegacyField editor) { grid.setEditorField(getPropertyId(), editor); return this; } @@ -3910,7 +3918,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, * if no field has been configured and there is a problem * building or binding */ - public Field getEditorField() { + public LegacyField getEditorField() { return grid.getEditorField(getPropertyId()); } @@ -4020,7 +4028,8 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, * @param designContext * the design context */ - protected void writeDesign(Element design, DesignContext designContext) { + protected void writeDesign(Element design, + DesignContext designContext) { Attributes attributes = design.attributes(); GridColumnState def = new GridColumnState(); @@ -4222,7 +4231,8 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, * @return an encoded value ready to be sent to the client */ public static JsonValue encodeValue(Object modelValue, - Renderer renderer, Converter converter, Locale locale) { + Renderer renderer, Converter converter, + Locale locale) { Class presentationType = renderer.getPresentationType(); T presentationValue; @@ -4417,17 +4427,17 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, /** * Property id to column instance mapping */ - private final Map columns = new HashMap(); + private final Map columns = new HashMap<>(); /** * Key generator for column server-to-client communication */ - private final KeyMapper columnKeys = new KeyMapper(); + private final KeyMapper columnKeys = new KeyMapper<>(); /** * The current sort order */ - private final List sortOrder = new ArrayList(); + private final List sortOrder = new ArrayList<>(); /** * Property listener for listening to changes in data source properties. @@ -4440,7 +4450,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, .getContainerPropertyIds()); // Find columns that need to be removed. - List removedColumns = new LinkedList(); + List removedColumns = new LinkedList<>(); for (Object propertyId : columns.keySet()) { if (!properties.contains(propertyId)) { removedColumns.add(getColumn(propertyId)); @@ -4456,7 +4466,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, datasourceExtension.columnsRemoved(removedColumns); // Add new columns - List addedColumns = new LinkedList(); + List addedColumns = new LinkedList<>(); for (Object propertyId : properties) { if (!columns.containsKey(propertyId)) { addedColumns.add(appendColumn(propertyId)); @@ -4474,7 +4484,8 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, .getSortableContainerPropertyIds(); for (Object propertyId : columns.keySet()) { Column column = columns.get(propertyId); - if (!sortables.contains(propertyId) && column.isSortable()) { + if (!sortables.contains(propertyId) && column + .isSortable()) { column.setSortable(false); } } @@ -4531,10 +4542,11 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, private DetailComponentManager detailComponentManager = null; - private Set extensionComponents = new HashSet(); + private Set extensionComponents = new HashSet<>(); private static final Method SELECTION_CHANGE_METHOD = ReflectTools - .findMethod(SelectionListener.class, "select", SelectionEvent.class); + .findMethod(SelectionListener.class, "select", + SelectionEvent.class); private static final Method SORT_ORDER_CHANGE_METHOD = ReflectTools .findMethod(SortListener.class, "sort", SortEvent.class); @@ -4613,7 +4625,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, boolean userOriginated) { assert columnIds.length == directions.length; - List order = new ArrayList( + List order = new ArrayList<>( columnIds.length); for (int i = 0; i < columnIds.length; i++) { Object propertyId = getPropertyIdByColumnId(columnIds[i]); @@ -4660,7 +4672,8 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, getState(false).columnOrder = newColumnOrder; // write changes to diffState so that possible reverting the // column order is sent to client - assert diffState.hasKey(diffStateKey) : "Field name has changed"; + assert diffState.hasKey( + diffStateKey) : "Field name has changed"; Type type = null; try { type = (getState(false).getClass().getDeclaredField( @@ -4699,7 +4712,8 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, JsonObject diffState = connectorTracker .getDiffState(Grid.this); - assert diffState.hasKey(diffStateKey) : "Field name has changed"; + assert diffState.hasKey( + diffStateKey) : "Field name has changed"; Type type = null; try { type = (getState(false).getClass().getDeclaredField( @@ -4722,7 +4736,8 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, @Override public void contextClick(int rowIndex, String rowKey, - String columnId, Section section, MouseEventDetails details) { + String columnId, Section section, + MouseEventDetails details) { Object itemId = null; if (rowKey != null) { itemId = getKeyMapper().get(rowKey); @@ -4806,7 +4821,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, errorMessage = event.getUserErrorMessage(); - errorColumnIds = new ArrayList(); + errorColumnIds = new ArrayList<>(); for (Column column : event.getErrorColumns()) { errorColumnIds.add(column.state.id); } @@ -5032,7 +5047,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, * @return unmodifiable copy of current columns in visual order */ public List getColumns() { - List columns = new ArrayList(); + List columns = new ArrayList<>(); for (String columnId : getState(false).columnOrder) { columns.add(getColumnByColumnId(columnId)); } @@ -5075,7 +5090,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, // Inform the data provider of this new column. Column column = getColumn(propertyId); - List addedColumns = new ArrayList(); + List addedColumns = new ArrayList<>(); addedColumns.add(column); datasourceExtension.columnsAdded(addedColumns); @@ -5141,8 +5156,8 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, * Removes all columns from this Grid. */ public void removeAllColumns() { - List removed = new ArrayList(columns.values()); - Set properties = new HashSet(columns.keySet()); + List removed = new ArrayList<>(columns.values()); + Set properties = new HashSet<>(columns.keySet()); for (Object propertyId : properties) { removeColumn(propertyId); } @@ -5237,7 +5252,8 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, footer.addColumn(datasourcePropertyId); String humanFriendlyPropertyId = SharedUtil - .propertyIdToHumanFriendly(String.valueOf(datasourcePropertyId)); + .propertyIdToHumanFriendly(String.valueOf( + datasourcePropertyId)); column.setHeaderCaption(humanFriendlyPropertyId); if (datasource instanceof Sortable @@ -5258,13 +5274,14 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, * @throws IllegalArgumentException * if there is no column for given property id in this grid */ - public void removeColumn(Object propertyId) throws IllegalArgumentException { + public void removeColumn(Object propertyId) + throws IllegalArgumentException { if (!columns.keySet().contains(propertyId)) { throw new IllegalArgumentException( "There is no column for given property id " + propertyId); } - List removed = new ArrayList(); + List removed = new ArrayList<>(); removed.add(getColumn(propertyId)); internalRemoveColumn(propertyId); datasourceExtension.columnsRemoved(removed); @@ -5292,12 +5309,12 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, * properties in the desired column order */ public void setColumns(Object... propertyIds) { - Set removePids = new HashSet(columns.keySet()); + Set removePids = new HashSet<>(columns.keySet()); removePids.removeAll(Arrays.asList(propertyIds)); for (Object removePid : removePids) { removeColumn(removePid); } - Set addPids = new HashSet(Arrays.asList(propertyIds)); + Set addPids = new HashSet<>(Arrays.asList(propertyIds)); addPids.removeAll(columns.keySet()); for (Object propertyId : addPids) { addColumn(propertyId); @@ -5314,7 +5331,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, * properties in the order columns should be */ public void setColumnOrder(Object... propertyIds) { - List columnOrder = new ArrayList(); + List columnOrder = new ArrayList<>(); for (Object propertyId : propertyIds) { if (columns.containsKey(propertyId)) { columnOrder.add(columnKeys.key(propertyId)); @@ -5602,7 +5619,8 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, public SelectionModel setSelectionMode(final SelectionMode selectionMode) throws IllegalArgumentException { if (selectionMode == null) { - throw new IllegalArgumentException("selection mode may not be null"); + throw new IllegalArgumentException( + "selection mode may not be null"); } final SelectionModel newSelectionModel = selectionMode.createModel(); setSelectionModel(newSelectionModel); @@ -6075,7 +6093,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, getState().sortColumns = new String[] {}; getState(false).sortDirs = new SortDirection[] {}; } - fireEvent(new SortEvent(this, new ArrayList(sortOrder), + fireEvent(new SortEvent(this, new ArrayList<>(sortOrder), userOriginated)); } else { throw new IllegalStateException( @@ -6414,7 +6432,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, public Iterator iterator() { // This is a hash set to avoid adding header/footer components inside // merged cells multiple times - LinkedHashSet componentList = new LinkedHashSet(); + LinkedHashSet componentList = new LinkedHashSet<>(); Header header = getHeader(); for (int i = 0; i < header.getRowCount(); ++i) { @@ -6476,9 +6494,11 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, * * @since 7.6 */ - public void setCellDescriptionGenerator(CellDescriptionGenerator generator) { + public void setCellDescriptionGenerator( + CellDescriptionGenerator generator) { cellDescriptionGenerator = generator; - getState().hasDescriptions = (generator != null || rowDescriptionGenerator != null); + getState().hasDescriptions = (generator != null + || rowDescriptionGenerator != null); datasourceExtension.refreshCache(); } @@ -6512,7 +6532,8 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, */ public void setRowDescriptionGenerator(RowDescriptionGenerator generator) { rowDescriptionGenerator = generator; - getState().hasDescriptions = (generator != null || cellDescriptionGenerator != null); + getState().hasDescriptions = (generator != null + || cellDescriptionGenerator != null); datasourceExtension.refreshCache(); } @@ -6738,14 +6759,14 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, } } - private Field getEditorField(Object propertyId) { + private LegacyField getEditorField(Object propertyId) { checkColumnExists(propertyId); if (!getColumn(propertyId).isEditable()) { return null; } - Field editor = editorFieldGroup.getField(propertyId); + LegacyField editor = editorFieldGroup.getField(propertyId); try { if (editor == null) { @@ -6809,7 +6830,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, editorActive = true; // Must ensure that all fields, recursively, are sent to the client // This is needed because the fields are hidden using isRendered - for (Field f : getEditorFields()) { + for (LegacyField f : getEditorFields()) { f.markAsDirtyRecursive(); } @@ -6819,10 +6840,10 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, } } - private void setEditorField(Object propertyId, Field field) { + private void setEditorField(Object propertyId, LegacyField field) { checkColumnExists(propertyId); - Field oldField = editorFieldGroup.getField(propertyId); + LegacyField oldField = editorFieldGroup.getField(propertyId); if (oldField != null) { editorFieldGroup.unbind(oldField); oldField.setParent(null); @@ -6884,7 +6905,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, */ cancelEditor(); } - for (Field editor : getEditorFields()) { + for (LegacyField editor : getEditorFields()) { editor.setParent(null); } @@ -6901,8 +6922,8 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, * * @return a collection of all the fields bound to the item editor */ - Collection> getEditorFields() { - Collection> fields = editorFieldGroup.getFields(); + Collection> getEditorFields() { + Collection> fields = editorFieldGroup.getFields(); assert allAttached(fields); return fields; } @@ -7273,7 +7294,8 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, if (selectionModel.getClass().equals(SingleSelectionModel.class)) { selectionMode = SelectionMode.SINGLE; - } else if (selectionModel.getClass().equals(MultiSelectionModel.class)) { + } else if (selectionModel.getClass().equals( + MultiSelectionModel.class)) { selectionMode = SelectionMode.MULTI; } else if (selectionModel.getClass().equals(NoSelectionModel.class)) { selectionMode = SelectionMode.NONE; diff --git a/server/src/main/java/com/vaadin/ui/ProgressBar.java b/server/src/main/java/com/vaadin/ui/ProgressBar.java index d38067d51e..3182563eda 100644 --- a/server/src/main/java/com/vaadin/ui/ProgressBar.java +++ b/server/src/main/java/com/vaadin/ui/ProgressBar.java @@ -19,6 +19,7 @@ package com.vaadin.ui; import org.jsoup.nodes.Element; import com.vaadin.data.Property; +import com.vaadin.legacy.ui.LegacyAbstractField; import com.vaadin.shared.ui.progressindicator.ProgressBarState; import com.vaadin.ui.declarative.DesignAttributeHandler; import com.vaadin.ui.declarative.DesignContext; @@ -34,7 +35,7 @@ import com.vaadin.ui.declarative.DesignContext; * @since 7.1 * @author Vaadin Ltd */ -public class ProgressBar extends AbstractField implements +public class ProgressBar extends LegacyAbstractField implements Property.Viewer, Property.ValueChangeListener { private static final float DEFAULT_VALUE = 0f; @@ -140,8 +141,8 @@ public class ProgressBar extends AbstractField implements } /* - * Overridden to keep the shared state in sync with the AbstractField - * internal value. Should be removed once AbstractField is refactored to use + * Overridden to keep the shared state in sync with the LegacyAbstractField + * internal value. Should be removed once LegacyAbstractField is refactored to use * shared state. * * See tickets #10921 and #11064. diff --git a/server/src/main/java/com/vaadin/ui/RichTextArea.java b/server/src/main/java/com/vaadin/ui/RichTextArea.java index 2f0ba215b9..57fcdc0a5e 100644 --- a/server/src/main/java/com/vaadin/ui/RichTextArea.java +++ b/server/src/main/java/com/vaadin/ui/RichTextArea.java @@ -21,6 +21,7 @@ import java.util.Map; import org.jsoup.nodes.Element; import com.vaadin.data.Property; +import com.vaadin.legacy.ui.LegacyAbstractField; import com.vaadin.server.PaintException; import com.vaadin.server.PaintTarget; import com.vaadin.shared.ui.textarea.RichTextAreaState; @@ -33,7 +34,7 @@ import com.vaadin.ui.declarative.DesignContext; * {@link RichTextArea} may produce unexpected results as formatting is counted * into length of field. */ -public class RichTextArea extends AbstractField implements +public class RichTextArea extends LegacyAbstractField implements LegacyComponent { /** diff --git a/server/src/main/java/com/vaadin/ui/Slider.java b/server/src/main/java/com/vaadin/ui/Slider.java index 1fd6d425fe..fbb9aa292a 100644 --- a/server/src/main/java/com/vaadin/ui/Slider.java +++ b/server/src/main/java/com/vaadin/ui/Slider.java @@ -21,6 +21,7 @@ import java.util.Collection; import org.jsoup.nodes.Attributes; import org.jsoup.nodes.Element; +import com.vaadin.legacy.ui.LegacyAbstractField; import com.vaadin.shared.ui.slider.SliderOrientation; import com.vaadin.shared.ui.slider.SliderServerRpc; import com.vaadin.shared.ui.slider.SliderState; @@ -32,7 +33,7 @@ import com.vaadin.ui.declarative.DesignContext; * * @author Vaadin Ltd. */ -public class Slider extends AbstractField { +public class Slider extends LegacyAbstractField { private SliderServerRpc rpc = new SliderServerRpc() { @@ -299,8 +300,8 @@ public class Slider extends AbstractField { } /* - * Overridden to keep the shared state in sync with the AbstractField - * internal value. Should be removed once AbstractField is refactored to use + * Overridden to keep the shared state in sync with the LegacyAbstractField + * internal value. Should be removed once LegacyAbstractField is refactored to use * shared state. * * See tickets #10921 and #11064. diff --git a/server/src/main/java/com/vaadin/ui/Table.java b/server/src/main/java/com/vaadin/ui/Table.java index f518f4f161..4e85b9e028 100644 --- a/server/src/main/java/com/vaadin/ui/Table.java +++ b/server/src/main/java/com/vaadin/ui/Table.java @@ -57,6 +57,7 @@ import com.vaadin.event.dd.DragSource; import com.vaadin.event.dd.DropHandler; import com.vaadin.event.dd.DropTarget; import com.vaadin.event.dd.acceptcriteria.ServerSideCriterion; +import com.vaadin.legacy.ui.LegacyField; import com.vaadin.server.KeyMapper; import com.vaadin.server.LegacyCommunicationManager; import com.vaadin.server.LegacyPaint; @@ -581,7 +582,7 @@ public class Table extends AbstractSelect implements Action.Container, private RowGenerator rowGenerator = null; - private final Map, Property> associatedProperties = new HashMap, Property>(); + private final Map, Property> associatedProperties = new HashMap, Property>(); private boolean painted = false; @@ -2551,8 +2552,8 @@ public class Table extends AbstractSelect implements Action.Container, * Also remove property data sources to unregister listeners keeping the * fields in memory. */ - if (component instanceof Field) { - Field field = (Field) component; + if (component instanceof LegacyField) { + LegacyField field = (LegacyField) component; Property associatedProperty = associatedProperties .remove(component); if (associatedProperty != null @@ -4103,7 +4104,7 @@ public class Table extends AbstractSelect implements Action.Container, protected Object getPropertyValue(Object rowId, Object colId, Property property) { if (isEditable() && fieldFactory != null) { - final Field f = fieldFactory.createField( + final LegacyField f = fieldFactory.createField( getContainerDataSource(), rowId, colId, this); if (f != null) { // Remember that we have made this association so we can remove @@ -4119,7 +4120,7 @@ public class Table extends AbstractSelect implements Action.Container, /** * Binds an item property to a field generated by TableFieldFactory. The - * default behavior is to bind property straight to Field. If + * default behavior is to bind property straight to LegacyField. If * Property.Viewer type property (e.g. PropertyFormatter) is already set for * field, the property is bound to that Property.Viewer. * @@ -4130,7 +4131,7 @@ public class Table extends AbstractSelect implements Action.Container, * @since 6.7.3 */ protected void bindPropertyToField(Object rowId, Object colId, - Property property, Field field) { + Property property, LegacyField field) { // check if field has a property that is Viewer set. In that case we // expect developer has e.g. PropertyFormatter that he wishes to use and // assign the property to the Viewer instead. @@ -4780,7 +4781,7 @@ public class Table extends AbstractSelect implements Action.Container, * * The FieldFactory is only used if the Table is editable. * - * @return TableFieldFactory used to create the Field instances. + * @return TableFieldFactory used to create the LegacyField instances. * @see #isEditable */ public TableFieldFactory getTableFieldFactory() { @@ -4790,7 +4791,7 @@ public class Table extends AbstractSelect implements Action.Container, /** * Is table editable. * - * If table is editable a editor of type Field is created for each table + * If table is editable a editor of type LegacyField is created for each table * cell. The assigned FieldFactory is used to create the instances. * * To provide custom editors for table cells create a class implementing the @@ -4798,7 +4799,7 @@ public class Table extends AbstractSelect implements Action.Container, * property to true. * * @return true if table is editable, false otherwise. - * @see Field + * @see LegacyField * @see FieldFactory * */ @@ -4809,7 +4810,7 @@ public class Table extends AbstractSelect implements Action.Container, /** * Sets the editable property. * - * If table is editable a editor of type Field is created for each table + * If table is editable a editor of type LegacyField is created for each table * cell. The assigned FieldFactory is used to create the instances. * * To provide custom editors for table cells create a class implementing the @@ -4818,7 +4819,7 @@ public class Table extends AbstractSelect implements Action.Container, * * @param editable * true if table should be editable by user. - * @see Field + * @see LegacyField * @see FieldFactory * */ diff --git a/server/src/main/java/com/vaadin/ui/TableFieldFactory.java b/server/src/main/java/com/vaadin/ui/TableFieldFactory.java index 3c946dcec2..e77dc0ec35 100644 --- a/server/src/main/java/com/vaadin/ui/TableFieldFactory.java +++ b/server/src/main/java/com/vaadin/ui/TableFieldFactory.java @@ -18,12 +18,13 @@ package com.vaadin.ui; import java.io.Serializable; import com.vaadin.data.Container; +import com.vaadin.legacy.ui.LegacyField; /** - * Factory interface for creating new Field-instances based on Container + * Factory interface for creating new LegacyField-instances based on Container * (datasource), item id, property id and uiContext (the component responsible * for displaying fields). Currently this interface is used by {@link Table}, - * but might later be used by some other components for {@link Field} + * but might later be used by some other components for {@link LegacyField} * generation. * *

@@ -49,7 +50,7 @@ public interface TableFieldFactory extends Serializable { * @return A field suitable for editing the specified data or null if the * property should not be editable. */ - Field createField(Container container, Object itemId, Object propertyId, + LegacyField createField(Container container, Object itemId, Object propertyId, Component uiContext); } diff --git a/server/src/main/java/com/vaadin/ui/TextField.java b/server/src/main/java/com/vaadin/ui/TextField.java index 8772f95f3d..31a15f85c9 100644 --- a/server/src/main/java/com/vaadin/ui/TextField.java +++ b/server/src/main/java/com/vaadin/ui/TextField.java @@ -31,10 +31,10 @@ import com.vaadin.ui.declarative.DesignContext; *

* *

- * Since TextField extends AbstractField it implements + * Since TextField extends LegacyAbstractField it implements * the {@link com.vaadin.data.Buffered} interface. A TextField is * in write-through mode by default, so - * {@link com.vaadin.ui.AbstractField#setWriteThrough(boolean)} must be called + * {@link com.vaadin.legacy.ui.LegacyAbstractField#setWriteThrough(boolean)} must be called * to enable buffering. *

* -- cgit v1.2.3