Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||||||
PatternValidator |
|
| 1.8125;1.812 |
1 | // Copyright 2004, 2005 The Apache Software Foundation |
|
2 | // |
|
3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
|
4 | // you may not use this file except in compliance with the License. |
|
5 | // You may obtain a copy of the License at |
|
6 | // |
|
7 | // http://www.apache.org/licenses/LICENSE-2.0 |
|
8 | // |
|
9 | // Unless required by applicable law or agreed to in writing, software |
|
10 | // distributed under the License is distributed on an "AS IS" BASIS, |
|
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
12 | // See the License for the specific language governing permissions and |
|
13 | // limitations under the License. |
|
14 | ||
15 | package org.apache.tapestry.valid; |
|
16 | ||
17 | import java.util.HashMap; |
|
18 | import java.util.Map; |
|
19 | ||
20 | import org.apache.hivemind.ApplicationRuntimeException; |
|
21 | import org.apache.tapestry.IMarkupWriter; |
|
22 | import org.apache.tapestry.IRequestCycle; |
|
23 | import org.apache.tapestry.Tapestry; |
|
24 | import org.apache.tapestry.form.IFormComponent; |
|
25 | import org.apache.tapestry.util.RegexpMatcher; |
|
26 | ||
27 | /** |
|
28 | * <p>The validator bean that provides a pattern validation service. |
|
29 | * |
|
30 | * <p>The actual pattern matching algorithm is provided by the |
|
31 | * {@link org.apache.tapestry.valid.PatternDelegate}. This enables the user to provide |
|
32 | * custom pattern matching implementations. In the event a custom implementation is not |
|
33 | * provided, this validator will use the {@link org.apache.tapestry.util.RegexpMatcher}. |
|
34 | * |
|
35 | * <p>This validator has the ability to provide client side validation on demand. |
|
36 | * To enable client side validation simply set the <code>clientScriptingEnabled</code> |
|
37 | * property to <code>true</code>. |
|
38 | * The default implementation of the script will be in JavaScript and allows the user to |
|
39 | * override this with a custom implementation by setting the path to the custom |
|
40 | * script via {@link #setScriptPath(String)}. |
|
41 | * |
|
42 | * @author Harish Krishnaswamy |
|
43 | * @since 3.0 |
|
44 | */ |
|
45 | 1 | public class PatternValidator extends BaseValidator |
46 | { |
|
47 | /** |
|
48 | * The pattern that this validator will use to validate the input. The default |
|
49 | * pattern is an empty string. |
|
50 | */ |
|
51 | 1 | private String _patternString = ""; |
52 | ||
53 | /** |
|
54 | * A custom message in the event of a validation failure. |
|
55 | */ |
|
56 | private String _patternNotMatchedMessage; |
|
57 | ||
58 | /** |
|
59 | * The object that handles pattern matching. |
|
60 | */ |
|
61 | private PatternDelegate _patternDelegate; |
|
62 | ||
63 | /** |
|
64 | * The location of the script specification for client side validation. |
|
65 | */ |
|
66 | 1 | private String _scriptPath = "/org/apache/tapestry/valid/PatternValidator.script"; |
67 | ||
68 | /** |
|
69 | * Returns custom validation failure message. The default message comes from |
|
70 | * <code>ValidationStrings.properties</code> file for key |
|
71 | * <code>pattern-not-matched</code>. |
|
72 | */ |
|
73 | public String getPatternNotMatchedMessage() |
|
74 | { |
|
75 | 0 | return _patternNotMatchedMessage; |
76 | } |
|
77 | ||
78 | /** |
|
79 | * Returns the pattern that this validator uses for validation. |
|
80 | */ |
|
81 | public String getPatternString() |
|
82 | { |
|
83 | 5 | return _patternString; |
84 | } |
|
85 | ||
86 | /** |
|
87 | * Allows for a custom message to be set typically via the bean specification. |
|
88 | */ |
|
89 | public void setPatternNotMatchedMessage(String message) |
|
90 | { |
|
91 | 7 | _patternNotMatchedMessage = message; |
92 | 7 | } |
93 | ||
94 | /** |
|
95 | * Allows the user to change the validation pattern. |
|
96 | */ |
|
97 | public void setPatternString(String pattern) |
|
98 | { |
|
99 | 14 | _patternString = pattern; |
100 | 14 | } |
101 | ||
102 | /** |
|
103 | * Static inner class that acts as a delegate to RegexpMatcher and conforms to the |
|
104 | * PatternDelegate contract. |
|
105 | */ |
|
106 | 10 | private static class RegExpDelegate implements PatternDelegate |
107 | { |
|
108 | private RegexpMatcher _matcher; |
|
109 | ||
110 | private RegexpMatcher getPatternMatcher() |
|
111 | { |
|
112 | 9 | if (_matcher == null) |
113 | 5 | _matcher = new RegexpMatcher(); |
114 | ||
115 | 9 | return _matcher; |
116 | } |
|
117 | ||
118 | public boolean contains(String patternString, String input) |
|
119 | { |
|
120 | 8 | return getPatternMatcher().contains(patternString, input); |
121 | } |
|
122 | ||
123 | public String getEscapedPatternString(String patternString) |
|
124 | { |
|
125 | 1 | return getPatternMatcher().getEscapedPatternString(patternString); |
126 | } |
|
127 | } |
|
128 | ||
129 | /** |
|
130 | * Allows for a custom implementation to do the pattern matching. The default pattern |
|
131 | * matching is done with {@link org.apache.tapestry.util.RegexpMatcher}. |
|
132 | */ |
|
133 | public void setPatternDelegate(PatternDelegate patternDelegate) |
|
134 | { |
|
135 | 7 | _patternDelegate = patternDelegate; |
136 | 7 | } |
137 | ||
138 | /** |
|
139 | * Returns the custom pattern matcher if one is provided or creates and returns the |
|
140 | * default matcher laziliy. |
|
141 | */ |
|
142 | public PatternDelegate getPatternDelegate() |
|
143 | { |
|
144 | 11 | if (_patternDelegate == null) |
145 | 5 | _patternDelegate = new RegExpDelegate(); |
146 | ||
147 | 11 | return _patternDelegate; |
148 | } |
|
149 | ||
150 | /** |
|
151 | * @see org.apache.tapestry.valid.IValidator#toString(org.apache.tapestry.form.IFormComponent, java.lang.Object) |
|
152 | */ |
|
153 | public String toString(IFormComponent field, Object value) |
|
154 | { |
|
155 | 0 | if (value == null) |
156 | 0 | return null; |
157 | ||
158 | 0 | return value.toString(); |
159 | } |
|
160 | ||
161 | private String buildPatternNotMatchedMessage(IFormComponent field, String patternString) |
|
162 | { |
|
163 | 5 | String templateMessage = |
164 | getPattern( |
|
165 | _patternNotMatchedMessage, |
|
166 | "pattern-not-matched", |
|
167 | field.getPage().getLocale()); |
|
168 | ||
169 | 5 | return formatString(templateMessage, field.getDisplayName(), patternString); |
170 | } |
|
171 | ||
172 | /** |
|
173 | * @see org.apache.tapestry.valid.IValidator#toObject(org.apache.tapestry.form.IFormComponent, java.lang.String) |
|
174 | */ |
|
175 | public Object toObject(IFormComponent field, String input) throws ValidatorException |
|
176 | { |
|
177 | 9 | if (checkRequired(field, input)) |
178 | 0 | return null; |
179 | ||
180 | 9 | boolean matched = false; |
181 | ||
182 | try |
|
183 | { |
|
184 | 9 | matched = getPatternDelegate().contains(_patternString, input); |
185 | } |
|
186 | 1 | catch (Throwable t) |
187 | { |
|
188 | 1 | throw new ApplicationRuntimeException( |
189 | Tapestry.format( |
|
190 | "PatternValidator.pattern-match-error", |
|
191 | _patternString, |
|
192 | field.getDisplayName()), |
|
193 | field, |
|
194 | field.getLocation(), |
|
195 | t); |
|
196 | 8 | } |
197 | ||
198 | 8 | if (!matched) |
199 | 5 | throw new ValidatorException( |
200 | buildPatternNotMatchedMessage(field, _patternString), |
|
201 | ValidationConstraint.PATTERN_MISMATCH); |
|
202 | ||
203 | 3 | return input; |
204 | } |
|
205 | ||
206 | /** |
|
207 | * Allows for a custom implementation of the client side validation. |
|
208 | */ |
|
209 | public void setScriptPath(String scriptPath) |
|
210 | { |
|
211 | 0 | _scriptPath = scriptPath; |
212 | 0 | } |
213 | ||
214 | /** |
|
215 | * @see org.apache.tapestry.valid.IValidator#renderValidatorContribution(org.apache.tapestry.form.IFormComponent, org.apache.tapestry.IMarkupWriter, org.apache.tapestry.IRequestCycle) |
|
216 | */ |
|
217 | public void renderValidatorContribution( |
|
218 | IFormComponent field, |
|
219 | IMarkupWriter writer, |
|
220 | IRequestCycle cycle) |
|
221 | { |
|
222 | 0 | if (!isClientScriptingEnabled()) |
223 | 0 | return; |
224 | ||
225 | 0 | Map symbols = new HashMap(); |
226 | ||
227 | 0 | if (isRequired()) |
228 | 0 | symbols.put("requiredMessage", buildRequiredMessage(field)); |
229 | ||
230 | 0 | symbols.put( |
231 | "patternNotMatchedMessage", |
|
232 | buildPatternNotMatchedMessage(field, getEscapedPatternString())); |
|
233 | ||
234 | 0 | processValidatorScript(_scriptPath, cycle, field, symbols); |
235 | 0 | } |
236 | ||
237 | /** |
|
238 | * Returns the escaped sequence of the pattern string for rendering in the error message. |
|
239 | */ |
|
240 | public String getEscapedPatternString() |
|
241 | { |
|
242 | 2 | return getPatternDelegate().getEscapedPatternString(_patternString); |
243 | } |
|
244 | ||
245 | public String toString() |
|
246 | { |
|
247 | 0 | return "Pattern: " |
248 | + _patternString |
|
249 | + "; Script Path: " |
|
250 | + _scriptPath |
|
251 | + "; Pattern Delegate: " |
|
252 | + _patternDelegate; |
|
253 | } |
|
254 | } |