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.

CompositeValidator.java 7.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. /*
  2. @VaadinApache2LicenseForJavaFiles@
  3. */
  4. package com.vaadin.data.validator;
  5. import java.util.Collection;
  6. import java.util.HashSet;
  7. import java.util.LinkedList;
  8. import java.util.List;
  9. import com.vaadin.data.Validator;
  10. /**
  11. * The <code>CompositeValidator</code> allows you to chain (compose) many
  12. * validators to validate one field. The contained validators may be required to
  13. * all validate the value to validate or it may be enough that one contained
  14. * validator validates the value. This behaviour is controlled by the modes
  15. * <code>AND</code> and <code>OR</code>.
  16. *
  17. * @author Vaadin Ltd.
  18. * @version @VERSION@
  19. * @since 3.0
  20. */
  21. @SuppressWarnings("serial")
  22. public class CompositeValidator implements Validator {
  23. public enum CombinationMode {
  24. /**
  25. * The validators are combined with <code>AND</code> clause: validity of
  26. * the composite implies validity of the all validators it is composed
  27. * of must be valid.
  28. */
  29. AND,
  30. /**
  31. * The validators are combined with <code>OR</code> clause: validity of
  32. * the composite implies that some of validators it is composed of must
  33. * be valid.
  34. */
  35. OR;
  36. }
  37. /**
  38. * @deprecated from 7.0, use {@link CombinationMode#AND} instead    
  39. */
  40. @Deprecated
  41. public static final CombinationMode MODE_AND = CombinationMode.AND;
  42. /**
  43. * @deprecated from 7.0, use {@link CombinationMode#OR} instead    
  44. */
  45. @Deprecated
  46. public static final CombinationMode MODE_OR = CombinationMode.OR;
  47. private String errorMessage;
  48. /**
  49. * Operation mode.
  50. */
  51. private CombinationMode mode = CombinationMode.AND;
  52. /**
  53. * List of contained validators.
  54. */
  55. private final List<Validator> validators = new LinkedList<Validator>();
  56. /**
  57. * Construct a composite validator in <code>AND</code> mode without error
  58. * message.
  59. */
  60. public CompositeValidator() {
  61. this(CombinationMode.AND, "");
  62. }
  63. /**
  64. * Constructs a composite validator in given mode.
  65. *
  66. * @param mode
  67. * @param errorMessage
  68. */
  69. public CompositeValidator(CombinationMode mode, String errorMessage) {
  70. setErrorMessage(errorMessage);
  71. setMode(mode);
  72. }
  73. /**
  74. * Validates the given value.
  75. * <p>
  76. * The value is valid, if:
  77. * <ul>
  78. * <li><code>MODE_AND</code>: All of the sub-validators are valid
  79. * <li><code>MODE_OR</code>: Any of the sub-validators are valid
  80. * </ul>
  81. *
  82. * If the value is invalid, validation error is thrown. If the error message
  83. * is set (non-null), it is used. If the error message has not been set, the
  84. * first error occurred is thrown.
  85. * </p>
  86. *
  87. * @param value
  88. * the value to check.
  89. * @throws Validator.InvalidValueException
  90. * if the value is not valid.
  91. */
  92. @Override
  93. public void validate(Object value) throws Validator.InvalidValueException {
  94. switch (mode) {
  95. case AND:
  96. for (Validator validator : validators) {
  97. validator.validate(value);
  98. }
  99. return;
  100. case OR:
  101. Validator.InvalidValueException first = null;
  102. for (Validator v : validators) {
  103. try {
  104. v.validate(value);
  105. return;
  106. } catch (final Validator.InvalidValueException e) {
  107. if (first == null) {
  108. first = e;
  109. }
  110. }
  111. }
  112. if (first == null) {
  113. return;
  114. }
  115. final String em = getErrorMessage();
  116. if (em != null) {
  117. throw new Validator.InvalidValueException(em);
  118. } else {
  119. throw first;
  120. }
  121. }
  122. }
  123. /**
  124. * Gets the mode of the validator.
  125. *
  126. * @return Operation mode of the validator: {@link CombinationMode#AND} or
  127. * {@link CombinationMode#OR}.
  128. */
  129. public final CombinationMode getMode() {
  130. return mode;
  131. }
  132. /**
  133. * Sets the mode of the validator. The valid modes are:
  134. * <ul>
  135. * <li>{@link CombinationMode#AND} (default)
  136. * <li>{@link CombinationMode#OR}
  137. * </ul>
  138. *
  139. * @param mode
  140. * the mode to set.
  141. */
  142. public void setMode(CombinationMode mode) {
  143. if (mode == null) {
  144. throw new IllegalArgumentException(
  145. "The validator can't be set to null");
  146. }
  147. this.mode = mode;
  148. }
  149. /**
  150. * Gets the error message for the composite validator. If the error message
  151. * is null, original error messages of the sub-validators are used instead.
  152. */
  153. public String getErrorMessage() {
  154. if (errorMessage != null) {
  155. return errorMessage;
  156. }
  157. // TODO Return composite error message
  158. return null;
  159. }
  160. /**
  161. * Adds validator to the interface.
  162. *
  163. * @param validator
  164. * the Validator object which performs validation checks on this
  165. * set of data field values.
  166. */
  167. public void addValidator(Validator validator) {
  168. if (validator == null) {
  169. return;
  170. }
  171. validators.add(validator);
  172. }
  173. /**
  174. * Removes a validator from the composite.
  175. *
  176. * @param validator
  177. * the Validator object which performs validation checks on this
  178. * set of data field values.
  179. */
  180. public void removeValidator(Validator validator) {
  181. validators.remove(validator);
  182. }
  183. /**
  184. * Gets sub-validators by class.
  185. *
  186. * <p>
  187. * If the component contains directly or recursively (it contains another
  188. * composite containing the validator) validators compatible with given type
  189. * they are returned. This only applies to <code>AND</code> mode composite
  190. * validators.
  191. * </p>
  192. *
  193. * <p>
  194. * If the validator is in <code>OR</code> mode or does not contain any
  195. * validators of given type null is returned.
  196. * </p>
  197. *
  198. * @param validatorType
  199. * The type of validators to return
  200. *
  201. * @return Collection<Validator> of validators compatible with given type
  202. * that must apply or null if none found.
  203. */
  204. public Collection<Validator> getSubValidators(Class validatorType) {
  205. if (mode != CombinationMode.AND) {
  206. return null;
  207. }
  208. final HashSet<Validator> found = new HashSet<Validator>();
  209. for (Validator v : validators) {
  210. if (validatorType.isAssignableFrom(v.getClass())) {
  211. found.add(v);
  212. }
  213. if (v instanceof CompositeValidator
  214. && ((CompositeValidator) v).getMode() == MODE_AND) {
  215. final Collection<Validator> c = ((CompositeValidator) v)
  216. .getSubValidators(validatorType);
  217. if (c != null) {
  218. found.addAll(c);
  219. }
  220. }
  221. }
  222. return found.isEmpty() ? null : found;
  223. }
  224. /**
  225. * Sets the message to be included in the exception in case the value does
  226. * not validate. The exception message is typically shown to the end user.
  227. *
  228. * @param errorMessage
  229. * the error message.
  230. */
  231. public void setErrorMessage(String errorMessage) {
  232. this.errorMessage = errorMessage;
  233. }
  234. }