1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.beanutils.converters;
19
20 import java.text.DateFormat;
21 import java.text.SimpleDateFormat;
22 import java.util.Calendar;
23 import java.util.Date;
24 import java.util.GregorianCalendar;
25 import java.util.Locale;
26
27 import junit.framework.TestCase;
28 import org.apache.commons.beanutils.Converter;
29 import org.apache.commons.beanutils.ConversionException;
30
31 /***
32 * Abstract base for <Date>Converter classes.
33 *
34 * @version $Revision: 471689 $ $Date: 2006-11-06 10:52:49 +0000 (Mon, 06 Nov 2006) $
35 */
36
37 public abstract class DateConverterTestBase extends TestCase {
38
39
40
41 /***
42 * Construtc a new test case.
43 * @param name Name of the test
44 */
45 public DateConverterTestBase(String name) {
46 super(name);
47 }
48
49
50
51 /***
52 * Create the Converter with no default value.
53 * @return A new Converter
54 */
55 protected abstract DateTimeConverter makeConverter();
56
57 /***
58 * Create the Converter with a default value.
59 * @param defaultValue The default value
60 * @return A new Converter
61 */
62 protected abstract DateTimeConverter makeConverter(Object defaultValue);
63
64 /***
65 * Return the expected type
66 * @return The expected type
67 */
68 protected abstract Class getExpectedType();
69
70 /***
71 * Convert from a Calendar to the appropriate Date type
72 *
73 * @param value The Calendar value to convert
74 * @return The converted value
75 */
76 protected abstract Object toType(Calendar value);
77
78
79
80 /***
81 * Assumes ConversionException in response to covert(getExpectedType(), null).
82 */
83 public void testConvertNull() {
84 try {
85 makeConverter().convert(getExpectedType(), null);
86 fail("Expected ConversionException");
87 } catch(ConversionException e) {
88
89 }
90 }
91
92 /***
93 * Assumes convert() returns some non-null
94 * instance of getExpectedType().
95 */
96 public void testConvertDate() {
97 String[] message= {
98 "from Date",
99 "from Calendar",
100 "from SQL Date",
101 "from SQL Time",
102 "from SQL Timestamp"
103 };
104
105 long now = System.currentTimeMillis();
106
107 Object[] date = {
108 new Date(now),
109 new java.util.GregorianCalendar(),
110 new java.sql.Date(now),
111 new java.sql.Time(now),
112 new java.sql.Timestamp(now)
113 };
114
115
116 ((GregorianCalendar)date[1]).setTime(new Date(now));
117
118 for (int i = 0; i < date.length; i++) {
119 Object val = makeConverter().convert(getExpectedType(), date[i]);
120 assertNotNull("Convert " + message[i] + " should not be null", val);
121 assertTrue("Convert " + message[i] + " should return a " + getExpectedType().getName(),
122 getExpectedType().isInstance(val));
123 assertEquals("Convert " + message[i] + " should return a " + date[0],
124 now, getTimeInMillis(val));
125 }
126 }
127
128 /***
129 * Test Default Type conversion (i.e. don't specify target type)
130 */
131 public void testDefaultType() {
132 String pattern = "yyyy-MM-dd";
133
134
135 DateTimeConverter converter = makeConverter();
136 converter.setPattern(pattern);
137
138
139 String testString = "2006-10-29";
140 Calendar calendar = toCalendar(testString, pattern, null);
141 Object expected = toType(calendar);
142
143 Object result = converter.convert(null, testString);
144 if (getExpectedType().equals(Calendar.class)) {
145 assertTrue("TYPE ", getExpectedType().isAssignableFrom(result.getClass()));
146 } else {
147 assertEquals("TYPE ", getExpectedType(), result.getClass());
148 }
149 assertEquals("VALUE ", expected, result);
150 }
151
152 /***
153 * Test default String to type conversion
154 *
155 * N.B. This method is overriden by test case
156 * implementations for java.sql.Date/Time/Timestamp
157 */
158 public void testDefaultStringToTypeConvert() {
159
160
161 DateTimeConverter converter = makeConverter();
162 converter.setUseLocaleFormat(false);
163 try {
164 converter.convert(getExpectedType(), "2006-10-23");
165 fail("Expected Conversion exception");
166 } catch (ConversionException e) {
167
168 }
169
170 }
171
172 /***
173 * Test Conversion to String
174 */
175 public void testStringConversion() {
176
177 String pattern = "yyyy-MM-dd";
178
179
180 DateTimeConverter converter = makeConverter();
181 converter.setPattern(pattern);
182
183
184 String expected = "2006-10-29";
185 Calendar calendar = toCalendar(expected, pattern, null);
186
187
188 stringConversion(converter, expected, toType(calendar));
189
190
191 stringConversion(converter, expected, calendar);
192
193
194 stringConversion(converter, expected, toDate(calendar));
195
196
197 stringConversion(converter, expected, toSqlDate(calendar));
198
199
200 stringConversion(converter, expected, toSqlTimestamp(calendar));
201
202
203 stringConversion(converter, expected, toSqlTime(calendar));
204
205 stringConversion(converter, null, null);
206 stringConversion(converter, "", "");
207
208 }
209
210 /***
211 * Test Converter with no default value
212 */
213 public void testPatternNoDefault() {
214
215 String pattern = "yyyy-MM-dd";
216
217
218 DateTimeConverter converter = makeConverter();
219 converter.setPattern(pattern);
220
221
222 String testString = "2006-10-29";
223 Calendar calendar = toCalendar(testString, pattern, null);
224 Object expected = toType(calendar);
225 validConversion(converter, expected, testString);
226
227
228 validConversion(converter, expected, calendar);
229
230
231 validConversion(converter, expected, toDate(calendar));
232
233
234 validConversion(converter, expected, toSqlDate(calendar));
235
236
237 validConversion(converter, expected, toSqlTimestamp(calendar));
238
239
240 validConversion(converter, expected, toSqlTime(calendar));
241
242
243 invalidConversion(converter, null);
244 invalidConversion(converter, "");
245 invalidConversion(converter, "2006-10-2X");
246 invalidConversion(converter, "2006/10/01");
247 invalidConversion(converter, "02/10/2006");
248 invalidConversion(converter, "02/10/06");
249 invalidConversion(converter, new Integer(2));
250
251 }
252
253 /***
254 * Test Converter with no default value
255 */
256 public void testPatternDefault() {
257
258 String pattern = "yyyy-MM-dd";
259
260
261 Object defaultValue = toType("2000-01-01", pattern, null);
262 assertNotNull("Check default date", defaultValue);
263 DateTimeConverter converter = makeConverter(defaultValue);
264 converter.setPattern(pattern);
265
266
267 String testString = "2006-10-29";
268 Object expected = toType(testString, pattern, null);
269 validConversion(converter, expected, testString);
270
271
272 validConversion(converter, defaultValue, null);
273 validConversion(converter, defaultValue, "");
274 validConversion(converter, defaultValue, "2006-10-2X");
275 validConversion(converter, defaultValue, "2006/10/01");
276 validConversion(converter, defaultValue, "02/10/06");
277 validConversion(converter, defaultValue, new Integer(2));
278
279 }
280
281 /***
282 * Test Converter with no default value
283 */
284 public void testPatternNullDefault() {
285
286 String pattern = "yyyy-MM-dd";
287
288
289 Object defaultValue = null;
290 DateTimeConverter converter = makeConverter(defaultValue);
291 converter.setPattern(pattern);
292
293
294 String testString = "2006-10-29";
295 Object expected = toType(testString, pattern, null);
296 validConversion(converter, expected, testString);
297
298
299 validConversion(converter, defaultValue, null);
300 validConversion(converter, defaultValue, "");
301 validConversion(converter, defaultValue, "2006-10-2X");
302 validConversion(converter, defaultValue, "2006/10/01");
303 validConversion(converter, defaultValue, "02/10/06");
304 validConversion(converter, defaultValue, new Integer(2));
305
306 }
307
308 /***
309 * Test Converter with multiple patterns
310 */
311 public void testMultiplePatterns() {
312 String testString = null;
313 Object expected = null;
314
315
316 String[] patterns = new String[] {"yyyy-MM-dd", "yyyy/MM/dd"};
317 DateTimeConverter converter = makeConverter();
318 converter.setPatterns(patterns);
319
320
321 testString = "2006-10-28";
322 expected = toType(testString, patterns[0], null);
323 validConversion(converter, expected, testString);
324
325
326 testString = "2006/10/18";
327 expected = toType(testString, patterns[1], null);
328 validConversion(converter, expected, testString);
329
330
331 invalidConversion(converter, "17/03/2006");
332 invalidConversion(converter, "17.03.2006");
333
334 }
335
336 /***
337 * Test Date Converter with no default value
338 */
339 public void testLocale() {
340
341
342 Locale defaultLocale = Locale.getDefault();
343 Locale.setDefault(Locale.US);
344
345 String pattern = "M/d/yy";
346
347
348 DateTimeConverter converter = makeConverter();
349 converter.setUseLocaleFormat(true);
350
351
352 String testString = "10/28/06";
353 Object expected = toType(testString, pattern, null);
354 validConversion(converter, expected, testString);
355
356
357 invalidConversion(converter, null);
358 invalidConversion(converter, "");
359 invalidConversion(converter, "2006-10-2X");
360 invalidConversion(converter, "10.28.06");
361 invalidConversion(converter, "10-28-06");
362 invalidConversion(converter, new Integer(2));
363
364
365 Locale.setDefault(defaultLocale);
366
367 }
368
369 /***
370 * Test Converter with types it can't handle
371 */
372 public void testInvalidType() {
373
374
375 DateTimeConverter converter = makeConverter();
376
377
378 try {
379 converter.convert(Character.class, new Date());
380 fail("Requested Character.class conversion, expected ConversionException");
381 } catch (ConversionException e) {
382
383 }
384 }
385
386 /***
387 * Test Conversion to the required type
388 * @param converter The converter to use
389 * @param expected The expected result
390 * @param value The value to convert
391 */
392 void validConversion(Converter converter, Object expected, Object value) {
393 String valueType = (value == null ? "null" : value.getClass().getName());
394 String msg = "Converting '" + valueType + "' value '" + value + "'";
395 try {
396 Object result = converter.convert(getExpectedType(), value);
397 Class resultType = (result == null ? null : result.getClass());
398 Class expectType = (expected == null ? null : expected.getClass());
399 assertEquals("TYPE " + msg, expectType, resultType);
400 assertEquals("VALUE " + msg, expected, result);
401 } catch (Exception ex) {
402 fail(msg + " threw " + ex.toString());
403 }
404 }
405
406 /***
407 * Test Conversion to String
408 * @param converter The converter to use
409 * @param expected The expected result
410 * @param value The value to convert
411 */
412 void stringConversion(Converter converter, String expected, Object value) {
413 String valueType = (value == null ? "null" : value.getClass().getName());
414 String msg = "Converting '" + valueType + "' value '" + value + "' to String";
415 try {
416 Object result = converter.convert(String.class, value);
417 Class resultType = (result == null ? null : result.getClass());
418 Class expectType = (expected == null ? null : expected.getClass());
419 assertEquals("TYPE " + msg, expectType, resultType);
420 assertEquals("VALUE " + msg, expected, result);
421 } catch (Exception ex) {
422 fail(msg + " threw " + ex.toString());
423 }
424 }
425
426 /***
427 * Test Conversion Error
428 * @param converter The converter to use
429 * @param value The value to convert
430 */
431 void invalidConversion(Converter converter, Object value) {
432 String valueType = (value == null ? "null" : value.getClass().getName());
433 String msg = "Converting '" + valueType + "' value '" + value + "'";
434 try {
435 Object result = converter.convert(getExpectedType(), value);
436 fail(msg + ", expected ConversionException, but result = '" + result + "'");
437 } catch (ConversionException ex) {
438
439 }
440 }
441
442 /***
443 * Parse a String value to the required type
444 * @param value The String value to parse
445 * @param pattern The date pattern
446 * @param locale The locale to use (or null)
447 * @return parsed Calendar value
448 */
449 Object toType(String value, String pattern, Locale locale) {
450 Calendar calendar = toCalendar(value, pattern, locale);
451 return toType(calendar);
452 }
453
454 /***
455 * Parse a String value to a Calendar
456 * @param value The String value to parse
457 * @param pattern The date pattern
458 * @param locale The locale to use (or null)
459 * @return parsed Calendar value
460 */
461 Calendar toCalendar(String value, String pattern, Locale locale) {
462 Calendar calendar = null;
463 try {
464 DateFormat format = (locale == null)
465 ? new SimpleDateFormat(pattern)
466 : new SimpleDateFormat(pattern, locale);
467 format.setLenient(false);
468 format.parse(value);
469 calendar = format.getCalendar();
470 } catch (Exception e) {
471 fail("Error creating Calendar value ='"
472 + value + ", pattern='" + pattern + "' " + e.toString());
473 }
474 return calendar;
475 }
476
477 /***
478 * Convert a Calendar to a java.util.Date
479 * @param calendar The calendar object to convert
480 * @return The converted java.util.Date
481 */
482 Date toDate(Calendar calendar) {
483 return calendar.getTime();
484 }
485
486 /***
487 * Convert a Calendar to a java.sql.Date
488 * @param calendar The calendar object to convert
489 * @return The converted java.sql.Date
490 */
491 java.sql.Date toSqlDate(Calendar calendar) {
492 return new java.sql.Date(getTimeInMillis(calendar));
493 }
494
495 /***
496 * Convert a Calendar to a java.sql.Time
497 * @param calendar The calendar object to convert
498 * @return The converted java.sql.Time
499 */
500 java.sql.Time toSqlTime(Calendar calendar) {
501 return new java.sql.Time(getTimeInMillis(calendar));
502 }
503
504 /***
505 * Convert a Calendar to a java.sql.Timestamp
506 * @param calendar The calendar object to convert
507 * @return The converted java.sql.Timestamp
508 */
509 java.sql.Timestamp toSqlTimestamp(Calendar calendar) {
510 return new java.sql.Timestamp(getTimeInMillis(calendar));
511 }
512
513 /***
514 * Convert a Date or Calendar objects to the time in millisconds
515 * @param date The date or calendar object
516 * @return The time in milliseconds
517 */
518 long getTimeInMillis(Object date) {
519
520 if (date instanceof java.sql.Timestamp) {
521
522
523
524
525 java.sql.Timestamp timestamp = (java.sql.Timestamp)date;
526 long timeInMillis = ((timestamp.getTime() / 1000) * 1000);
527 timeInMillis += timestamp.getNanos() / 1000000;
528 return timeInMillis;
529 }
530
531 if (date instanceof Calendar) {
532 return ((Calendar)date).getTime().getTime();
533 } else {
534 return ((Date)date).getTime();
535 }
536 }
537 }