Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
PatternValidator |
|
| 1.8125;1.812 | ||||
PatternValidator$1 |
|
| 1.8125;1.812 | ||||
PatternValidator$RegExpDelegate |
|
| 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 | 0 | 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 | 0 | 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 | 0 | 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 | 0 | 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 | 0 | _patternNotMatchedMessage = message; |
92 | 0 | } |
93 | ||
94 | /** | |
95 | * Allows the user to change the validation pattern. | |
96 | */ | |
97 | public void setPatternString(String pattern) | |
98 | { | |
99 | 0 | _patternString = pattern; |
100 | 0 | } |
101 | ||
102 | /** | |
103 | * Static inner class that acts as a delegate to RegexpMatcher and conforms to the | |
104 | * PatternDelegate contract. | |
105 | */ | |
106 | 0 | private static class RegExpDelegate implements PatternDelegate |
107 | { | |
108 | private RegexpMatcher _matcher; | |
109 | ||
110 | private RegexpMatcher getPatternMatcher() | |
111 | { | |
112 | 0 | if (_matcher == null) |
113 | 0 | _matcher = new RegexpMatcher(); |
114 | ||
115 | 0 | return _matcher; |
116 | } | |
117 | ||
118 | public boolean contains(String patternString, String input) | |
119 | { | |
120 | 0 | return getPatternMatcher().contains(patternString, input); |
121 | } | |
122 | ||
123 | public String getEscapedPatternString(String patternString) | |
124 | { | |
125 | 0 | 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 | 0 | _patternDelegate = patternDelegate; |
136 | 0 | } |
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 | 0 | if (_patternDelegate == null) |
145 | 0 | _patternDelegate = new RegExpDelegate(); |
146 | ||
147 | 0 | 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 | 0 | String templateMessage = |
164 | getPattern( | |
165 | _patternNotMatchedMessage, | |
166 | "pattern-not-matched", | |
167 | field.getPage().getLocale()); | |
168 | ||
169 | 0 | 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 | 0 | if (checkRequired(field, input)) |
178 | 0 | return null; |
179 | ||
180 | 0 | boolean matched = false; |
181 | ||
182 | try | |
183 | { | |
184 | 0 | matched = getPatternDelegate().contains(_patternString, input); |
185 | } | |
186 | 0 | catch (Throwable t) |
187 | { | |
188 | 0 | throw new ApplicationRuntimeException( |
189 | Tapestry.format( | |
190 | "PatternValidator.pattern-match-error", | |
191 | _patternString, | |
192 | field.getDisplayName()), | |
193 | field, | |
194 | field.getLocation(), | |
195 | t); | |
196 | 0 | } |
197 | ||
198 | 0 | if (!matched) |
199 | 0 | throw new ValidatorException( |
200 | buildPatternNotMatchedMessage(field, _patternString), | |
201 | ValidationConstraint.PATTERN_MISMATCH); | |
202 | ||
203 | 0 | 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 | 0 | 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 | } |