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