1b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabotpackage org.junit.internal.runners.rules;
2b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot
3b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabotimport java.lang.annotation.Annotation;
4b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabotimport java.util.List;
5b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot
6b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabotimport org.junit.ClassRule;
7b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabotimport org.junit.Rule;
8b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabotimport org.junit.rules.TestRule;
9b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabotimport org.junit.runners.model.FrameworkField;
10b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabotimport org.junit.runners.model.TestClass;
11b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot
12b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot/**
13b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * A RuleFieldValidator validates the rule fields of a
14b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * {@link org.junit.runners.model.TestClass}. All reasons for rejecting the
15b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * {@code TestClass} are written to a list of errors.
16b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot *
17b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * There are two slightly different validators. The {@link #CLASS_RULE_VALIDATOR}
18b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * validates fields with a {@link ClassRule} annotation and the
19b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * {@link #RULE_VALIDATOR} validates fields with a {@link Rule} annotation.
20b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot */
21b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabotpublic enum RuleFieldValidator {
22b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	/**
23b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	 * Validates fields with a {@link ClassRule} annotation.
24b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	 */
25b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	CLASS_RULE_VALIDATOR(ClassRule.class, true),
26b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	/**
27b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	 * Validates fields with a {@link Rule} annotation.
28b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	 */
29b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	RULE_VALIDATOR(Rule.class, false);
30b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot
31b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	private final Class<? extends Annotation> fAnnotation;
32b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot
33b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	private final boolean fOnlyStaticFields;
34b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot
35b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	private RuleFieldValidator(Class<? extends Annotation> annotation,
36b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot			boolean onlyStaticFields) {
37b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		this.fAnnotation= annotation;
38b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		this.fOnlyStaticFields= onlyStaticFields;
39b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	}
40b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot
41b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	/**
42b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	 * Validate the {@link org.junit.runners.model.TestClass} and adds reasons
43b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	 * for rejecting the class to a list of errors.
44b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	 * @param target the {@code TestClass} to validate.
45b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	 * @param errors the list of errors.
46b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	 */
47b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	public void validate(TestClass target, List<Throwable> errors) {
48b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		List<FrameworkField> fields= target.getAnnotatedFields(fAnnotation);
49b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		for (FrameworkField each : fields)
50b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot			validateField(each, errors);
51b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	}
52b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot
53b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	private void validateField(FrameworkField field, List<Throwable> errors) {
54b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		optionallyValidateStatic(field, errors);
55b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		validatePublic(field, errors);
56b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		validateTestRuleOrMethodRule(field, errors);
57b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	}
58b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot
59b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	private void optionallyValidateStatic(FrameworkField field,
60b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot			List<Throwable> errors) {
61b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		if (fOnlyStaticFields && !field.isStatic())
62b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot			addError(errors, field, "must be static.");
63b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	}
64b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot
65b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	private void validatePublic(FrameworkField field, List<Throwable> errors) {
66b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		if (!field.isPublic())
67b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot			addError(errors, field, "must be public.");
68b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	}
69b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot
70b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	private void validateTestRuleOrMethodRule(FrameworkField field,
71b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot			List<Throwable> errors) {
72b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		if (!isMethodRule(field) && !isTestRule(field))
73b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot			addError(errors, field, "must implement MethodRule or TestRule.");
74b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	}
75b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot
76b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	private boolean isTestRule(FrameworkField target) {
77b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		return TestRule.class.isAssignableFrom(target.getType());
78b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	}
79b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot
80b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	@SuppressWarnings("deprecation")
81b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	private boolean isMethodRule(FrameworkField target) {
82b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		return org.junit.rules.MethodRule.class.isAssignableFrom(target
83b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot				.getType());
84b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	}
85b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot
86b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	private void addError(List<Throwable> errors, FrameworkField field,
87b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot			String suffix) {
88b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		String message= "The @" + fAnnotation.getSimpleName() + " '"
89b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot				+ field.getName() + "' " + suffix;
90b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		errors.add(new Exception(message));
91b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	}
92b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot}
93