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