+++ /dev/null
-/* \r
-@VaadinApache2LicenseForJavaFiles@\r
- */\r
-\r
-package com.vaadin.data.validator;\r
-\r
-import java.util.Collection;\r
-import java.util.Locale;\r
-\r
-import javax.validation.constraints.NotNull;\r
-\r
-import com.vaadin.data.Item;\r
-import com.vaadin.data.util.BeanItem;\r
-import com.vaadin.ui.Field;\r
-import com.vaadin.ui.Form;\r
-\r
-/**\r
- * Vaadin {@link Form} using the JSR-303 (javax.validation) declarative bean\r
- * validation on its fields.\r
- * \r
- * Most validation is performed using {@link BeanValidationValidator}. In\r
- * addition, fields are automatically marked as required when necessary based on\r
- * the {@link NotNull} annotations.\r
- * \r
- * If the item is a {@link BeanItem}, the exact type of the bean is used in\r
- * setting up validators. Otherwise, validation will only be performed based on\r
- * beanClass, and behavior is undefined for subclasses that have fields not\r
- * present in the superclass.\r
- * \r
- * Note that a JSR-303 implementation (e.g. Hibernate Validator or agimatec\r
- * validation) must be present on the project classpath when using bean\r
- * validation.\r
- * \r
- * @since 7.0\r
- * \r
- * @author Petri Hakala\r
- * @author Henri Sara\r
- */\r
-public class BeanValidationForm<T> extends Form {\r
-\r
- private static final long serialVersionUID = 1L;\r
-\r
- private Class<T> beanClass;\r
- private Locale locale;\r
-\r
- /**\r
- * Creates a form that performs validation on beans of the type given by\r
- * beanClass.\r
- * \r
- * Full validation of sub-types of beanClass is performed if the item used\r
- * is a {@link BeanItem}. Otherwise, the class given to this constructor\r
- * determines which properties are validated.\r
- * \r
- * @param beanClass\r
- * base class of beans for the form\r
- */\r
- public BeanValidationForm(Class<T> beanClass) {\r
- if (beanClass == null) {\r
- throw new IllegalArgumentException("Bean class cannot be null");\r
- }\r
- this.beanClass = beanClass;\r
- }\r
-\r
- @Override\r
- public void addField(Object propertyId, Field field) {\r
- Item item = getItemDataSource();\r
- Class<? extends T> beanClass = this.beanClass;\r
- if (item instanceof BeanItem) {\r
- beanClass = (Class<? extends T>) ((BeanItem<T>) item).getBean()\r
- .getClass();\r
- }\r
- BeanValidationValidator validator = BeanValidationValidator\r
- .addValidator(field, propertyId, beanClass);\r
- if (locale != null) {\r
- validator.setLocale(locale);\r
- }\r
- super.addField(propertyId, field);\r
- }\r
-\r
- /**\r
- * Sets the item data source for the form. If the new data source is a\r
- * {@link BeanItem}, its bean must be assignable to the bean class of the\r
- * form.\r
- * \r
- * {@inheritDoc}\r
- */\r
- @Override\r
- public void setItemDataSource(Item newDataSource) {\r
- if ((newDataSource instanceof BeanItem)\r
- && !beanClass.isAssignableFrom(((BeanItem) newDataSource)\r
- .getBean().getClass())) {\r
- throw new IllegalArgumentException("Bean must be of type "\r
- + beanClass.getName());\r
- }\r
- super.setItemDataSource(newDataSource);\r
- }\r
-\r
- /**\r
- * Sets the item data source for the form. If the new data source is a\r
- * {@link BeanItem}, its bean must be assignable to the bean class of the\r
- * form.\r
- * \r
- * {@inheritDoc}\r
- */\r
- @Override\r
- public void setItemDataSource(Item newDataSource, Collection propertyIds) {\r
- if ((newDataSource instanceof BeanItem)\r
- && !beanClass.isAssignableFrom(((BeanItem) newDataSource)\r
- .getBean().getClass())) {\r
- throw new IllegalArgumentException("Bean must be of type "\r
- + beanClass.getName());\r
- }\r
- super.setItemDataSource(newDataSource, propertyIds);\r
- }\r
-\r
- /**\r
- * Returns the base class of beans supported by this form.\r
- * \r
- * @return bean class\r
- */\r
- public Class<T> getBeanClass() {\r
- return beanClass;\r
- }\r
-}
\ No newline at end of file
import java.io.ObjectInputStream;\r
import java.io.Serializable;\r
import java.lang.annotation.Annotation;\r
-import java.lang.reflect.Constructor;\r
import java.lang.reflect.Method;\r
import java.util.ArrayList;\r
import java.util.Iterator;\r
import javax.validation.metadata.ConstraintDescriptor;\r
import javax.validation.metadata.PropertyDescriptor;\r
\r
-import com.vaadin.data.Property;\r
import com.vaadin.data.Validator;\r
-import com.vaadin.data.util.MethodProperty;\r
import com.vaadin.ui.Field;\r
\r
/**\r
private transient javax.validation.Validator validator;\r
private String propertyName;\r
private Class<?> beanClass;\r
- private MethodProperty method;\r
private Locale locale;\r
\r
/**\r
this.beanClass = beanClass;\r
this.propertyName = propertyName;\r
validator = factory.getValidator();\r
- try {\r
- method = new MethodProperty(beanClass.newInstance(), propertyName);\r
- } catch (Exception e) {\r
- throw new IllegalArgumentException("Class '" + beanClass\r
- + "' must contain default constructor");\r
- }\r
locale = Locale.getDefault();\r
}\r
\r
}\r
\r
public void validate(final Object value) throws InvalidValueException {\r
- Object convertedValue = value;\r
- try {\r
- convertedValue = convertValue(value);\r
- } catch (Exception e) {\r
- String msg = getErrorMessage(value);\r
- if (msg != null) {\r
- throw new InvalidValueException(msg);\r
- } else {\r
- // there should be always some constraints if conversion is\r
- // needed\r
- // for example if String -> Integer then Digits annotation\r
- throw new InvalidValueException("Conversion exception");\r
- }\r
- }\r
Set<?> violations = validator.validateValue(beanClass, propertyName,\r
- convertedValue);\r
+ value);\r
if (violations.size() > 0) {\r
List<String> exceptions = new ArrayList<String>();\r
for (Object v : violations) {\r
final ConstraintViolation<?> violation = (ConstraintViolation<?>) v;\r
String msg = factory.getMessageInterpolator().interpolate(\r
violation.getMessageTemplate(),\r
- new SimpleContext(convertedValue, violation\r
+ new SimpleContext(value, violation\r
.getConstraintDescriptor()), locale);\r
exceptions.add(msg);\r
}\r
}\r
}\r
\r
- /**\r
- * Convert the value the way {@link MethodProperty} does: if the bean field\r
- * is assignable from the value, return the value directly. Otherwise, try\r
- * to find a constructor for bean field type that takes a String and call it\r
- * with value.toString() .\r
- * \r
- * @param value\r
- * the value to convert\r
- * @return converted value, assignable to the field of the bean\r
- * @throws {@link ConversionException} if no suitable conversion found or\r
- * the target type constructor from string threw an exception\r
- */\r
- private Object convertValue(Object value)\r
- throws Property.ConversionException {\r
- // Try to assign the compatible value directly\r
- if (value == null\r
- || method.getType().isAssignableFrom(value.getClass())) {\r
- return value;\r
- } else {\r
- try {\r
- // Gets the string constructor\r
- final Constructor constr = method.getType().getConstructor(\r
- new Class[] { String.class });\r
-\r
- return constr.newInstance(new Object[] { value.toString() });\r
-\r
- } catch (final java.lang.Exception e) {\r
- throw new Property.ConversionException(e);\r
- }\r
- }\r
- }\r
-\r
private String getErrorMessage(final Object value,\r
Class<? extends Annotation>... an) {\r
BeanDescriptor beanDesc = validator.getConstraintsForClass(beanClass);\r