1 package com.atlassian.plugin.util.validation;
2
3 import org.dom4j.Node;
4
5 import java.util.ArrayList;
6 import java.util.List;
7
8 import static com.google.common.base.Preconditions.checkNotNull;
9
10
11
12
13
14
15
16 public class ValidationPattern {
17 private final List<Rule> rules = new ArrayList<>();
18
19 private ValidationPattern() {
20 }
21
22
23
24
25 public static ValidationPattern createPattern() {
26 return new ValidationPattern();
27 }
28
29
30
31
32
33
34
35
36 public ValidationPattern rule(String context, RuleTest... tests) {
37 rules.add(new Rule(context, tests));
38 return this;
39 }
40
41
42
43
44
45
46
47 public ValidationPattern rule(RuleTest... tests) {
48 rules.add(new Rule(".", tests));
49 return this;
50 }
51
52
53
54
55
56
57
58
59 public void evaluate(Node node) throws ValidationException {
60 List<String> errors = new ArrayList<>();
61 for (Rule rule : rules) {
62 rule.evaluate(node, errors);
63 }
64 if (!errors.isEmpty()) {
65 if (errors.size() == 1) {
66 throw new ValidationException(errors.get(0), errors);
67 } else {
68 StringBuilder sb = new StringBuilder();
69 sb.append("There were validation errors:\n");
70 for (String msg : errors) {
71 sb.append("\t- ").append(msg).append("\n");
72 }
73 throw new ValidationException(sb.toString(), errors);
74 }
75 }
76 }
77
78
79
80
81
82
83
84 public static RuleTest test(String xpath) {
85 return new RuleTest(xpath);
86 }
87
88
89
90
91 public static class RuleTest {
92 private final String xpath;
93 private String errorMessage;
94
95 private RuleTest(String xpath) {
96 this.xpath = checkNotNull(xpath);
97 }
98
99
100
101
102
103
104
105 public RuleTest withError(String msg) {
106 this.errorMessage = msg;
107 return this;
108 }
109
110 private void evaluate(Node ctxNode, List<String> errors) {
111 Object obj = ctxNode.selectObject(xpath);
112 if (obj == null) {
113 errors.add(errorMessage + ": " + ctxNode.asXML());
114 } else if (obj instanceof Boolean && !((Boolean) obj)) {
115 errors.add(errorMessage + ": " + ctxNode.asXML());
116 } else if (obj instanceof List && ((List<?>) obj).isEmpty()) {
117 errors.add(errorMessage + ": " + ctxNode.asXML());
118 }
119 }
120 }
121
122
123
124
125 public static class Rule {
126 private final String contextPattern;
127 private final RuleTest[] tests;
128
129 private Rule(String contextPattern, RuleTest[] tests) {
130 this.contextPattern = checkNotNull(contextPattern);
131 this.tests = checkNotNull(tests);
132 }
133
134 private void evaluate(Node e, List<String> errors) {
135 @SuppressWarnings("unchecked")
136 List<Node> contexts = e.selectNodes(contextPattern);
137
138 if (contexts != null && contexts.size() > 0) {
139 for (Node ctxNode : contexts) {
140 for (RuleTest test : tests) {
141 test.evaluate(ctxNode, errors);
142 }
143 }
144 }
145 }
146 }
147
148 }