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  
18  package org.apache.commons.beanutils.locale.converters;
19  
20  import java.text.SimpleDateFormat;
21  import java.text.ParseException;
22  import java.text.DateFormatSymbols;
23  
24  import java.util.Locale;
25  
26  import org.apache.commons.beanutils.ConversionException;
27  import org.apache.commons.beanutils.locale.BaseLocaleConverter;
28  import org.apache.commons.logging.LogFactory;
29  import org.apache.commons.logging.Log;
30  
31  /***
32   * Test Case for the DateLocaleConverter class.
33   *
34   * @author Robert Burrell Donkin
35   * @author Niall Pemberton
36   * @version $Revision: 555645 $ $Date: 2007-07-12 15:40:37 +0100 (Thu, 12 Jul 2007) $
37   */
38  
39  public class DateLocaleConverterTestCase extends BaseLocaleConverterTestCase {
40  
41      /*** All logging goes through this logger */
42      private Log log = LogFactory.getLog(DateLocaleConverterTestCase.class);
43  
44      protected String localizedDatePattern; 
45      protected String localizedDateValue;
46      protected String localizedShortDateValue;
47      protected String defaultDatePattern; 
48      protected String defaultDateValue;
49      protected String defaultShortDateValue;
50  
51      protected boolean validLocalDateSymbols;
52  
53      // ------------------------------------------------------------------------
54  
55      public DateLocaleConverterTestCase(String name) {
56          super(name);
57      }
58      
59      // -------------------------------------------------- Overall Test Methods
60  
61      /***
62       * Set up instance variables required by this test case.
63       */
64      public void setUp() throws Exception {
65  
66          super.setUp();
67  
68          String version = System.getProperty("java.specification.version");
69          log.warn("JDK Version "+version);
70  
71  
72          try {
73              SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
74              expectedValue      = format.parse("20041001");
75              defaultValue       = format.parse("19670316");
76          } catch (Exception ex) {
77              log.error("Error creating expected/default dates", ex);
78          }
79  
80          // Default Locale (Use US)
81          defaultLocale           = Locale.US;
82          defaultDatePattern      = "d MMMM yyyy";
83          defaultDateValue        = "1 October 2004";
84          defaultShortDateValue   = "10/01/04";
85  
86          // Use German Locale
87  //        localizedLocale         = Locale.GERMAN;  // N.B. doesn't work for dates
88  //        localizedLocale         = Locale.GERMANY; // N.B. doesn't work for dates
89          localizedLocale         = new Locale("de", "AT"); // Austria/German works
90          localizedDatePattern    = "t MMMM uuuu";
91          localizedDateValue      = "1 Oktober 2004";
92          localizedShortDateValue = "01.10.04";
93  
94          // Test whether the "local pattern characters" are what we
95          // are expecting - Locale.GERMAN and Locale.GERMANY, Locale.FRENCH all
96          // returned the standard "English" pattern characters on my machine
97          // for JDK 1.4 (JDK 1.3 was OK). The Austria/German locale was OK though
98          String expectedChars = "GuMtkHmsSEDFwWahKzZ";
99          DateFormatSymbols localizedSymbols = new DateFormatSymbols(localizedLocale);
100         String localChars    = localizedSymbols.getLocalPatternChars();
101 
102         // different JDK versions seem to have different numbers of pattern characters 
103         int lth = localChars.length() > expectedChars.length() ? expectedChars.length() :
104                      localChars.length() < expectedChars.length() ? localChars.length() : expectedChars.length();
105         validLocalDateSymbols = expectedChars.substring(0, lth).equals(localChars.substring(0, lth));
106 
107     }
108 
109     /***
110      * Tear down instance variables required by this test case.
111      */
112     public void tearDown() {
113         super.tearDown();
114     }
115 
116 
117     // ------------------------------------------------------------------------
118 
119     public void testSetLenient() {
120         // make sure that date format works as expected
121         SimpleDateFormat dateFormat = new SimpleDateFormat("MMM dd, yyyy", Locale.UK);
122         
123         // test with no leniency
124         dateFormat.setLenient(false);
125         
126         try {
127             
128             dateFormat.parse("Feb 10, 2001");
129             
130         } catch (ParseException e) {
131             fail("Could not parse date (1) - " + e.getMessage());
132         }
133         
134         try {
135         
136             dateFormat.parse("Feb 31, 2001");
137             fail("Parsed illegal date (1)");
138         
139         } catch (ParseException e) {
140             // that's what we expected
141         }	
142         
143         // test with leniency
144         dateFormat.setLenient(true);
145         
146         try {
147             
148             dateFormat.parse("Feb 10, 2001");
149             
150         } catch (ParseException e) {
151             fail("Could not parse date (2) - " + e.getMessage());
152         }
153         
154         try {
155         
156             dateFormat.parse("Feb 31, 2001");
157         
158         } catch (ParseException e) {
159             fail("Could not parse date (3) - " + e.getMessage());
160         }
161         
162         // now repeat tests for converter
163         DateLocaleConverter converter = new DateLocaleConverter(Locale.UK, "MMM dd, yyyy");
164         
165         // test with no leniency
166         converter.setLenient(false);
167         assertEquals("Set lenient failed", converter.isLenient(), false);
168         
169         try {
170             
171             converter.convert("Feb 10, 2001");
172             
173         } catch (ConversionException e) {
174             fail("Could not parse date (4) - " + e.getMessage());
175         }
176         
177         try {
178         
179             converter.convert("Feb 31, 2001");
180             assertEquals("Set lenient failed", converter.isLenient(), false);
181             fail("Parsed illegal date (2)");
182         
183         } catch (ConversionException e) {
184             // that's what we expected
185         }	
186         
187         // test with leniency
188         converter.setLenient(true);
189         assertEquals("Set lenient failed", converter.isLenient(), true);
190         
191         try {
192             
193             converter.convert("Feb 10, 2001");
194             
195         } catch (ConversionException e) {
196             fail("Could not parse date (5) - " + e.getMessage());
197         }
198         
199         try {
200         
201             converter.convert("Feb 31, 2001");
202         
203         } catch (ConversionException e) {
204             fail("Could not parse date (6) - " + e.getMessage());
205         }
206     }
207 
208     /***
209      * Test Converter(defaultValue, locale, pattern, localizedPattern) constructor
210      */
211     public void testConstructorMain() {
212 
213         // Skip this test if no valid symbols for the locale
214         if (!validLocalDateSymbols) {
215             log.error("Invalid locale symbols *** skipping testConstructorMain() **");
216             return;
217         } 
218 
219         // ------------- Construct with localized pattern ------------
220         converter = new DateLocaleConverter(defaultValue,
221                                             localizedLocale,
222                                             localizedDatePattern,
223                                             true);
224 
225 
226         convertValueNoPattern(converter, "(A)", localizedDateValue, expectedValue);
227         convertValueWithPattern(converter, "(A)", localizedDateValue, localizedDatePattern, expectedValue);
228         convertInvalid(converter, "(A)", defaultValue);
229         convertNull(converter, "(A)", defaultValue);
230 
231 
232         // Convert value in the wrong format - should return default value
233         convertValueNoPattern(converter, "(B)", defaultDateValue, defaultValue);
234 
235         // Convert with non-localized pattern - should return default value
236         convertValueWithPattern(converter, "(B)", localizedDateValue, defaultDatePattern, defaultValue);
237 
238         // **************************************************************************
239         // Convert with specified type
240         // 
241         // BaseLocaleConverter completely ignores the type - so even if we specify
242         // Double.class here it still returns a Date.
243         //  **** SHOULD IMPLEMENT THIS BEHAVIOUR ****
244         // **************************************************************************
245         convertValueToType(converter, "(B)", String.class, localizedDateValue, localizedDatePattern, expectedValue);
246 
247 
248         // ------------- Construct with non-localized pattern ------------
249         converter = new DateLocaleConverter(defaultValue,
250                                             localizedLocale,
251                                             defaultDatePattern,
252                                             false);
253 
254 
255         convertValueNoPattern(converter, "(C)", localizedDateValue, expectedValue);
256         convertValueWithPattern(converter, "(C)", localizedDateValue, defaultDatePattern, expectedValue);
257         convertInvalid(converter, "(C)", defaultValue);
258         convertNull(converter, "(C)", defaultValue);
259 
260     }
261 
262     /***
263      * Test Converter() constructor
264      * 
265      * Uses the default locale, no default value
266      * 
267      */
268     public void testConstructor_2() {
269 
270         // ------------- Construct using default pattern & default locale ------------
271         converter = new DateLocaleConverter();
272 
273         // Perform Tests
274         convertValueNoPattern(converter, defaultShortDateValue, expectedValue);
275         convertValueWithPattern(converter, defaultDateValue, defaultDatePattern, expectedValue);
276         convertInvalid(converter, null);
277         convertNull(converter, null);
278 
279     }
280 
281     /***
282      * Test Converter(locPattern) constructor
283      * 
284      * Uses the default locale, no default value
285      * 
286      */
287     public void testConstructor_3() {
288 
289         // ------------- Construct using default pattern & default locale --------
290         converter = new DateLocaleConverter(true);
291 
292         // Perform Tests
293         convertValueNoPattern(converter, defaultShortDateValue, expectedValue);
294         convertValueWithPattern(converter, defaultDateValue, defaultDatePattern, expectedValue);
295         convertInvalid(converter, null);
296         convertNull(converter, null);
297 
298 
299     }
300 
301     /***
302      * Test Converter(Locale) constructor
303      */
304     public void testConstructor_4() {
305 
306         // ------------- Construct using specified Locale --------
307         converter = new DateLocaleConverter(localizedLocale);
308 
309         // Perform Tests
310         convertValueNoPattern(converter, localizedShortDateValue, expectedValue);
311         convertValueWithPattern(converter, localizedDateValue, defaultDatePattern, expectedValue);
312         convertInvalid(converter, null);
313         convertNull(converter, null);
314 
315 
316     }
317 
318 
319     /***
320      * Test Converter(Locale, locPattern) constructor
321      */
322     public void testConstructor_5() {
323 
324         // Skip this test if no valid symbols for the locale
325         if (!validLocalDateSymbols) {
326             log.error("Invalid locale symbols *** skipping testConstructor_5() **");
327             return;
328         } 
329 
330         // ------------- Construct using specified Locale --------
331         converter = new DateLocaleConverter(localizedLocale, true);
332 
333         // Perform Tests
334         convertValueNoPattern(converter, localizedShortDateValue, expectedValue);
335         convertValueWithPattern(converter, localizedDateValue, localizedDatePattern, expectedValue);
336         convertInvalid(converter, null);
337         convertNull(converter, null);
338 
339 
340     }
341 
342     /***
343      * Test Converter(Locale, pattern) constructor
344      */
345     public void testConstructor_6() {
346 
347         // ------------- Construct using specified Locale --------
348         converter = new DateLocaleConverter(localizedLocale, defaultDatePattern);
349 
350         // Perform Tests
351         convertValueNoPattern(converter, localizedDateValue, expectedValue);
352         convertValueWithPattern(converter, localizedDateValue, defaultDatePattern, expectedValue);
353         convertInvalid(converter, null);
354         convertNull(converter, null);
355 
356     }
357 
358     /***
359      * Test Converter(Locale, pattern, locPattern) constructor
360      */
361     public void testConstructor_7() {
362 
363         // Skip this test if no valid symbols for the locale
364         if (!validLocalDateSymbols) {
365             log.error("Invalid locale symbols *** skipping testConstructor_7() **");
366             return;
367         } 
368 
369         // ------------- Construct using specified Locale --------
370         converter = new DateLocaleConverter(localizedLocale, localizedDatePattern, true);
371 
372         // Perform Tests
373         convertValueNoPattern(converter, localizedDateValue, expectedValue);
374         convertValueWithPattern(converter, localizedDateValue, localizedDatePattern, expectedValue);
375         convertInvalid(converter, null);
376         convertNull(converter, null);
377 
378     }
379 
380     /***
381      * Test Converter(defaultValue) constructor
382      */
383     public void testConstructor_8() {
384 
385         // ------------- Construct using specified Locale --------
386         converter = new DateLocaleConverter(defaultValue);
387 
388         // Perform Tests
389         convertValueNoPattern(converter, defaultShortDateValue, expectedValue);
390         convertValueWithPattern(converter, defaultDateValue, defaultDatePattern, expectedValue);
391         convertInvalid(converter, defaultValue);
392         convertNull(converter, defaultValue);
393 
394     }
395 
396     /***
397      * Test Converter(defaultValue, locPattern) constructor
398      */
399     public void testConstructor_9() {
400 
401         // ------------- Construct using specified Locale --------
402         converter = new DateLocaleConverter(defaultValue, true);
403 
404         // Perform Tests
405         convertValueNoPattern(converter, defaultShortDateValue, expectedValue);
406         convertValueWithPattern(converter, defaultDateValue, defaultDatePattern, expectedValue);
407         convertInvalid(converter, defaultValue);
408         convertNull(converter, defaultValue);
409 
410     }
411 
412     /***
413      * Test invalid date
414      */
415     public void testInvalidDate() {
416 
417         converter = new DateLocaleConverter(defaultLocale);
418 
419         try {
420             converter.convert("01/10/2004", "dd-MM-yyyy");
421         } catch (ConversionException e) {
422             assertEquals("Parse Error", "Error parsing date '01/10/2004' at position=2", e.getMessage());
423         }
424 
425         try {
426             converter.convert("01-10-2004X", "dd-MM-yyyy");
427         } catch (ConversionException e) {
428             assertEquals("Parse Length", "Date '01-10-2004X' contains unparsed characters from position=10", e.getMessage());
429         }
430 
431     }
432 
433     /***
434      * Test java.util.Date
435      */
436     public void testDateObject() {
437         converter = new DateLocaleConverter(defaultLocale);
438         assertEquals("java.util.Date", expectedValue, converter.convert(expectedValue));
439     }
440 
441     /***
442      * Test Calendar
443      */
444     public void testCalendarObject() {
445         converter = new DateLocaleConverter(defaultLocale);
446         java.util.Calendar calendar = java.util.Calendar.getInstance();
447         calendar.setTime((java.util.Date)expectedValue);
448         assertEquals("java.util.Calendar", expectedValue, converter.convert(calendar));
449     }
450 
451 }
452