|
|||||||||||||||||||
30 day Evaluation License registered to hlship@comcast.net Your 30 day evaluation period has expired. Please visit http://www.cenqua.com to obtain a licensed version of Clover | |||||||||||||||||||
Source file | Conditionals | Statements | Methods | TOTAL | |||||||||||||||
BaseValidator.java | 66.7% | 53.1% | 64.7% | 58.2% |
|
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.text.MessageFormat; | |
18 | import java.util.HashMap; | |
19 | import java.util.Locale; | |
20 | import java.util.Map; | |
21 | import java.util.ResourceBundle; | |
22 | ||
23 | import org.apache.hivemind.ApplicationRuntimeException; | |
24 | import org.apache.hivemind.HiveMind; | |
25 | import org.apache.hivemind.Resource; | |
26 | import org.apache.hivemind.util.ClasspathResource; | |
27 | import org.apache.hivemind.util.PropertyUtils; | |
28 | import org.apache.tapestry.IEngine; | |
29 | import org.apache.tapestry.IForm; | |
30 | import org.apache.tapestry.IMarkupWriter; | |
31 | import org.apache.tapestry.IRequestCycle; | |
32 | import org.apache.tapestry.IScript; | |
33 | import org.apache.tapestry.PageRenderSupport; | |
34 | import org.apache.tapestry.TapestryUtils; | |
35 | import org.apache.tapestry.engine.IScriptSource; | |
36 | import org.apache.tapestry.form.FormEventType; | |
37 | import org.apache.tapestry.form.IFormComponent; | |
38 | import org.apache.tapestry.html.Body; | |
39 | ||
40 | /** | |
41 | * Abstract base class for {@link IValidator}. Supports a required and locale property. | |
42 | * | |
43 | * @author Howard Lewis Ship | |
44 | * @since 1.0.8 | |
45 | */ | |
46 | ||
47 | public abstract class BaseValidator implements IValidator | |
48 | { | |
49 | /** | |
50 | * Input Symbol used to represent the field being validated. | |
51 | * | |
52 | * @see #processValidatorScript(String, IRequestCycle, IFormComponent, Map) | |
53 | * @since 2.2 | |
54 | */ | |
55 | ||
56 | public static final String FIELD_SYMBOL = "field"; | |
57 | ||
58 | /** | |
59 | * Input symbol used to represent the validator itself to the script. | |
60 | * | |
61 | * @see #processValidatorScript(String, IRequestCycle, IFormComponent, Map) | |
62 | * @since 2.2 | |
63 | */ | |
64 | ||
65 | public static final String VALIDATOR_SYMBOL = "validator"; | |
66 | ||
67 | /** | |
68 | * Input symbol used to represent the {@link IForm}containing the field to the script. | |
69 | * | |
70 | * @see #processValidatorScript(String, IRequestCycle, IFormComponent, Map) | |
71 | * @since 2.2 | |
72 | */ | |
73 | ||
74 | public static final String FORM_SYMBOL = "form"; | |
75 | ||
76 | /** | |
77 | * Output symbol set by the script asthe name of the validator JavaScript function. The function | |
78 | * implemented must return true or false (true if the field is valid, false otherwise). After | |
79 | * the script is executed, the function is added to the {@link IForm}as a | |
80 | * {@link org.apache.tapestry.form.FormEventType#SUBMIT}. | |
81 | * | |
82 | * @see #processValidatorScript(String, IRequestCycle, IFormComponent, Map) | |
83 | * @since 2.2 | |
84 | */ | |
85 | ||
86 | public static final String FUNCTION_SYMBOL = "function"; | |
87 | ||
88 | private boolean _required; | |
89 | ||
90 | /** @since 3.0 */ | |
91 | ||
92 | private String _requiredMessage; | |
93 | ||
94 | /** | |
95 | * @since 2.2 | |
96 | */ | |
97 | ||
98 | private boolean _clientScriptingEnabled = false; | |
99 | ||
100 | /** | |
101 | * Standard constructor. Leaves locale as system default and required as false. | |
102 | */ | |
103 | ||
104 | 71 | public BaseValidator() |
105 | { | |
106 | } | |
107 | ||
108 | /** | |
109 | * Allow the validator to be initialized with a property initialization string. | |
110 | * | |
111 | * @since 4.0 | |
112 | */ | |
113 | 7 | public BaseValidator(String initializer) |
114 | { | |
115 | 7 | PropertyUtils.configureProperties(this, initializer); |
116 | } | |
117 | ||
118 | 0 | protected BaseValidator(boolean required) |
119 | { | |
120 | 0 | _required = required; |
121 | } | |
122 | ||
123 | 5 | public boolean isRequired() |
124 | { | |
125 | 5 | return _required; |
126 | } | |
127 | ||
128 | 4 | public void setRequired(boolean required) |
129 | { | |
130 | 4 | _required = required; |
131 | } | |
132 | ||
133 | /** | |
134 | * Gets a pattern, either as the default value, or as a localized key. If override is null, then | |
135 | * the key from the <code>org.apache.tapestry.valid.ValidationStrings</code> | |
136 | * {@link ResourceBundle}(in the specified locale) is used. The pattern can then be used with | |
137 | * {@link #formatString(String, Object[])}. | |
138 | * <p> | |
139 | * Why do we not just lump these strings into TapestryStrings.properties? because | |
140 | * TapestryStrings.properties is localized to the server's locale, which is fine for the | |
141 | * logging, debugging and error messages it contains. For field validation, whose errors are | |
142 | * visible to the end user normally, we want to localize to the page's locale. | |
143 | * | |
144 | * @param override | |
145 | * The override value for the localized string from the bundle. | |
146 | * @param key | |
147 | * used to lookup pattern from bundle, if override is null. | |
148 | * @param locale | |
149 | * used to get right localization of bundle. | |
150 | * @since 3.0 | |
151 | */ | |
152 | ||
153 | 36 | protected String getPattern(String override, String key, Locale locale) |
154 | { | |
155 | 36 | if (override != null) |
156 | 10 | return override; |
157 | ||
158 | 26 | ResourceBundle strings = ResourceBundle.getBundle( |
159 | "org.apache.tapestry.valid.ValidationStrings", | |
160 | locale); | |
161 | ||
162 | 26 | return strings.getString(key); |
163 | } | |
164 | ||
165 | /** | |
166 | * Gets a string from the standard resource bundle. The string in the bundle is treated as a | |
167 | * pattern for {@link MessageFormat#format(java.lang.String, java.lang.Object[])}. | |
168 | * | |
169 | * @param pattern | |
170 | * string the input pattern to be used with | |
171 | * {@link MessageFormat#format(java.lang.String, java.lang.Object[])}. It may | |
172 | * contain replaceable parameters, {0}, {1}, etc. | |
173 | * @param args | |
174 | * the arguments used to fill replaceable parameters {0}, {1}, etc. | |
175 | * @since 3.0 | |
176 | */ | |
177 | ||
178 | 41 | protected String formatString(String pattern, Object[] args) |
179 | { | |
180 | 41 | return MessageFormat.format(pattern, args); |
181 | } | |
182 | ||
183 | /** | |
184 | * Convienience method for invoking {@link #formatString(String, Object[])}. | |
185 | * | |
186 | * @since 3.0 | |
187 | */ | |
188 | ||
189 | 16 | protected String formatString(String pattern, Object arg) |
190 | { | |
191 | 16 | return formatString(pattern, new Object[] |
192 | { arg }); | |
193 | } | |
194 | ||
195 | /** | |
196 | * Convienience method for invoking {@link #formatString(String, Object[])}. | |
197 | * | |
198 | * @since 3.0 | |
199 | */ | |
200 | ||
201 | 24 | protected String formatString(String pattern, Object arg1, Object arg2) |
202 | { | |
203 | 24 | return formatString(pattern, new Object[] |
204 | { arg1, arg2 }); | |
205 | } | |
206 | ||
207 | /** | |
208 | * Invoked to check if the value is null. If the value is null (or empty), but the required flag | |
209 | * is set, then this method throws a {@link ValidatorException}. Otherwise, returns true if the | |
210 | * value is null. | |
211 | */ | |
212 | ||
213 | 58 | protected boolean checkRequired(IFormComponent field, String value) throws ValidatorException |
214 | { | |
215 | 58 | boolean isEmpty = HiveMind.isBlank(value); |
216 | ||
217 | 58 | if (_required && isEmpty) |
218 | 2 | throw new ValidatorException(buildRequiredMessage(field), ValidationConstraint.REQUIRED); |
219 | ||
220 | 56 | return isEmpty; |
221 | } | |
222 | ||
223 | /** | |
224 | * Builds an error message indicating a value for a required field was not supplied. | |
225 | * | |
226 | * @since 3.0 | |
227 | */ | |
228 | ||
229 | 3 | protected String buildRequiredMessage(IFormComponent field) |
230 | { | |
231 | 3 | String pattern = getPattern(_requiredMessage, "field-is-required", field.getPage() |
232 | .getLocale()); | |
233 | ||
234 | 3 | return formatString(pattern, field.getDisplayName()); |
235 | } | |
236 | ||
237 | /** | |
238 | * This implementation does nothing. Subclasses may supply their own implementation. | |
239 | * | |
240 | * @since 2.2 | |
241 | */ | |
242 | ||
243 | 0 | public void renderValidatorContribution(IFormComponent field, IMarkupWriter writer, |
244 | IRequestCycle cycle) | |
245 | { | |
246 | } | |
247 | ||
248 | /** | |
249 | * Invoked (from sub-class implementations of | |
250 | * {@link #renderValidatorContribution(IFormComponent, IMarkupWriter, IRequestCycle)}to process | |
251 | * a standard validation script. This expects that: | |
252 | * <ul> | |
253 | * <li>The {@link IFormComponent}is (ultimately) wrapped by a {@link Body} | |
254 | * <li>The script generates a symbol named "function" (as per {@link #FUNCTION_SYMBOL}) | |
255 | * </ul> | |
256 | * | |
257 | * @param scriptPath | |
258 | * the resource path of the script to execute | |
259 | * @param cycle | |
260 | * The active request cycle | |
261 | * @param field | |
262 | * The field to be validated | |
263 | * @param symbols | |
264 | * a set of input symbols needed by the script. These symbols are augmented with | |
265 | * symbols for the field, form and validator. symbols may be null, but will be | |
266 | * modified if not null. | |
267 | * @throws ApplicationRuntimeException | |
268 | * if there's an error processing the script. | |
269 | * @since 2.2 | |
270 | */ | |
271 | ||
272 | 0 | protected void processValidatorScript(String scriptPath, IRequestCycle cycle, |
273 | IFormComponent field, Map symbols) | |
274 | { | |
275 | 0 | IEngine engine = field.getPage().getEngine(); |
276 | 0 | IScriptSource source = engine.getScriptSource(); |
277 | 0 | IForm form = field.getForm(); |
278 | ||
279 | 0 | Map finalSymbols = (symbols == null) ? new HashMap() : symbols; |
280 | ||
281 | 0 | finalSymbols.put(FIELD_SYMBOL, field); |
282 | 0 | finalSymbols.put(FORM_SYMBOL, form); |
283 | 0 | finalSymbols.put(VALIDATOR_SYMBOL, this); |
284 | ||
285 | 0 | Resource location = new ClasspathResource(engine.getClassResolver(), scriptPath); |
286 | ||
287 | 0 | IScript script = source.getScript(location); |
288 | ||
289 | // If there's an error, report it against the field (this validator object doesn't | |
290 | // have a location). | |
291 | ||
292 | 0 | PageRenderSupport pageRenderSupport = TapestryUtils.getPageRenderSupport(cycle, field); |
293 | ||
294 | 0 | script.execute(cycle, pageRenderSupport, finalSymbols); |
295 | } | |
296 | ||
297 | /** | |
298 | * Returns true if client scripting is enabled. Some validators are capable of generating | |
299 | * client-side scripting to perform validation when the form is submitted. By default, this flag | |
300 | * is false and subclasses should check it (in | |
301 | * {@link #renderValidatorContribution(IFormComponent, IMarkupWriter, IRequestCycle)}) before | |
302 | * generating client side script. | |
303 | * | |
304 | * @since 2.2 | |
305 | */ | |
306 | ||
307 | 0 | public boolean isClientScriptingEnabled() |
308 | { | |
309 | 0 | return _clientScriptingEnabled; |
310 | } | |
311 | ||
312 | 0 | public void setClientScriptingEnabled(boolean clientScriptingEnabled) |
313 | { | |
314 | 0 | _clientScriptingEnabled = clientScriptingEnabled; |
315 | } | |
316 | ||
317 | 0 | public String getRequiredMessage() |
318 | { | |
319 | 0 | return _requiredMessage; |
320 | } | |
321 | ||
322 | /** | |
323 | * Overrides the <code>field-is-required</code> bundle key. Parameter {0} is the display name | |
324 | * of the field. | |
325 | * | |
326 | * @since 3.0 | |
327 | */ | |
328 | ||
329 | 1 | public void setRequiredMessage(String string) |
330 | { | |
331 | 1 | _requiredMessage = string; |
332 | } | |
333 | ||
334 | } |
|