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