aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorArtur Signell <artur@vaadin.com>2011-12-14 22:09:43 +0200
committerArtur Signell <artur@vaadin.com>2011-12-14 22:40:57 +0200
commite137e9fdd2c5182777a0419b8cf8e146fc33fd18 (patch)
tree0e7b248aa2e5f7fb612d851375a8ecaa5dfc0ece /src
parent0bcd80a5ec66ca4e17fd689a5beab8de5c76559a (diff)
downloadvaadin-framework-e137e9fdd2c5182777a0419b8cf8e146fc33fd18.tar.gz
vaadin-framework-e137e9fdd2c5182777a0419b8cf8e146fc33fd18.zip
#8110 Validation is now done on the converted value
Added type to AbstractValidator and automatic type checking so sub classes get the correct type automatically Added a RangeValidator that work with any type that is Comparable CompositeValidator no longer extends AbstractValidator as it does not validate in the same way as AbstractValidator does
Diffstat (limited to 'src')
-rw-r--r--src/com/vaadin/data/validator/AbstractStringValidator.java41
-rw-r--r--src/com/vaadin/data/validator/AbstractValidator.java33
-rw-r--r--src/com/vaadin/data/validator/CompositeValidator.java36
-rw-r--r--src/com/vaadin/data/validator/DateRangeValidator.java37
-rw-r--r--src/com/vaadin/data/validator/DoubleRangeValidator.java36
-rw-r--r--src/com/vaadin/data/validator/DoubleValidator.java8
-rw-r--r--src/com/vaadin/data/validator/IntegerRangeValidator.java37
-rw-r--r--src/com/vaadin/data/validator/IntegerValidator.java8
-rw-r--r--src/com/vaadin/data/validator/RangeValidator.java172
-rw-r--r--src/com/vaadin/data/validator/RegexpValidator.java5
-rw-r--r--src/com/vaadin/data/validator/StringLengthValidator.java10
-rw-r--r--src/com/vaadin/ui/AbstractField.java97
12 files changed, 418 insertions, 102 deletions
diff --git a/src/com/vaadin/data/validator/AbstractStringValidator.java b/src/com/vaadin/data/validator/AbstractStringValidator.java
index c47ca15d77..5267cc7b7b 100644
--- a/src/com/vaadin/data/validator/AbstractStringValidator.java
+++ b/src/com/vaadin/data/validator/AbstractStringValidator.java
@@ -4,9 +4,7 @@
package com.vaadin.data.validator;
/**
- * Validator base class for validating strings. See
- * {@link com.vaadin.data.validator.AbstractValidator} for more information.
- *
+ * Validator base class for validating strings.
* <p>
* To include the value that failed validation in the exception message you can
* use "{0}" in the error message. This will be replaced with the failed value
@@ -15,12 +13,11 @@ package com.vaadin.data.validator;
* </p>
*
* @author Vaadin Ltd.
- * @version
- * @VERSION@
+ * @version @VERSION@
* @since 5.4
*/
@SuppressWarnings("serial")
-public abstract class AbstractStringValidator extends AbstractValidator {
+public abstract class AbstractStringValidator extends AbstractValidator<String> {
/**
* Constructs a validator for strings.
@@ -38,36 +35,8 @@ public abstract class AbstractStringValidator extends AbstractValidator {
super(errorMessage);
}
- /**
- * Tests if the given value is a valid string.
- * <p>
- * Null values are always accepted. Values that are not {@link String}s are
- * converted using {@link #toString()}. Then {@link #isValidString(String)}
- * is used to validate the value.
- * </p>
- *
- * @param value
- * the value to check
- * @return true if the value (or its toString()) is a valid string, false
- * otherwise
- */
@Override
- protected boolean isValidValue(Object value) {
- if (value == null) {
- return true;
- }
- if (!(value instanceof String)) {
- value = String.valueOf(value);
- }
- return isValidString((String) value);
+ public Class<String> getType() {
+ return String.class;
}
-
- /**
- * Checks if the given string is valid.
- *
- * @param value
- * String to check. Can never be null.
- * @return true if the string is valid, false otherwise
- */
- protected abstract boolean isValidString(String value);
}
diff --git a/src/com/vaadin/data/validator/AbstractValidator.java b/src/com/vaadin/data/validator/AbstractValidator.java
index 2bf2edbecc..27eaaca485 100644
--- a/src/com/vaadin/data/validator/AbstractValidator.java
+++ b/src/com/vaadin/data/validator/AbstractValidator.java
@@ -27,13 +27,14 @@ import com.vaadin.data.Validator;
* applications. To check validity, {@link #validate(Object)} should be used.
* </p>
*
+ * @param <T>
+ * The type
* @author Vaadin Ltd.
* @version
* @VERSION@
* @since 5.4
*/
-@SuppressWarnings("serial")
-public abstract class AbstractValidator implements Validator {
+public abstract class AbstractValidator<T> implements Validator {
/**
* Error message that is included in an {@link InvalidValueException} if
@@ -81,16 +82,36 @@ public abstract class AbstractValidator implements Validator {
* @param value
* @return
*/
- protected abstract boolean isValidValue(Object value);
+ protected abstract boolean isValidValue(T value);
public void validate(Object value) throws InvalidValueException {
- if (!isValidValue(value)) {
- String message = errorMessage.replace("{0}", String.valueOf(value));
+ // isValidType ensures that value can safely be cast to TYPE
+ if (!isValidType(value) || !isValidValue((T) value)) {
+ String message = getErrorMessage().replace("{0}",
+ String.valueOf(value));
throw new InvalidValueException(message);
}
}
/**
+ * Checks the type of the value to validate to ensure it conforms with
+ * getType. Enables sub classes to handle the specific type instead of
+ * Object.
+ *
+ * @param value
+ * The value to check
+ * @return true if the value can safely be cast to the type specified by
+ * {@link #getType()}
+ */
+ protected boolean isValidType(Object value) {
+ if (value == null) {
+ return true;
+ }
+
+ return getType().isAssignableFrom(value.getClass());
+ }
+
+ /**
* Returns the message to be included in the exception in case the value
* does not validate.
*
@@ -112,4 +133,6 @@ public abstract class AbstractValidator implements Validator {
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
+
+ public abstract Class<T> getType();
}
diff --git a/src/com/vaadin/data/validator/CompositeValidator.java b/src/com/vaadin/data/validator/CompositeValidator.java
index 2dd5950cec..083af70f30 100644
--- a/src/com/vaadin/data/validator/CompositeValidator.java
+++ b/src/com/vaadin/data/validator/CompositeValidator.java
@@ -19,12 +19,11 @@ import com.vaadin.data.Validator;
* <code>AND</code> and <code>OR</code>.
*
* @author Vaadin Ltd.
- * @version
- * @VERSION@
+ * @version @VERSION@
* @since 3.0
*/
@SuppressWarnings("serial")
-public class CompositeValidator extends AbstractValidator {
+public class CompositeValidator implements Validator {
public enum CombinationMode {
/**
@@ -52,6 +51,8 @@ public class CompositeValidator extends AbstractValidator {
@Deprecated
public static final CombinationMode MODE_OR = CombinationMode.OR;
+ private String errorMessage;
+
/**
* Operation mode.
*/
@@ -67,7 +68,7 @@ public class CompositeValidator extends AbstractValidator {
* message.
*/
public CompositeValidator() {
- super("");
+ this(CombinationMode.AND, "");
}
/**
@@ -77,7 +78,7 @@ public class CompositeValidator extends AbstractValidator {
* @param errorMessage
*/
public CompositeValidator(CombinationMode mode, String errorMessage) {
- super(errorMessage);
+ setErrorMessage(errorMessage);
setMode(mode);
}
@@ -100,7 +101,6 @@ public class CompositeValidator extends AbstractValidator {
* @throws Validator.InvalidValueException
* if the value is not valid.
*/
- @Override
public void validate(Object value) throws Validator.InvalidValueException {
switch (mode) {
case AND:
@@ -133,12 +133,6 @@ public class CompositeValidator extends AbstractValidator {
}
}
- @Override
- protected boolean isValidValue(Object value) {
- // not used as validate() overridden
- return false;
- }
-
/**
* Gets the mode of the validator.
*
@@ -171,10 +165,9 @@ public class CompositeValidator extends AbstractValidator {
* Gets the error message for the composite validator. If the error message
* is null, original error messages of the sub-validators are used instead.
*/
- @Override
public String getErrorMessage() {
- if (super.getErrorMessage() != null) {
- return super.getErrorMessage();
+ if (errorMessage != null) {
+ return errorMessage;
}
// TODO Return composite error message
@@ -229,7 +222,7 @@ public class CompositeValidator extends AbstractValidator {
* that must apply or null if none found.
*/
public Collection<Validator> getSubValidators(Class validatorType) {
- if (mode != MODE_AND) {
+ if (mode != CombinationMode.AND) {
return null;
}
@@ -251,4 +244,15 @@ public class CompositeValidator extends AbstractValidator {
return found.isEmpty() ? null : found;
}
+ /**
+ * Sets the message to be included in the exception in case the value does
+ * not validate. The exception message is typically shown to the end user.
+ *
+ * @param errorMessage
+ * the error message.
+ */
+ public void setErrorMessage(String errorMessage) {
+ this.errorMessage = errorMessage;
+ }
+
}
diff --git a/src/com/vaadin/data/validator/DateRangeValidator.java b/src/com/vaadin/data/validator/DateRangeValidator.java
new file mode 100644
index 0000000000..36a607691e
--- /dev/null
+++ b/src/com/vaadin/data/validator/DateRangeValidator.java
@@ -0,0 +1,37 @@
+package com.vaadin.data.validator;
+
+import java.util.Date;
+
+import com.vaadin.ui.DateField.Resolution;
+
+/**
+ * Validator for validating that a Date is inside a given range.
+ *
+ * @author Vaadin Ltd.
+ * @version
+ * @VERSION@
+ * @since 7.0
+ */
+public class DateRangeValidator extends RangeValidator<Date> {
+
+ /**
+ * Creates a validator for checking that an Date is within a given range.
+ *
+ * By default the range is inclusive i.e. both minValue and maxValue are
+ * valid values. Use {@link #setMinValueIncluded(boolean)} or
+ * {@link #setMaxValueIncluded(boolean)} to change it.
+ *
+ *
+ * @param errorMessage
+ * the message to display in case the value does not validate.
+ * @param minValue
+ * The minimum value to accept or null for no limit
+ * @param maxValue
+ * The maximum value to accept or null for no limit
+ */
+ public DateRangeValidator(String errorMessage, Date minValue,
+ Date maxValue, Resolution resolution) {
+ super(errorMessage, Date.class, minValue, maxValue);
+ }
+
+}
diff --git a/src/com/vaadin/data/validator/DoubleRangeValidator.java b/src/com/vaadin/data/validator/DoubleRangeValidator.java
new file mode 100644
index 0000000000..91fcf004af
--- /dev/null
+++ b/src/com/vaadin/data/validator/DoubleRangeValidator.java
@@ -0,0 +1,36 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.data.validator;
+
+/**
+ * Validator for validating that a {@link Double} is inside a given range.
+ *
+ * @author Vaadin Ltd.
+ * @version
+ * @VERSION@
+ * @since 7.0
+ */
+@SuppressWarnings("serial")
+public class DoubleRangeValidator extends RangeValidator<Double> {
+
+ /**
+ * Creates a validator for checking that an Double is within a given range.
+ *
+ * By default the range is inclusive i.e. both minValue and maxValue are
+ * valid values. Use {@link #setMinValueIncluded(boolean)} or
+ * {@link #setMaxValueIncluded(boolean)} to change it.
+ *
+ *
+ * @param errorMessage
+ * the message to display in case the value does not validate.
+ * @param minValue
+ * The minimum value to accept or null for no limit
+ * @param maxValue
+ * The maximum value to accept or null for no limit
+ */
+ public DoubleRangeValidator(String errorMessage, Double minValue, Double maxValue) {
+ super(errorMessage, Double.class, minValue, maxValue);
+ }
+
+}
diff --git a/src/com/vaadin/data/validator/DoubleValidator.java b/src/com/vaadin/data/validator/DoubleValidator.java
index e90919c17d..f603f57480 100644
--- a/src/com/vaadin/data/validator/DoubleValidator.java
+++ b/src/com/vaadin/data/validator/DoubleValidator.java
@@ -12,7 +12,9 @@ package com.vaadin.data.validator;
* @version
* @VERSION@
* @since 5.4
+ * @deprecated in Vaadin 7.0. Use an Double converter on the field instead.
*/
+@Deprecated
@SuppressWarnings("serial")
public class DoubleValidator extends AbstractStringValidator {
@@ -22,13 +24,17 @@ public class DoubleValidator extends AbstractStringValidator {
*
* @param errorMessage
* the message to display in case the value does not validate.
+ * @deprecated in Vaadin 7.0. Use a Double converter on the field instead
+ * and/or use a {@link DoubleRangeValidator} for validating that
+ * the value is inside a given range.
*/
+ @Deprecated
public DoubleValidator(String errorMessage) {
super(errorMessage);
}
@Override
- protected boolean isValidString(String value) {
+ protected boolean isValidValue(String value) {
try {
Double.parseDouble(value);
return true;
diff --git a/src/com/vaadin/data/validator/IntegerRangeValidator.java b/src/com/vaadin/data/validator/IntegerRangeValidator.java
new file mode 100644
index 0000000000..c171dd97d8
--- /dev/null
+++ b/src/com/vaadin/data/validator/IntegerRangeValidator.java
@@ -0,0 +1,37 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.data.validator;
+
+/**
+ * Validator for validating that an {@link Integer} is inside a given range.
+ *
+ * @author Vaadin Ltd.
+ * @version
+ * @VERSION@
+ * @since 5.4
+ */
+@SuppressWarnings("serial")
+public class IntegerRangeValidator extends RangeValidator<Integer> {
+
+ /**
+ * Creates a validator for checking that an Integer is within a given range.
+ *
+ * By default the range is inclusive i.e. both minValue and maxValue are
+ * valid values. Use {@link #setMinValueIncluded(boolean)} or
+ * {@link #setMaxValueIncluded(boolean)} to change it.
+ *
+ *
+ * @param errorMessage
+ * the message to display in case the value does not validate.
+ * @param minValue
+ * The minimum value to accept or null for no limit
+ * @param maxValue
+ * The maximum value to accept or null for no limit
+ */
+ public IntegerRangeValidator(String errorMessage, Integer minValue,
+ Integer maxValue) {
+ super(errorMessage, Integer.class, minValue, maxValue);
+ }
+
+}
diff --git a/src/com/vaadin/data/validator/IntegerValidator.java b/src/com/vaadin/data/validator/IntegerValidator.java
index 50b45b90ce..bf46497594 100644
--- a/src/com/vaadin/data/validator/IntegerValidator.java
+++ b/src/com/vaadin/data/validator/IntegerValidator.java
@@ -12,8 +12,10 @@ package com.vaadin.data.validator;
* @version
* @VERSION@
* @since 5.4
+ * @deprecated in Vaadin 7.0. Use an Integer converter on the field instead.
*/
@SuppressWarnings("serial")
+@Deprecated
public class IntegerValidator extends AbstractStringValidator {
/**
@@ -22,14 +24,18 @@ public class IntegerValidator extends AbstractStringValidator {
*
* @param errorMessage
* the message to display in case the value does not validate.
+ * @deprecated in Vaadin 7.0. Use an Integer converter on the field instead
+ * and/or use an {@link IntegerRangeValidator} for validating
+ * that the value is inside a given range.
*/
+ @Deprecated
public IntegerValidator(String errorMessage) {
super(errorMessage);
}
@Override
- protected boolean isValidString(String value) {
+ protected boolean isValidValue(String value) {
try {
Integer.parseInt(value);
return true;
diff --git a/src/com/vaadin/data/validator/RangeValidator.java b/src/com/vaadin/data/validator/RangeValidator.java
new file mode 100644
index 0000000000..0847b8ed7b
--- /dev/null
+++ b/src/com/vaadin/data/validator/RangeValidator.java
@@ -0,0 +1,172 @@
+package com.vaadin.data.validator;
+
+/**
+ * An base implementation for validating any objects that implement
+ * {@link Comparable}.
+ *
+ * Verifies that the value is of the given type and within the (optionally)
+ * given limits. Typically you want to use a sub class of this like
+ * {@link IntegerRangeValidator}, {@link DoubleRangeValidator} or
+ * {@link DateRangeValidator} in applications.
+ *
+ * @param <T>
+ * The type of Number to validate. Must implement Comparable so that
+ * minimum and maximum checks work.
+ * @author Vaadin Ltd.
+ * @version
+ * @VERSION@
+ * @since 7.0
+ */
+public class RangeValidator<T extends Comparable> extends AbstractValidator<T> {
+
+ private T minValue = null;
+ private boolean minValueIncluded = true;
+ private T maxValue = null;
+ private boolean maxValueIncluded = true;
+ private Class<T> type;
+
+ /**
+ * Creates a new range validator of the given type.
+ *
+ * @param errorMessage
+ * The error message to use if validation fails
+ * @param type
+ * The type of object the validator can validate.
+ * @param minValue
+ * The minimum value that should be accepted or null for no limit
+ * @param maxValue
+ * The maximum value that should be accepted or null for no limit
+ */
+ public RangeValidator(String errorMessage, Class<T> type, T minValue,
+ T maxValue) {
+ super(errorMessage);
+ this.type = type;
+ this.minValue = minValue;
+ this.maxValue = maxValue;
+ }
+
+ /**
+ * Checks if the minimum value is part of the accepted range
+ *
+ * @return true if the minimum value is part of the range, false otherwise
+ */
+ public boolean isMinValueIncluded() {
+ return minValueIncluded;
+ }
+
+ /**
+ * Sets if the minimum value is part of the accepted range
+ *
+ * @param minValueIncluded
+ * true if the minimum value should be part of the range, false
+ * otherwise
+ */
+ public void setMinValueIncluded(boolean minValueIncluded) {
+ this.minValueIncluded = minValueIncluded;
+ }
+
+ /**
+ * Checks if the maximum value is part of the accepted range
+ *
+ * @return true if the maximum value is part of the range, false otherwise
+ */
+ public boolean isMaxValueIncluded() {
+ return maxValueIncluded;
+ }
+
+ /**
+ * Sets if the maximum value is part of the accepted range
+ *
+ * @param maxValueIncluded
+ * true if the maximum value should be part of the range, false
+ * otherwise
+ */
+ public void setMaxValueIncluded(boolean maxValueIncluded) {
+ this.maxValueIncluded = maxValueIncluded;
+ }
+
+ /**
+ * Gets the minimum value of the range
+ *
+ * @return the minimum value
+ */
+ public T getMinValue() {
+ return minValue;
+ }
+
+ /**
+ * Sets the minimum value of the range. Use
+ * {@link #setMinValueIncluded(boolean)} to control whether this value is
+ * part of the range or not.
+ *
+ * @param minValue
+ * the minimum value
+ */
+ public void setMinValue(T minValue) {
+ this.minValue = minValue;
+ }
+
+ /**
+ * Gets the maximum value of the range
+ *
+ * @return the maximum value
+ */
+ public T getMaxValue() {
+ return maxValue;
+ }
+
+ /**
+ * Sets the maximum value of the range. Use
+ * {@link #setMaxValueIncluded(boolean)} to control whether this value is
+ * part of the range or not.
+ *
+ * @param maxValue
+ * the maximum value
+ */
+ public void setMaxValue(T maxValue) {
+ this.maxValue = maxValue;
+ }
+
+ /* (non-Javadoc)
+ * @see com.vaadin.data.validator.AbstractValidator#isValidValue(java.lang.Object)
+ */
+ @Override
+ protected boolean isValidValue(T value) {
+ if (value == null) {
+ return true;
+ }
+
+ if (getMinValue() != null) {
+ // Ensure that the min limit is ok
+ int result = value.compareTo(getMinValue());
+ if (result < 0) {
+ // value less than min value
+ return false;
+ } else if (result == 0 && !isMinValueIncluded()) {
+ // values equal and min value not included
+ return false;
+ }
+ }
+ if (getMaxValue() != null) {
+ // Ensure that the Max limit is ok
+ int result = value.compareTo(getMaxValue());
+ if (result > 0) {
+ // value greater than max value
+ return false;
+ } else if (result == 0 && !isMaxValueIncluded()) {
+ // values equal and max value not included
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see com.vaadin.data.validator.AbstractValidator#getType()
+ */
+ @Override
+ public Class<T> getType() {
+ return type;
+ }
+
+}
diff --git a/src/com/vaadin/data/validator/RegexpValidator.java b/src/com/vaadin/data/validator/RegexpValidator.java
index 684de7697c..dec0bf0be9 100644
--- a/src/com/vaadin/data/validator/RegexpValidator.java
+++ b/src/com/vaadin/data/validator/RegexpValidator.java
@@ -62,8 +62,11 @@ public class RegexpValidator extends AbstractStringValidator {
this.complete = complete;
}
+ /* (non-Javadoc)
+ * @see com.vaadin.data.validator.AbstractValidator#isValidValue(java.lang.Object)
+ */
@Override
- protected boolean isValidString(String value) {
+ protected boolean isValidValue(String value) {
if (complete) {
return getMatcher(value).matches();
} else {
diff --git a/src/com/vaadin/data/validator/StringLengthValidator.java b/src/com/vaadin/data/validator/StringLengthValidator.java
index 1f2b569726..a6242e8170 100644
--- a/src/com/vaadin/data/validator/StringLengthValidator.java
+++ b/src/com/vaadin/data/validator/StringLengthValidator.java
@@ -14,7 +14,7 @@ package com.vaadin.data.validator;
* @since 3.0
*/
@SuppressWarnings("serial")
-public class StringLengthValidator extends AbstractValidator {
+public class StringLengthValidator extends AbstractStringValidator {
private int minLength = -1;
@@ -62,15 +62,11 @@ public class StringLengthValidator extends AbstractValidator {
* @return <code>true</code> for valid value, otherwise <code>false</code>.
*/
@Override
- protected boolean isValidValue(Object value) {
+ protected boolean isValidValue(String value) {
if (value == null) {
return allowNull;
}
- final String s = value.toString();
- if (s == null) {
- return allowNull;
- }
- final int len = s.length();
+ final int len = value.length();
if ((minLength >= 0 && len < minLength)
|| (maxLength >= 0 && len > maxLength)) {
return false;
diff --git a/src/com/vaadin/ui/AbstractField.java b/src/com/vaadin/ui/AbstractField.java
index fb7efc41f5..6b1c535a03 100644
--- a/src/com/vaadin/ui/AbstractField.java
+++ b/src/com/vaadin/ui/AbstractField.java
@@ -245,15 +245,12 @@ public abstract class AbstractField<T> extends AbstractComponent implements
public void commit() throws Buffered.SourceException, InvalidValueException {
if (dataSource != null && !dataSource.isReadOnly()) {
if ((isInvalidCommitted() || isValid())) {
- final T fieldValue = getFieldValue();
try {
// Commits the value to datasource.
valueWasModifiedByDataSourceDuringCommit = false;
committingValueToDataSource = true;
- getPropertyDataSource().setValue(
- convertToDataSource(fieldValue));
-
+ getPropertyDataSource().setValue(getConvertedFieldValue());
} catch (final Throwable e) {
// Sets the buffering state.
@@ -518,7 +515,8 @@ public abstract class AbstractField<T> extends AbstractComponent implements
* @throws Property.ConversionException
*/
protected void setValue(T newFieldValue, boolean repaintIsNotNeeded)
- throws Property.ReadOnlyException, Property.ConversionException {
+ throws Property.ReadOnlyException, Property.ConversionException,
+ InvalidValueException {
if (!equals(newFieldValue, getInternalValue())) {
@@ -529,19 +527,19 @@ public abstract class AbstractField<T> extends AbstractComponent implements
// Repaint is needed even when the client thinks that it knows the
// new state if validity of the component may change
- if (repaintIsNotNeeded && (isRequired() || getValidators() != null)) {
+ if (repaintIsNotNeeded
+ && (isRequired() || getValidators() != null || getValueConverter() != null)) {
repaintIsNotNeeded = false;
}
- // If invalid values are not allowed, the value must be checked
if (!isInvalidAllowed()) {
- final Collection<Validator> v = getValidators();
- if (v != null) {
- for (final Iterator<Validator> i = v.iterator(); i
- .hasNext();) {
- (i.next()).validate(newFieldValue);
- }
- }
+ /*
+ * 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
@@ -717,15 +715,15 @@ public abstract class AbstractField<T> extends AbstractComponent implements
}
/**
- * Sets the value converter for the field from the converter factory defined
- * for the application. Clears the value converter if no application
+ * Retrieves a value converter for the field from the converter factory
+ * defined for the application. Clears the value 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
*/
- private void updateValueConverterFromFactory(Class<?> datamodelType) {
+ public void updateValueConverterFromFactory(Class<?> datamodelType) {
Converter<?, T> converter = null;
Application app = Application.getCurrentApplication();
@@ -822,6 +820,15 @@ public abstract class AbstractField<T> extends AbstractComponent implements
}
}
+ /**
+ * Returns the current field value converted to the data source type.
+ *
+ * @return The converted value that is compatible with the data source type
+ */
+ public Object getConvertedFieldValue() {
+ return convertToDataSource(getFieldValue());
+ }
+
/* Validation */
/**
@@ -891,8 +898,9 @@ public abstract class AbstractField<T> extends AbstractComponent implements
* Checks the validity of the Field.
*
* A field is invalid if it is set as required (using
- * {@link #setRequired(boolean)} and is empty or if one or several of the
- * validators added to the field indicate it is invalid.
+ * {@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 value 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
@@ -905,30 +913,49 @@ public abstract class AbstractField<T> extends AbstractComponent implements
if (isRequired() && isEmpty()) {
throw new Validator.EmptyValueException(requiredError);
}
+ validate(getFieldValue());
+ }
- // If there is no validator, there can not be any errors
- if (validators == null) {
- return;
- }
-
- final Object fieldValue = 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 {
- List<InvalidValueException> validationExceptions = null;
+ Object valueToValidate = fieldValue;
- // Gets all the validation errors
- for (Validator v : validators) {
+ // If there is a converter we start by converting the value as we want
+ // to validate the converted value
+ if (getValueConverter() != null) {
try {
- v.validate(fieldValue);
- } catch (final Validator.InvalidValueException e) {
- if (validationExceptions == null) {
- validationExceptions = new ArrayList<InvalidValueException>();
+ valueToValidate = getValueConverter()
+ .convertFromTargetToSource(fieldValue, getLocale());
+ } catch (Exception e) {
+ throw new InvalidValueException(e.getMessage());
+ }
+ }
+
+ List<InvalidValueException> validationExceptions = new ArrayList<InvalidValueException>();
+ if (validators != null) {
+ // Gets all the validation errors
+ for (Validator v : validators) {
+ try {
+ v.validate(valueToValidate);
+ } catch (final Validator.InvalidValueException e) {
+ validationExceptions.add(e);
}
- validationExceptions.add(e);
}
}
- // If there were no error
- if (validationExceptions == null) {
+ // If there were no errors
+ if (validationExceptions.isEmpty()) {
return;
}