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