PageRenderTime 41ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/framework/src/play-java/src/main/java/play/data/validation/Constraints.java

https://gitlab.com/KiaraGrouwstra/playframework
Java | 511 lines | 309 code | 106 blank | 96 comment | 28 complexity | a87bf8c4cb3c2c30edabdd1b782a160b MD5 | raw file
  1. /*
  2. * Copyright (C) 2009-2015 Typesafe Inc. <http://www.typesafe.com>
  3. */
  4. package play.data.validation;
  5. import play.libs.F.*;
  6. import static play.libs.F.*;
  7. import static java.lang.annotation.ElementType.*;
  8. import static java.lang.annotation.RetentionPolicy.*;
  9. import java.lang.annotation.*;
  10. import java.lang.reflect.Constructor;
  11. import java.lang.reflect.Method;
  12. import javax.validation.*;
  13. import javax.validation.metadata.*;
  14. import java.util.*;
  15. /**
  16. * Defines a set of built-in validation constraints.
  17. */
  18. public class Constraints {
  19. /**
  20. * Super-type for validators.
  21. */
  22. public static abstract class Validator<T> {
  23. /**
  24. * Returns <code>true</code> if this value is valid.
  25. */
  26. public abstract boolean isValid(T object);
  27. /**
  28. * Returns <code>true</code> if this value is valid for the given constraint.
  29. *
  30. * @param constraintContext The JSR-303 validation context.
  31. */
  32. public boolean isValid(T object, ConstraintValidatorContext constraintContext) {
  33. return isValid(object);
  34. }
  35. public abstract Tuple<String, Object[]> getErrorMessageKey();
  36. }
  37. /**
  38. * Converts a set of constraints to human-readable values.
  39. */
  40. public static List<Tuple<String,List<Object>>> displayableConstraint(Set<ConstraintDescriptor<?>> constraints) {
  41. List<Tuple<String,List<Object>>> displayable = new ArrayList<Tuple<String,List<Object>>>();
  42. for(ConstraintDescriptor<?> c: constraints) {
  43. Class<?> annotationType = c.getAnnotation().annotationType();
  44. if(annotationType.isAnnotationPresent(play.data.Form.Display.class)) {
  45. play.data.Form.Display d = annotationType.getAnnotation(play.data.Form.Display.class);
  46. String name = d.name();
  47. List<Object> attributes = new ArrayList<Object>();
  48. Map<String,Object> annotationAttributes = c.getAttributes();
  49. for(String attr: d.attributes()) {
  50. attributes.add(annotationAttributes.get(attr));
  51. }
  52. displayable.add(Tuple(name, attributes));
  53. }
  54. }
  55. return displayable;
  56. }
  57. // --- Required
  58. /**
  59. * Defines a field as required.
  60. */
  61. @Target({FIELD})
  62. @Retention(RUNTIME)
  63. @Constraint(validatedBy = RequiredValidator.class)
  64. @play.data.Form.Display(name="constraint.required")
  65. public static @interface Required {
  66. String message() default RequiredValidator.message;
  67. Class<?>[] groups() default {};
  68. Class<? extends Payload>[] payload() default {};
  69. }
  70. /**
  71. * Validator for <code>@Required</code> fields.
  72. */
  73. public static class RequiredValidator extends Validator<Object> implements ConstraintValidator<Required, Object> {
  74. final static public String message = "error.required";
  75. public void initialize(Required constraintAnnotation) {}
  76. public boolean isValid(Object object) {
  77. if(object == null) {
  78. return false;
  79. }
  80. if(object instanceof String) {
  81. return !((String)object).isEmpty();
  82. }
  83. if(object instanceof Collection) {
  84. return !((Collection)object).isEmpty();
  85. }
  86. return true;
  87. }
  88. public Tuple<String, Object[]> getErrorMessageKey() {
  89. return Tuple(message, new Object[] {});
  90. }
  91. }
  92. /**
  93. * Constructs a 'required' validator.
  94. */
  95. public static Validator<Object> required() {
  96. return new RequiredValidator();
  97. }
  98. // --- Min
  99. /**
  100. * Defines a minumum value for a numeric field.
  101. */
  102. @Target({FIELD})
  103. @Retention(RUNTIME)
  104. @Constraint(validatedBy = MinValidator.class)
  105. @play.data.Form.Display(name="constraint.min", attributes={"value"})
  106. public static @interface Min {
  107. String message() default MinValidator.message;
  108. Class<?>[] groups() default {};
  109. Class<? extends Payload>[] payload() default {};
  110. long value();
  111. }
  112. /**
  113. * Validator for <code>@Min</code> fields.
  114. */
  115. public static class MinValidator extends Validator<Number> implements ConstraintValidator<Min, Number> {
  116. final static public String message = "error.min";
  117. private long min;
  118. public MinValidator() {}
  119. public MinValidator(long value) {
  120. this.min = value;
  121. }
  122. public void initialize(Min constraintAnnotation) {
  123. this.min = constraintAnnotation.value();
  124. }
  125. public boolean isValid(Number object) {
  126. if(object == null) {
  127. return true;
  128. }
  129. return object.longValue() >= min;
  130. }
  131. public Tuple<String, Object[]> getErrorMessageKey() {
  132. return Tuple(message, new Object[] { min });
  133. }
  134. }
  135. /**
  136. * Constructs a 'min' validator.
  137. */
  138. public static Validator<Number> min(long value) {
  139. return new MinValidator(value);
  140. }
  141. // --- Max
  142. /**
  143. * Defines a maximum value for a numeric field.
  144. */
  145. @Target({FIELD})
  146. @Retention(RUNTIME)
  147. @Constraint(validatedBy = MaxValidator.class)
  148. @play.data.Form.Display(name="constraint.max", attributes={"value"})
  149. public static @interface Max {
  150. String message() default MaxValidator.message;
  151. Class<?>[] groups() default {};
  152. Class<? extends Payload>[] payload() default {};
  153. long value();
  154. }
  155. /**
  156. * Validator for <code>@Max</code> fields.
  157. */
  158. public static class MaxValidator extends Validator<Number> implements ConstraintValidator<Max, Number> {
  159. final static public String message = "error.max";
  160. private long max;
  161. public MaxValidator() {}
  162. public MaxValidator(long value) {
  163. this.max = value;
  164. }
  165. public void initialize(Max constraintAnnotation) {
  166. this.max = constraintAnnotation.value();
  167. }
  168. public boolean isValid(Number object) {
  169. if(object == null) {
  170. return true;
  171. }
  172. return object.longValue() <= max;
  173. }
  174. public Tuple<String, Object[]> getErrorMessageKey() {
  175. return Tuple(message, new Object[] { max });
  176. }
  177. }
  178. /**
  179. * Constructs a 'max' validator.
  180. */
  181. public static Validator<Number> max(long value) {
  182. return new MaxValidator(value);
  183. }
  184. // --- MinLength
  185. /**
  186. * Defines a minumum length for a string field.
  187. */
  188. @Target({FIELD})
  189. @Retention(RUNTIME)
  190. @Constraint(validatedBy = MinLengthValidator.class)
  191. @play.data.Form.Display(name="constraint.minLength", attributes={"value"})
  192. public static @interface MinLength {
  193. String message() default MinLengthValidator.message;
  194. Class<?>[] groups() default {};
  195. Class<? extends Payload>[] payload() default {};
  196. long value();
  197. }
  198. /**
  199. * Validator for <code>@MinLength</code> fields.
  200. */
  201. public static class MinLengthValidator extends Validator<String> implements ConstraintValidator<MinLength, String> {
  202. final static public String message = "error.minLength";
  203. private long min;
  204. public MinLengthValidator() {}
  205. public MinLengthValidator(long value) {
  206. this.min = value;
  207. }
  208. public void initialize(MinLength constraintAnnotation) {
  209. this.min = constraintAnnotation.value();
  210. }
  211. public boolean isValid(String object) {
  212. if(object == null || object.length() == 0) {
  213. return true;
  214. }
  215. return object.length() >= min;
  216. }
  217. public Tuple<String, Object[]> getErrorMessageKey() {
  218. return Tuple(message, new Object[] { min });
  219. }
  220. }
  221. /**
  222. * Constructs a 'minLength' validator.
  223. */
  224. public static Validator<String> minLength(long value) {
  225. return new MinLengthValidator(value);
  226. }
  227. // --- MaxLength
  228. /**
  229. * Defines a maxmimum length for a string field.
  230. */
  231. @Target({FIELD})
  232. @Retention(RUNTIME)
  233. @Constraint(validatedBy = MaxLengthValidator.class)
  234. @play.data.Form.Display(name="constraint.maxLength", attributes={"value"})
  235. public static @interface MaxLength {
  236. String message() default MaxLengthValidator.message;
  237. Class<?>[] groups() default {};
  238. Class<? extends Payload>[] payload() default {};
  239. long value();
  240. }
  241. /**
  242. * Validator for <code>@MaxLength</code> fields.
  243. */
  244. public static class MaxLengthValidator extends Validator<String> implements ConstraintValidator<MaxLength, String> {
  245. final static public String message = "error.maxLength";
  246. private long max;
  247. public MaxLengthValidator() {}
  248. public MaxLengthValidator(long value) {
  249. this.max = value;
  250. }
  251. public void initialize(MaxLength constraintAnnotation) {
  252. this.max = constraintAnnotation.value();
  253. }
  254. public boolean isValid(String object) {
  255. if(object == null || object.length() == 0) {
  256. return true;
  257. }
  258. return object.length() <= max;
  259. }
  260. public Tuple<String, Object[]> getErrorMessageKey() {
  261. return Tuple(message, new Object[] { max });
  262. }
  263. }
  264. /**
  265. * Constructs a 'maxLength' validator.
  266. */
  267. public static Validator<String> maxLength(long value) {
  268. return new MaxLengthValidator(value);
  269. }
  270. // --- Email
  271. /**
  272. * Defines a email constraint for a string field.
  273. */
  274. @Target({FIELD})
  275. @Retention(RUNTIME)
  276. @Constraint(validatedBy = EmailValidator.class)
  277. @play.data.Form.Display(name="constraint.email", attributes={})
  278. public static @interface Email {
  279. String message() default EmailValidator.message;
  280. Class<?>[] groups() default {};
  281. Class<? extends Payload>[] payload() default {};
  282. }
  283. /**
  284. * Validator for <code>@Email</code> fields.
  285. */
  286. public static class EmailValidator extends Validator<String> implements ConstraintValidator<Email, String> {
  287. final static public String message = "error.email";
  288. final static java.util.regex.Pattern regex = java.util.regex.Pattern.compile(
  289. "\\b[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*\\b");
  290. public EmailValidator() {}
  291. public void initialize(Email constraintAnnotation) {
  292. }
  293. public boolean isValid(String object) {
  294. if(object == null || object.length() == 0) {
  295. return true;
  296. }
  297. return regex.matcher(object).matches();
  298. }
  299. public Tuple<String, Object[]> getErrorMessageKey() {
  300. return Tuple(message, new Object[] {});
  301. }
  302. }
  303. /**
  304. * Constructs a 'email' validator.
  305. */
  306. public static Validator<String> email() {
  307. return new EmailValidator();
  308. }
  309. // --- Pattern
  310. /**
  311. * Defines a pattern constraint for a string field.
  312. */
  313. @Target({FIELD})
  314. @Retention(RUNTIME)
  315. @Constraint(validatedBy = PatternValidator.class)
  316. @play.data.Form.Display(name="constraint.pattern", attributes={"value"})
  317. public static @interface Pattern {
  318. String message() default PatternValidator.message;
  319. Class<?>[] groups() default {};
  320. Class<? extends Payload>[] payload() default {};
  321. String value();
  322. }
  323. /**
  324. * Validator for <code>@Pattern</code> fields.
  325. */
  326. public static class PatternValidator extends Validator<String> implements ConstraintValidator<Pattern, String> {
  327. final static public String message = "error.pattern";
  328. java.util.regex.Pattern regex = null;
  329. public PatternValidator() {}
  330. public PatternValidator(String regex) {
  331. this.regex = java.util.regex.Pattern.compile(regex);
  332. }
  333. public void initialize(Pattern constraintAnnotation) {
  334. regex = java.util.regex.Pattern.compile(constraintAnnotation.value());
  335. }
  336. public boolean isValid(String object) {
  337. if(object == null || object.length() == 0) {
  338. return true;
  339. }
  340. return regex.matcher(object).matches();
  341. }
  342. public Tuple<String, Object[]> getErrorMessageKey() {
  343. return Tuple(message, new Object[] { regex });
  344. }
  345. }
  346. /**
  347. * Constructs a 'pattern' validator.
  348. */
  349. public static Validator<String> pattern(String regex) {
  350. return new PatternValidator(regex);
  351. }
  352. /**
  353. * Defines a custom validator.
  354. */
  355. @Target({FIELD})
  356. @Retention(RUNTIME)
  357. @Constraint(validatedBy = ValidateWithValidator.class)
  358. @play.data.Form.Display(name="constraint.validatewith", attributes={})
  359. public static @interface ValidateWith {
  360. String message() default ValidateWithValidator.defaultMessage;
  361. Class<?>[] groups() default {};
  362. Class<? extends Payload>[] payload() default {};
  363. Class<? extends Validator> value();
  364. }
  365. /**
  366. * Validator for <code>@ValidateWith</code> fields.
  367. */
  368. public static class ValidateWithValidator extends Validator<Object> implements ConstraintValidator<ValidateWith, Object> {
  369. final static public String defaultMessage = "error.invalid";
  370. Class<?> clazz = null;
  371. Validator validator = null;
  372. public ValidateWithValidator() {}
  373. public ValidateWithValidator(Class clazz) {
  374. this.clazz = clazz;
  375. }
  376. public void initialize(ValidateWith constraintAnnotation) {
  377. this.clazz = constraintAnnotation.value();
  378. try {
  379. Constructor<?> constructor = clazz.getDeclaredConstructor();
  380. constructor.setAccessible(true);
  381. validator = (Validator)constructor.newInstance();
  382. } catch(Exception e) {
  383. throw new RuntimeException(e);
  384. }
  385. }
  386. @SuppressWarnings("unchecked")
  387. public boolean isValid(Object object) {
  388. try {
  389. return validator.isValid(object);
  390. } catch(Exception e) {
  391. throw new RuntimeException(e);
  392. }
  393. }
  394. @SuppressWarnings("unchecked")
  395. public Tuple<String, Object[]> getErrorMessageKey() {
  396. Tuple<String, Object[]> errorMessageKey = null;
  397. try {
  398. errorMessageKey = validator.getErrorMessageKey();
  399. } catch(Exception e) {
  400. throw new RuntimeException(e);
  401. }
  402. return (errorMessageKey != null) ? errorMessageKey : Tuple(defaultMessage, new Object[] {});
  403. }
  404. }
  405. }