You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

BeanValidator.java 5.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /*
  2. @VaadinApache2LicenseForJavaFiles@
  3. */
  4. package com.vaadin.data.validator;
  5. import java.io.Serializable;
  6. import java.util.ArrayList;
  7. import java.util.List;
  8. import java.util.Locale;
  9. import java.util.Set;
  10. import javax.validation.ConstraintViolation;
  11. import javax.validation.MessageInterpolator.Context;
  12. import javax.validation.Validation;
  13. import javax.validation.ValidatorFactory;
  14. import javax.validation.metadata.ConstraintDescriptor;
  15. import com.vaadin.data.Validator;
  16. /**
  17. * Vaadin {@link Validator} using the JSR-303 (javax.validation)
  18. * annotation-based bean validation.
  19. *
  20. * The annotations of the fields of the beans are used to determine the
  21. * validation to perform.
  22. *
  23. * Note that a JSR-303 implementation (e.g. Hibernate Validator or Apache Bean
  24. * Validation - formerly agimatec validation) must be present on the project
  25. * classpath when using bean validation.
  26. *
  27. * @since 7.0
  28. *
  29. * @author Petri Hakala
  30. * @author Henri Sara
  31. */
  32. public class BeanValidator implements Validator {
  33. private static final long serialVersionUID = 1L;
  34. private static ValidatorFactory factory;
  35. private transient javax.validation.Validator javaxBeanValidator;
  36. private String propertyName;
  37. private Class<?> beanClass;
  38. private Locale locale;
  39. /**
  40. * Simple implementation of a message interpolator context that returns
  41. * fixed values.
  42. */
  43. protected static class SimpleContext implements Context, Serializable {
  44. private final Object value;
  45. private final ConstraintDescriptor<?> descriptor;
  46. /**
  47. * Create a simple immutable message interpolator context.
  48. *
  49. * @param value
  50. * value being validated
  51. * @param descriptor
  52. * ConstraintDescriptor corresponding to the constraint being
  53. * validated
  54. */
  55. public SimpleContext(Object value, ConstraintDescriptor<?> descriptor) {
  56. this.value = value;
  57. this.descriptor = descriptor;
  58. }
  59. @Override
  60. public ConstraintDescriptor<?> getConstraintDescriptor() {
  61. return descriptor;
  62. }
  63. @Override
  64. public Object getValidatedValue() {
  65. return value;
  66. }
  67. }
  68. /**
  69. * Creates a Vaadin {@link Validator} utilizing JSR-303 bean validation.
  70. *
  71. * @param beanClass
  72. * bean class based on which the validation should be performed
  73. * @param propertyName
  74. * property to validate
  75. */
  76. public BeanValidator(Class<?> beanClass, String propertyName) {
  77. this.beanClass = beanClass;
  78. this.propertyName = propertyName;
  79. locale = Locale.getDefault();
  80. }
  81. /*
  82. * (non-Javadoc)
  83. *
  84. * @see com.vaadin.data.Validator#validate(java.lang.Object)
  85. */
  86. @Override
  87. public void validate(final Object value) throws InvalidValueException {
  88. Set<?> violations = getJavaxBeanValidator().validateValue(beanClass,
  89. propertyName, value);
  90. if (violations.size() > 0) {
  91. List<String> exceptions = new ArrayList<String>();
  92. for (Object v : violations) {
  93. final ConstraintViolation<?> violation = (ConstraintViolation<?>) v;
  94. String msg = getJavaxBeanValidatorFactory()
  95. .getMessageInterpolator().interpolate(
  96. violation.getMessageTemplate(),
  97. new SimpleContext(value, violation
  98. .getConstraintDescriptor()), locale);
  99. exceptions.add(msg);
  100. }
  101. StringBuilder b = new StringBuilder();
  102. for (int i = 0; i < exceptions.size(); i++) {
  103. if (i != 0) {
  104. b.append("<br/>");
  105. }
  106. b.append(exceptions.get(i));
  107. }
  108. throw new InvalidValueException(b.toString());
  109. }
  110. }
  111. /**
  112. * Sets the locale used for validation error messages.
  113. *
  114. * Revalidation is not automatically triggered by setting the locale.
  115. *
  116. * @param locale
  117. */
  118. public void setLocale(Locale locale) {
  119. this.locale = locale;
  120. }
  121. /**
  122. * Gets the locale used for validation error messages.
  123. *
  124. * @return locale used for validation
  125. */
  126. public Locale getLocale() {
  127. return locale;
  128. }
  129. /**
  130. * Returns the underlying JSR-303 bean validator factory used. A factory is
  131. * created using {@link Validation} if necessary.
  132. *
  133. * @return {@link ValidatorFactory} to use
  134. */
  135. protected static ValidatorFactory getJavaxBeanValidatorFactory() {
  136. if (factory == null) {
  137. factory = Validation.buildDefaultValidatorFactory();
  138. }
  139. return factory;
  140. }
  141. /**
  142. * Returns a shared Validator instance to use. An instance is created using
  143. * the validator factory if necessary and thereafter reused by the
  144. * {@link BeanValidator} instance.
  145. *
  146. * @return the JSR-303 {@link javax.validation.Validator} to use
  147. */
  148. protected javax.validation.Validator getJavaxBeanValidator() {
  149. if (javaxBeanValidator == null) {
  150. javaxBeanValidator = getJavaxBeanValidatorFactory().getValidator();
  151. }
  152. return javaxBeanValidator;
  153. }
  154. }