aboutsummaryrefslogtreecommitdiffstats
path: root/server/src
diff options
context:
space:
mode:
authorArtur Signell <artur@vaadin.com>2016-08-25 14:46:30 +0300
committerArtur Signell <artur@vaadin.com>2016-08-26 11:40:13 +0300
commitc11121e2b7e685d42eb129c8a97e5ed4690af2f2 (patch)
treee1ed542be05eda64d12d18f8310db9900f835cb5 /server/src
parent58853fe47bb01a0c0c2b5c380056d22ccccd6f08 (diff)
downloadvaadin-framework-c11121e2b7e685d42eb129c8a97e5ed4690af2f2.tar.gz
vaadin-framework-c11121e2b7e685d42eb129c8a97e5ed4690af2f2.zip
Move old Field and AbstractField to compatibility package
Change-Id: Ia9b6f77763abac87ec61d1ee198cb8d41419a934
Diffstat (limited to 'server/src')
-rw-r--r--server/src/main/java/com/vaadin/event/FieldEvents.java13
-rw-r--r--server/src/main/java/com/vaadin/v7/ui/AbstractField.java1810
-rw-r--r--server/src/main/java/com/vaadin/v7/ui/Field.java150
-rw-r--r--server/src/test/java/com/vaadin/tests/VaadinClasses.java12
-rw-r--r--server/src/test/java/com/vaadin/tests/server/component/FieldDefaultValuesTest.java77
-rw-r--r--server/src/test/java/com/vaadin/tests/server/components/AbstractFieldValueChangeTestBase.java130
6 files changed, 7 insertions, 2185 deletions
diff --git a/server/src/main/java/com/vaadin/event/FieldEvents.java b/server/src/main/java/com/vaadin/event/FieldEvents.java
index a8e5ca8191..ba84e96b3f 100644
--- a/server/src/main/java/com/vaadin/event/FieldEvents.java
+++ b/server/src/main/java/com/vaadin/event/FieldEvents.java
@@ -24,7 +24,6 @@ import com.vaadin.shared.communication.FieldRpc.FocusAndBlurServerRpc;
import com.vaadin.ui.Component;
import com.vaadin.ui.Component.Event;
import com.vaadin.util.ReflectTools;
-import com.vaadin.v7.ui.Field;
/**
* Interface that serves as a wrapper for {@link Field} related events.
@@ -43,7 +42,7 @@ public interface FieldEvents {
public interface FocusNotifier extends Serializable {
/**
* Adds a <code>FocusListener</code> to the Component which gets fired
- * when a <code>LegacyField</code> receives keyboard focus.
+ * when a <code>Field</code> receives keyboard focus.
*
* @param listener
* @see FocusListener
@@ -74,7 +73,7 @@ public interface FieldEvents {
public interface BlurNotifier extends Serializable {
/**
* Adds a <code>BlurListener</code> to the Component which gets fired
- * when a <code>LegacyField</code> loses keyboard focus.
+ * when a <code>Field</code> loses keyboard focus.
*
* @param listener
* @see BlurListener
@@ -95,7 +94,7 @@ public interface FieldEvents {
/**
* <code>FocusEvent</code> class for holding additional event information.
- * Fired when a <code>LegacyField</code> receives keyboard focus.
+ * Fired when a <code>Field</code> receives keyboard focus.
*
* @since 6.2
*/
@@ -114,7 +113,7 @@ public interface FieldEvents {
/**
* <code>FocusListener</code> interface for listening for
- * <code>FocusEvent</code> fired by a <code>LegacyField</code>.
+ * <code>FocusEvent</code> fired by a <code>Field</code>.
*
* @see FocusEvent
* @since 6.2
@@ -135,7 +134,7 @@ public interface FieldEvents {
/**
* <code>BlurEvent</code> class for holding additional event information.
- * Fired when a <code>LegacyField</code> loses keyboard focus.
+ * Fired when a <code>Field</code> loses keyboard focus.
*
* @since 6.2
*/
@@ -154,7 +153,7 @@ public interface FieldEvents {
/**
* <code>BlurListener</code> interface for listening for
- * <code>BlurEvent</code> fired by a <code>LegacyField</code>.
+ * <code>BlurEvent</code> fired by a <code>Field</code>.
*
* @see BlurEvent
* @since 6.2
diff --git a/server/src/main/java/com/vaadin/v7/ui/AbstractField.java b/server/src/main/java/com/vaadin/v7/ui/AbstractField.java
deleted file mode 100644
index 33f262d581..0000000000
--- a/server/src/main/java/com/vaadin/v7/ui/AbstractField.java
+++ /dev/null
@@ -1,1810 +0,0 @@
-/*
- * Copyright 2000-2016 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.v7.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.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;
-import com.vaadin.v7.data.Buffered;
-import com.vaadin.v7.data.Property;
-import com.vaadin.v7.data.Validatable;
-import com.vaadin.v7.data.Validator;
-import com.vaadin.v7.data.Validator.InvalidValueException;
-import com.vaadin.v7.data.util.converter.Converter;
-import com.vaadin.v7.data.util.converter.Converter.ConversionException;
-import com.vaadin.v7.data.util.converter.ConverterUtil;
-
-/**
- * <p>
- * 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.v7.data.Property}interface.
- * <code>LegacyAbstractField</code> implements that interface itself, too, so
- * accessing the Property value represented by it is straightforward.
- * </p>
- *
- * <p>
- * LegacyAbstractField also provides the {@link com.vaadin.v7.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.
- * </p>
- *
- * <p>
- * The class also supports {@link com.vaadin.v7.data.Validator validators}
- * to make sure the value contained in the field is valid.
- * </p>
- *
- * @author Vaadin Ltd.
- * @since 3.0
- *
- * @deprecated This class is, apart from the rename, identical to the Vaadin 7
- * {@code com.vaadin.ui.AbstractField}. It is provided for
- * compatibility and migration purposes. As of 8.0, new field
- * implementations should extend the new
- * {@link com.vaadin.ui.AbstractField} instead.
- */
-@SuppressWarnings("serial")
-@Deprecated
-public abstract class AbstractField<T> extends AbstractComponent
- implements Field<T>, 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<T, Object> converter = null;
- /**
- * Connected data-source.
- */
- private Property<?> dataSource = null;
-
- /**
- * The list of validators.
- */
- private LinkedList<Validator> 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 <code>getValue</code>
- * and <code>setValue</code> must be compatible with this type: one must be
- * able to safely cast the value returned from <code>getValue</code> to the
- * given type and pass any variable assignable to this type as an argument
- * to <code>setValue</code>.
- *
- * @return the type of the LegacyField
- */
- @Override
- public abstract Class<? extends T> 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.v7.data.BufferedValidatable#isInvalidCommitted()
- */
- @Override
- public boolean isInvalidCommitted() {
- return invalidCommitted;
- }
-
- /**
- * Sets if the invalid data should be committed to datasource.
- *
- * @see com.vaadin.v7.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.
- * <p>
- * When the field is in buffered mode, changes will not be committed to the
- * property data source until {@link #commit()} is called.
- * </p>
- * <p>
- * Setting buffered mode from true to false will commit any pending changes.
- * </p>
- * <p>
- *
- * </p>
- *
- * @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;
- }
-
- /* Property interface implementation */
-
- /**
- * Gets the current value of the field.
- *
- * <p>
- * This is the visible, modified and possible invalid value the user have
- * entered to the field.
- * </p>
- *
- * <p>
- * 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.
- * </p>
- *
- * <p>
- * Since Vaadin 7.0, no implicit conversions between other data types and
- * String are performed, but a converter is used if set.
- * </p>
- *
- * @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 <code>null</code> if
- * none defined.
- */
- @Override
- public Property getPropertyDataSource() {
- return dataSource;
- }
-
- /**
- * <p>
- * Sets the specified Property as the data source for the field. All
- * uncommitted changes are replaced with a value from the new data source.
- * </p>
- *
- * <p>
- * 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.
- * </p>
- *
- * <p>
- * If the data source implements
- * {@link com.vaadin.v7.data.Property.ValueChangeNotifier} and/or
- * {@link com.vaadin.v7.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}.
- * </p>
- *
- * <p>
- * 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().
- * </p>
- *
- * @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<Validator> validators = ((Validatable) dataSource)
- .getValidators();
- if (validators != null) {
- for (final Iterator<Validator> 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<T, ?> c = (Converter<T, ?>) 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<Object>) 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.
- * <p>
- * 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.
- * </p>
- *
- * @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<Validator> 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 <code>true</code> if all registered validators claim that the
- * current value is valid or if the field is empty and not required,
- * <code>false</code> 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.v7.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.
- * <p>
- * 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<InvalidValueException> 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.v7.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.
- * <p>
- * 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.
- * </p>
- *
- * @see com.vaadin.v7.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(AbstractField.ValueChangeEvent.class, listener,
- VALUE_CHANGE_METHOD);
- // ensure "automatic immediate handling" works
- markAsDirty();
- }
-
- /**
- * @deprecated As of 7.0, replaced by
- * {@link #addValueChangeListener(com.vaadin.v7.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.v7.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 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 <code>Event</code> 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.v7.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.v7.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 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 <code>true</code> if the field is required, otherwise
- * <code>false</code>.
- */
- @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<T, Object> 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<T, ?> converter) {
- this.converter = (Converter<T, Object>) 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
- * <code>isListeningToPropertyEvents == true</code>.
- */
- 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 <code>isListeningToPropertyEvents == false</code>.
- */
- 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;
- }
- }
-
- /*
- * (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<String> getCustomAttributes() {
- Collection<String> 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/v7/ui/Field.java b/server/src/main/java/com/vaadin/v7/ui/Field.java
deleted file mode 100644
index 0756dfaf90..0000000000
--- a/server/src/main/java/com/vaadin/v7/ui/Field.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright 2000-2016 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.v7.ui;
-
-import com.vaadin.data.HasRequired;
-import com.vaadin.data.HasValue.ValueChange;
-import com.vaadin.ui.Component;
-import com.vaadin.ui.Component.Focusable;
-import com.vaadin.v7.data.BufferedValidatable;
-import com.vaadin.v7.data.Property;
-
-/**
- * LegacyField interface is implemented by all legacy 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.AbstractField} 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
- *
- * @deprecated This interface is, apart from the rename, identical to the Vaadin
- * 7 {@code com.vaadin.ui.Field}. It is provided for compatibility
- * and migration purposes. As of 8.0, new field components should
- * extend {@link com.vaadin.ui.AbstractField} instead.
- */
-@Deprecated
-public interface Field<T> extends Component, BufferedValidatable,
- Property<T>, Property.ValueChangeNotifier, Property.ValueChangeListener,
- Property.Editor, Focusable, HasRequired {
- /**
- * Is this field required.
- *
- * Required fields must filled by the user.
- *
- * @return <code>true</code> if the field is required,otherwise
- * <code>false</code>.
- * @since 3.1
- */
- @Override
- public boolean isRequired();
-
- /**
- * Sets the field required. Required fields must filled by the user.
- *
- * @param required
- * Is the field required.
- * @since 3.1
- */
- @Override
- 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 <code>Event</code> object specifying the LegacyField whose value has
- * been changed.
- *
- * @author Vaadin Ltd.
- * @since 3.0
- *
- * @deprecated As of 8.0, replaced by {@link ValueChange}.
- */
- @Deprecated
- @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.
- * <p>
- * 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/test/java/com/vaadin/tests/VaadinClasses.java b/server/src/test/java/com/vaadin/tests/VaadinClasses.java
index ad1119a8ad..ba56fcee35 100644
--- a/server/src/test/java/com/vaadin/tests/VaadinClasses.java
+++ b/server/src/test/java/com/vaadin/tests/VaadinClasses.java
@@ -29,7 +29,6 @@ import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalSplitPanel;
import com.vaadin.ui.Window;
import com.vaadin.ui.themes.BaseTheme;
-import com.vaadin.v7.ui.Field;
@SuppressWarnings("deprecation")
public class VaadinClasses {
@@ -63,15 +62,6 @@ public class VaadinClasses {
}
}
- public static List<Class<? extends Field>> getFields() {
- try {
- return findClasses(Field.class, "com.vaadin.ui");
- } catch (IOException e) {
- e.printStackTrace();
- return null;
- }
- }
-
public static List<Class<? extends BaseTheme>> getThemeClasses() {
try {
return findClasses(BaseTheme.class, "com.vaadin.ui.themes");
@@ -136,7 +126,7 @@ public class VaadinClasses {
}
- private static <T> List<Class<? extends T>> findClasses(Class<T> baseClass,
+ public static <T> List<Class<? extends T>> findClasses(Class<T> baseClass,
String basePackage) throws IOException {
return findClasses(baseClass, basePackage, new String[] {});
}
diff --git a/server/src/test/java/com/vaadin/tests/server/component/FieldDefaultValuesTest.java b/server/src/test/java/com/vaadin/tests/server/component/FieldDefaultValuesTest.java
deleted file mode 100644
index ba2bccfb78..0000000000
--- a/server/src/test/java/com/vaadin/tests/server/component/FieldDefaultValuesTest.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright 2000-2016 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.tests.server.component;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-import com.vaadin.tests.VaadinClasses;
-import com.vaadin.ui.Slider;
-import com.vaadin.v7.ui.Field;
-
-public class FieldDefaultValuesTest {
-
- @Test
- public void testFieldsHaveDefaultValueAfterClear() throws Exception {
- for (Field<?> field : createFields()) {
- Object originalValue = field.getValue();
-
- field.clear();
-
- Object clearedValue = field.getValue();
-
- Assert.assertEquals(
- "Expected to get default value after clearing "
- + field.getClass().getName(),
- originalValue, clearedValue);
- }
- }
-
- @Test
- public void testFieldsAreEmptyAfterClear() throws Exception {
- for (Field<?> field : createFields()) {
- field.clear();
-
- if (field instanceof Slider) {
- Assert.assertFalse(
- "Slider should not be empty even after being cleared",
- field.isEmpty());
-
- } else {
- Assert.assertTrue(
- field.getClass().getName()
- + " should be empty after being cleared",
- field.isEmpty());
- }
- }
- }
-
- @SuppressWarnings("rawtypes")
- private static List<Field<?>> createFields()
- throws InstantiationException, IllegalAccessException {
- List<Field<?>> fieldInstances = new ArrayList<Field<?>>();
-
- for (Class<? extends Field> fieldType : VaadinClasses
- .getFields()) {
- fieldInstances.add(fieldType.newInstance());
- }
- return fieldInstances;
- }
-
-}
diff --git a/server/src/test/java/com/vaadin/tests/server/components/AbstractFieldValueChangeTestBase.java b/server/src/test/java/com/vaadin/tests/server/components/AbstractFieldValueChangeTestBase.java
deleted file mode 100644
index 36057e935f..0000000000
--- a/server/src/test/java/com/vaadin/tests/server/components/AbstractFieldValueChangeTestBase.java
+++ /dev/null
@@ -1,130 +0,0 @@
-package com.vaadin.tests.server.components;
-
-import org.easymock.EasyMock;
-import org.junit.Test;
-
-import com.vaadin.v7.data.Property.ValueChangeEvent;
-import com.vaadin.v7.data.Property.ValueChangeListener;
-import com.vaadin.v7.data.Property.ValueChangeNotifier;
-import com.vaadin.v7.data.util.ObjectProperty;
-import com.vaadin.v7.ui.AbstractField;
-
-/**
- * Base class for tests for checking that value change listeners for fields are
- * not called exactly once when they should be, and not at other times.
- *
- * Does not check all cases (e.g. properties that do not implement
- * {@link ValueChangeNotifier}).
- *
- * Subclasses should implement {@link #setValue()} and call
- * <code>super.setValue(LegacyAbstractField)</code>. Also, subclasses should
- * typically override {@link #setValue(AbstractField)} to set the field
- * value via <code>changeVariables()</code>.
- */
-public abstract class AbstractFieldValueChangeTestBase<T> {
-
- private AbstractField<T> field;
- private ValueChangeListener listener;
-
- protected void setUp(AbstractField<T> field) {
- this.field = field;
- listener = EasyMock.createStrictMock(ValueChangeListener.class);
-
- }
-
- protected ValueChangeListener getListener() {
- return listener;
- }
-
- /**
- * Test that listeners are not called when they have been unregistered.
- */
- @Test
- public void testRemoveListener() {
- getField().setPropertyDataSource(new ObjectProperty<String>(""));
- getField().setBuffered(false);
-
- // Expectations and start test
- listener.valueChange(EasyMock.isA(ValueChangeEvent.class));
- EasyMock.replay(listener);
-
- // Add listener and set the value -> should end up in listener once
- getField().addListener(listener);
- setValue(getField());
-
- // Ensure listener was called once
- EasyMock.verify(listener);
-
- // Remove the listener and set the value -> should not end up in
- // listener
- getField().removeListener(listener);
- setValue(getField());
-
- // Ensure listener still has been called only once
- EasyMock.verify(listener);
- }
-
- /**
- * Common unbuffered case: both writeThrough (auto-commit) and readThrough
- * are on. Calling commit() should not cause notifications.
- *
- * Using the readThrough mode allows changes made to the property value to
- * be seen in some cases also when there is no notification of value change
- * from the property.
- *
- * LegacyField value change notifications closely mirror value changes of
- * the data source behind the field.
- */
- @Test
- public void testNonBuffered() {
- getField().setPropertyDataSource(new ObjectProperty<String>(""));
- getField().setBuffered(false);
-
- expectValueChangeFromSetValueNotCommit();
- }
-
- /**
- * Fully buffered use where the data source is neither read nor modified
- * during editing, and is updated at commit().
- *
- * LegacyField value change notifications reflect the buffered value in the
- * field, not the original data source value changes.
- */
- public void testBuffered() {
- getField().setPropertyDataSource(new ObjectProperty<String>(""));
- getField().setBuffered(true);
-
- expectValueChangeFromSetValueNotCommit();
- }
-
- protected void expectValueChangeFromSetValueNotCommit() {
- // Expectations and start test
- listener.valueChange(EasyMock.isA(ValueChangeEvent.class));
- EasyMock.replay(listener);
-
- // Add listener and set the value -> should end up in listener once
- getField().addListener(listener);
- setValue(getField());
-
- // Ensure listener was called once
- EasyMock.verify(listener);
-
- // commit
- getField().commit();
-
- // Ensure listener was not called again
- EasyMock.verify(listener);
- }
-
- protected AbstractField<T> getField() {
- return field;
- }
-
- /**
- * Override in subclasses to set value with changeVariables().
- */
- protected void setValue(AbstractField<T> field) {
- field.setValue((T) "newValue");
- }
-
-}