diff options
author | Artur Signell <artur@vaadin.com> | 2016-08-25 14:46:30 +0300 |
---|---|---|
committer | Artur Signell <artur@vaadin.com> | 2016-08-26 11:40:13 +0300 |
commit | c11121e2b7e685d42eb129c8a97e5ed4690af2f2 (patch) | |
tree | e1ed542be05eda64d12d18f8310db9900f835cb5 /server/src | |
parent | 58853fe47bb01a0c0c2b5c380056d22ccccd6f08 (diff) | |
download | vaadin-framework-c11121e2b7e685d42eb129c8a97e5ed4690af2f2.tar.gz vaadin-framework-c11121e2b7e685d42eb129c8a97e5ed4690af2f2.zip |
Move old Field and AbstractField to compatibility package
Change-Id: Ia9b6f77763abac87ec61d1ee198cb8d41419a934
Diffstat (limited to 'server/src')
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"); - } - -} |