%line | %branch | |||||||||
---|---|---|---|---|---|---|---|---|---|---|
org.apache.commons.validator.routines.AbstractCalendarValidator |
|
|
1 | /* |
|
2 | * $Id: AbstractCalendarValidator.java 386637 2006-03-17 13:22:26Z niallp $ |
|
3 | * $Revision: 386637 $ |
|
4 | * $Date: 2006-03-17 13:22:26 +0000 (Fri, 17 Mar 2006) $ |
|
5 | * |
|
6 | * ==================================================================== |
|
7 | * Copyright 2006 The Apache Software Foundation |
|
8 | * |
|
9 | * Licensed under the Apache License, Version 2.0 (the "License"); |
|
10 | * you may not use this file except in compliance with the License. |
|
11 | * You may obtain a copy of the License at |
|
12 | * |
|
13 | * http://www.apache.org/licenses/LICENSE-2.0 |
|
14 | * |
|
15 | * Unless required by applicable law or agreed to in writing, software |
|
16 | * distributed under the License is distributed on an "AS IS" BASIS, |
|
17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
18 | * See the License for the specific language governing permissions and |
|
19 | * limitations under the License. |
|
20 | */ |
|
21 | package org.apache.commons.validator.routines; |
|
22 | ||
23 | import java.text.DateFormatSymbols; |
|
24 | import java.text.Format; |
|
25 | import java.text.DateFormat; |
|
26 | import java.text.SimpleDateFormat; |
|
27 | import java.util.Calendar; |
|
28 | import java.util.Locale; |
|
29 | import java.util.TimeZone; |
|
30 | ||
31 | /** |
|
32 | * <p>Abstract class for Date/Time/Calendar validation.</p> |
|
33 | * |
|
34 | * <p>This is a <i>base</i> class for building Date / Time |
|
35 | * Validators using format parsing.</p> |
|
36 | * |
|
37 | * @version $Revision: 386637 $ $Date: 2006-03-17 13:22:26 +0000 (Fri, 17 Mar 2006) $ |
|
38 | * @since Validator 1.3.0 |
|
39 | */ |
|
40 | public abstract class AbstractCalendarValidator extends AbstractFormatValidator { |
|
41 | ||
42 | 27 | private int dateStyle = -1; |
43 | ||
44 | 27 | private int timeStyle = -1; |
45 | ||
46 | /** |
|
47 | * Construct an instance with the specified <i>strict</i>, |
|
48 | * <i>time</i> and <i>date</i> style parameters. |
|
49 | * |
|
50 | * @param strict <code>true</code> if strict |
|
51 | * <code>Format</code> parsing should be used. |
|
52 | * @param dateStyle the date style to use for Locale validation. |
|
53 | * @param timeStyle the time style to use for Locale validation. |
|
54 | */ |
|
55 | public AbstractCalendarValidator(boolean strict, int dateStyle, class="keyword">int timeStyle) { |
|
56 | 27 | super(strict); |
57 | 27 | this.dateStyle = dateStyle; |
58 | 27 | this.timeStyle = timeStyle; |
59 | 27 | } |
60 | ||
61 | /** |
|
62 | * <p>Validate using the specified <code>Locale</code>. |
|
63 | * |
|
64 | * @param value The value validation is being performed on. |
|
65 | * @param pattern The pattern used to format the value. |
|
66 | * @param locale The locale to use for the Format, defaults to the default |
|
67 | * @return <code>true</code> if the value is valid. |
|
68 | */ |
|
69 | public boolean isValid(String value, String pattern, Locale locale) { |
|
70 | 134 | Object parsedValue = parse(value, pattern, locale, (TimeZone)null); |
71 | 134 | return (parsedValue == null ? false : true); |
72 | } |
|
73 | ||
74 | /** |
|
75 | * <p>Format an object into a <code>String</code> using |
|
76 | * the default Locale.</p> |
|
77 | * |
|
78 | * @param value The value validation is being performed on. |
|
79 | * @param timeZone The Time Zone used to format the date, |
|
80 | * system default if null (unless value is a <code>Calendar</code>. |
|
81 | * @return The value formatted as a <code>String</code>. |
|
82 | */ |
|
83 | public String format(Object value, TimeZone timeZone) { |
|
84 | 1 | return format(value, (String)null, (Locale)class="keyword">null, timeZone); |
85 | } |
|
86 | ||
87 | /** |
|
88 | * <p>Format an object into a <code>String</code> using |
|
89 | * the specified pattern.</p> |
|
90 | * |
|
91 | * @param value The value validation is being performed on. |
|
92 | * @param pattern The pattern used to format the value. |
|
93 | * @param timeZone The Time Zone used to format the date, |
|
94 | * system default if null (unless value is a <code>Calendar</code>. |
|
95 | * @return The value formatted as a <code>String</code>. |
|
96 | */ |
|
97 | public String format(Object value, String pattern, TimeZone timeZone) { |
|
98 | 2 | return format(value, pattern, (Locale)null, timeZone); |
99 | } |
|
100 | ||
101 | /** |
|
102 | * <p>Format an object into a <code>String</code> using |
|
103 | * the specified Locale.</p> |
|
104 | * |
|
105 | * @param value The value validation is being performed on. |
|
106 | * @param locale The locale to use for the Format. |
|
107 | * @param timeZone The Time Zone used to format the date, |
|
108 | * system default if null (unless value is a <code>Calendar</code>. |
|
109 | * @return The value formatted as a <code>String</code>. |
|
110 | */ |
|
111 | public String format(Object value, Locale locale, TimeZone timeZone) { |
|
112 | 1 | return format(value, (String)null, locale, timeZone); |
113 | } |
|
114 | ||
115 | /** |
|
116 | * <p>Format an object using the specified pattern and/or |
|
117 | * <code>Locale</code>. |
|
118 | * |
|
119 | * @param value The value validation is being performed on. |
|
120 | * @param pattern The pattern used to format the value. |
|
121 | * @param locale The locale to use for the Format. |
|
122 | * @return The value formatted as a <code>String</code>. |
|
123 | */ |
|
124 | public String format(Object value, String pattern, Locale locale) { |
|
125 | 11 | return format(value, pattern, locale, (TimeZone)null); |
126 | } |
|
127 | ||
128 | /** |
|
129 | * <p>Format an object using the specified pattern and/or |
|
130 | * <code>Locale</code>. |
|
131 | * |
|
132 | * @param value The value validation is being performed on. |
|
133 | * @param pattern The pattern used to format the value. |
|
134 | * @param locale The locale to use for the Format. |
|
135 | * @param timeZone The Time Zone used to format the date, |
|
136 | * system default if null (unless value is a <code>Calendar</code>. |
|
137 | * @return The value formatted as a <code>String</code>. |
|
138 | */ |
|
139 | public String format(Object value, String pattern, Locale locale, TimeZone timeZone) { |
|
140 | 16 | DateFormat formatter = (DateFormat)getFormat(pattern, locale); |
141 | 16 | if (timeZone != null) { |
142 | 5 | formatter.setTimeZone(timeZone); |
143 | 11 | } else if (value instanceof Calendar) { |
144 | 8 | formatter.setTimeZone(((Calendar)value).getTimeZone()); |
145 | } |
|
146 | 16 | return format(value, formatter); |
147 | } |
|
148 | ||
149 | /** |
|
150 | * <p>Format a value with the specified <code>DateFormat</code>.</p> |
|
151 | * |
|
152 | * @param value The value to be formatted. |
|
153 | * @param formatter The Format to use. |
|
154 | * @return The formatted value. |
|
155 | */ |
|
156 | protected String format(Object value, Format formatter) { |
|
157 | 16 | if (value == null) { |
158 | 1 | return null; |
159 | 15 | } else if (value instanceof Calendar) { |
160 | 13 | value = ((Calendar)value).getTime(); |
161 | } |
|
162 | 15 | return formatter.format(value); |
163 | } |
|
164 | ||
165 | /** |
|
166 | * <p>Checks if the value is valid against a specified pattern.</p> |
|
167 | * |
|
168 | * @param value The value validation is being performed on. |
|
169 | * @param pattern The pattern used to validate the value against, or the |
|
170 | * default for the <code>Locale</code> if <code>null</code>. |
|
171 | * @param locale The locale to use for the date format, system default if null. |
|
172 | * @param timeZone The Time Zone used to parse the date, system default if null. |
|
173 | * @return The parsed value if valid or <code>null</code> if invalid. |
|
174 | */ |
|
175 | protected Object parse(String value, String pattern, Locale locale, TimeZone timeZone) { |
|
176 | ||
177 | 282 | value = (value == null ? class="keyword">null : value.trim()); |
178 | 282 | if (value == null || value.length() == 0) { |
179 | 0 | return null; |
180 | } |
|
181 | 282 | DateFormat formatter = (DateFormat)getFormat(pattern, locale); |
182 | 282 | if (timeZone != null) { |
183 | 12 | formatter.setTimeZone(timeZone); |
184 | } |
|
185 | 282 | return parse(value, formatter); |
186 | ||
187 | } |
|
188 | ||
189 | /** |
|
190 | * <p>Process the parsed value, performing any further validation |
|
191 | * and type conversion required.</p> |
|
192 | * |
|
193 | * @param value The parsed object created. |
|
194 | * @param formatter The Format used to parse the value with. |
|
195 | * @return The parsed value converted to the appropriate type |
|
196 | * if valid or <code>null</code> if invalid. |
|
197 | */ |
|
198 | protected abstract Object processParsedValue(Object value, Format formatter); |
|
199 | ||
200 | /** |
|
201 | * <p>Returns a <code>DateFormat</code> for the specified <i>pattern</i> |
|
202 | * and/or <code>Locale</code>.</p> |
|
203 | * |
|
204 | * @param pattern The pattern used to validate the value against or |
|
205 | * <code>null</code> to use the default for the <code>Locale</code>. |
|
206 | * @param locale The locale to use for the currency format, system default if null. |
|
207 | * @return The <code>DateFormat</code> to created. |
|
208 | */ |
|
209 | protected Format getFormat(String pattern, Locale locale) { |
|
210 | 298 | DateFormat formatter = null; |
211 | 298 | boolean usePattern = (pattern != null && pattern.length() > 0); |
212 | 298 | if (!usePattern) { |
213 | 145 | formatter = (DateFormat)getFormat(locale); |
214 | 153 | } else if (locale == null) { |
215 | 139 | formatter = new SimpleDateFormat(pattern); |
216 | } else { |
|
217 | 14 | DateFormatSymbols symbols = new DateFormatSymbols(locale); |
218 | 14 | formatter = new SimpleDateFormat(pattern, symbols); |
219 | } |
|
220 | 298 | formatter.setLenient(false); |
221 | 298 | return formatter; |
222 | } |
|
223 | ||
224 | /** |
|
225 | * <p>Returns a <code>DateFormat</code> for the specified Locale.</p> |
|
226 | * |
|
227 | * @param locale The locale a <code>DateFormat</code> is required for, |
|
228 | * system default if null. |
|
229 | * @return The <code>DateFormat</code> to created. |
|
230 | */ |
|
231 | protected Format getFormat(Locale locale) { |
|
232 | ||
233 | 145 | DateFormat formatter = null; |
234 | 145 | if (dateStyle >= 0 && timeStyle >= 0) { |
235 | 2 | if (locale == null) { |
236 | 1 | formatter = DateFormat.getDateTimeInstance(dateStyle, timeStyle); |
237 | } else { |
|
238 | 1 | formatter = DateFormat.getDateTimeInstance(dateStyle, timeStyle, locale); |
239 | } |
|
240 | 143 | } else if (timeStyle >= 0) { |
241 | 41 | if (locale == null) { |
242 | 3 | formatter = DateFormat.getTimeInstance(timeStyle); |
243 | } else { |
|
244 | 38 | formatter = DateFormat.getTimeInstance(timeStyle, locale); |
245 | } |
|
246 | } else { |
|
247 | 102 | int useDateStyle = dateStyle >= 0 ? dateStyle : DateFormat.SHORT; |
248 | 102 | if (locale == null) { |
249 | 13 | formatter = DateFormat.getDateInstance(useDateStyle); |
250 | } else { |
|
251 | 89 | formatter = DateFormat.getDateInstance(useDateStyle, locale); |
252 | } |
|
253 | } |
|
254 | 145 | formatter.setLenient(false); |
255 | 145 | return formatter; |
256 | ||
257 | } |
|
258 | ||
259 | /** |
|
260 | * <p>Compares a calendar value to another, indicating whether it is |
|
261 | * equal, less then or more than at a specified level.</p> |
|
262 | * |
|
263 | * @param value The Calendar value. |
|
264 | * @param compare The <code>Calendar</code> to check the value against. |
|
265 | * @param field The field <i>level</i> to compare to - e.g. specifying |
|
266 | * <code>Calendar.MONTH</code> will compare the year and month |
|
267 | * portions of the calendar. |
|
268 | * @return Zero if the first value is equal to the second, -1 |
|
269 | * if it is less than the second or +1 if it is greater than the second. |
|
270 | */ |
|
271 | protected int compare(Calendar value, Calendar compare, class="keyword">int field) { |
|
272 | ||
273 | 44 | int result = 0; |
274 | ||
275 | // Compare Year |
|
276 | 44 | result = calculateCompareResult(value, compare, Calendar.YEAR); |
277 | 44 | if (result != 0 || field == Calendar.YEAR) { |
278 | 6 | return result; |
279 | } |
|
280 | ||
281 | // Compare Week of Year |
|
282 | 38 | if (field == Calendar.WEEK_OF_YEAR) { |
283 | 10 | return calculateCompareResult(value, compare, Calendar.WEEK_OF_YEAR); |
284 | } |
|
285 | ||
286 | // Compare Day of the Year |
|
287 | 28 | if (field == Calendar.DAY_OF_YEAR) { |
288 | 1 | return calculateCompareResult(value, compare, Calendar.DAY_OF_YEAR); |
289 | } |
|
290 | ||
291 | // Compare Month |
|
292 | 27 | result = calculateCompareResult(value, compare, Calendar.MONTH); |
293 | 27 | if (result != 0 || field == Calendar.MONTH) { |
294 | 10 | return result; |
295 | } |
|
296 | ||
297 | // Compare Week of Month |
|
298 | 17 | if (field == Calendar.WEEK_OF_MONTH) { |
299 | 1 | return calculateCompareResult(value, compare, Calendar.WEEK_OF_MONTH); |
300 | } |
|
301 | ||
302 | // Compare Date |
|
303 | 16 | result = calculateCompareResult(value, compare, Calendar.DATE); |
304 | 16 | if (result != 0 || (field == Calendar.DATE || |
305 | field == Calendar.DAY_OF_MONTH || |
|
306 | field == Calendar.DAY_OF_WEEK || |
|
307 | field == Calendar.DAY_OF_WEEK_IN_MONTH)) { |
|
308 | 10 | return result; |
309 | } |
|
310 | ||
311 | // Compare Time fields |
|
312 | 6 | return compareTime(value, compare, field); |
313 | ||
314 | } |
|
315 | ||
316 | /** |
|
317 | * <p>Compares a calendar time value to another, indicating whether it is |
|
318 | * equal, less then or more than at a specified level.</p> |
|
319 | * |
|
320 | * @param value The Calendar value. |
|
321 | * @param compare The <code>Calendar</code> to check the value against. |
|
322 | * @param field The field <i>level</i> to compare to - e.g. specifying |
|
323 | * <code>Calendar.MINUTE</code> will compare the hours and minutes |
|
324 | * portions of the calendar. |
|
325 | * @return Zero if the first value is equal to the second, -1 |
|
326 | * if it is less than the second or +1 if it is greater than the second. |
|
327 | */ |
|
328 | protected int compareTime(Calendar value, Calendar compare, class="keyword">int field) { |
|
329 | ||
330 | 24 | int result = 0; |
331 | ||
332 | // Compare Hour |
|
333 | 24 | result = calculateCompareResult(value, compare, Calendar.HOUR_OF_DAY); |
334 | 24 | if (result != 0 || (field == Calendar.HOUR || field == Calendar.HOUR_OF_DAY)) { |
335 | 7 | return result; |
336 | } |
|
337 | ||
338 | // Compare Minute |
|
339 | 17 | result = calculateCompareResult(value, compare, Calendar.MINUTE); |
340 | 17 | if (result != 0 || field == Calendar.MINUTE) { |
341 | 7 | return result; |
342 | } |
|
343 | ||
344 | // Compare Second |
|
345 | 10 | result = calculateCompareResult(value, compare, Calendar.SECOND); |
346 | 10 | if (result != 0 || field == Calendar.SECOND) { |
347 | 6 | return result; |
348 | } |
|
349 | ||
350 | // Compare Milliseconds |
|
351 | 4 | if (field == Calendar.MILLISECOND) { |
352 | 3 | return calculateCompareResult(value, compare, Calendar.MILLISECOND); |
353 | } |
|
354 | ||
355 | 1 | throw new IllegalArgumentException("Invalid field: " + field); |
356 | ||
357 | } |
|
358 | ||
359 | /** |
|
360 | * <p>Compares a calendar's quarter value to another, indicating whether it is |
|
361 | * equal, less then or more than the specified quarter.</p> |
|
362 | * |
|
363 | * @param value The Calendar value. |
|
364 | * @param compare The <code>Calendar</code> to check the value against. |
|
365 | * @param monthOfFirstQuarter The month that the first quarter starts. |
|
366 | * @return Zero if the first quarter is equal to the second, -1 |
|
367 | * if it is less than the second or +1 if it is greater than the second. |
|
368 | */ |
|
369 | protected int compareQuarters(Calendar value, Calendar compare, class="keyword">int monthOfFirstQuarter) { |
|
370 | 25 | int valueQuarter = calculateQuarter(value, monthOfFirstQuarter); |
371 | 25 | int compareQuarter = calculateQuarter(compare, monthOfFirstQuarter); |
372 | 25 | if (valueQuarter < compareQuarter) { |
373 | 6 | return -1; |
374 | 19 | } else if (valueQuarter > compareQuarter) { |
375 | 9 | return 1; |
376 | } else { |
|
377 | 10 | return 0; |
378 | } |
|
379 | } |
|
380 | ||
381 | /** |
|
382 | * <p>Calculate the quarter for the specified Calendar.</p> |
|
383 | * |
|
384 | * @param calendar The Calendar value. |
|
385 | * @param monthOfFirstQuarter The month that the first quarter starts. |
|
386 | * @return The calculated quarter. |
|
387 | */ |
|
388 | private int calculateQuarter(Calendar calendar, class="keyword">int monthOfFirstQuarter) { |
|
389 | // Add Year |
|
390 | 50 | int year = calendar.get(Calendar.YEAR); |
391 | ||
392 | 50 | int month = (calendar.get(Calendar.MONTH) + 1); |
393 | 50 | int relativeMonth = (month >= monthOfFirstQuarter) |
394 | ? (month - monthOfFirstQuarter) |
|
395 | : (month + (12 - monthOfFirstQuarter)); |
|
396 | 50 | int quarter = ((relativeMonth / 3) + 1); |
397 | // adjust the year if the quarter doesn't start in January |
|
398 | 50 | if (month < monthOfFirstQuarter) { |
399 | 1 | --year; |
400 | } |
|
401 | 50 | return (year * 10) + quarter; |
402 | } |
|
403 | ||
404 | /** |
|
405 | * <p>Compares the field from two calendars indicating whether the field for the |
|
406 | * first calendar is equal to, less than or greater than the field from the |
|
407 | * second calendar. |
|
408 | * |
|
409 | * @param value The Calendar value. |
|
410 | * @param compare The <code>Calendar</code> to check the value against. |
|
411 | * @param field The field to compare for the calendars. |
|
412 | * @return Zero if the first calendar's field is equal to the seconds, -1 |
|
413 | * if it is less than the seconds or +1 if it is greater than the seconds. |
|
414 | */ |
|
415 | private int calculateCompareResult(Calendar value, Calendar compare, class="keyword">int field) { |
|
416 | 153 | int difference = value.get(field) - compare.get(field); |
417 | 153 | if (dclass="keyword">ifference < 0) { |
418 | 13 | return -1; |
419 | 140 | } else if (dclass="keyword">ifference > 0) { |
420 | 17 | return 1; |
421 | } else { |
|
422 | 123 | return 0; |
423 | } |
|
424 | } |
|
425 | } |
This report is generated by jcoverage, Maven and Maven JCoverage Plugin. |