1// © 2016 and later: Unicode, Inc. and others.
2// License & terms of use: http://www.unicode.org/copyright.html#License
3/*
4 *******************************************************************************
5 * Copyright (c) 2004-2014, International Business Machines
6 * Corporation and others.  All Rights Reserved.
7 *******************************************************************************
8 *
9 */
10package com.ibm.icu.dev.test.serializable;
11
12import java.text.AttributedCharacterIterator;
13import java.util.Date;
14import java.util.HashMap;
15import java.util.Locale;
16
17import com.ibm.icu.impl.DateNumberFormat;
18import com.ibm.icu.impl.TZDBTimeZoneNames;
19import com.ibm.icu.impl.TimeZoneGenericNames;
20import com.ibm.icu.impl.TimeZoneGenericNames.GenericNameType;
21import com.ibm.icu.impl.Utility;
22import com.ibm.icu.text.ChineseDateFormat;
23import com.ibm.icu.text.ChineseDateFormatSymbols;
24import com.ibm.icu.text.CompactDecimalFormat;
25import com.ibm.icu.text.CurrencyPluralInfo;
26import com.ibm.icu.text.DateFormat;
27import com.ibm.icu.text.DateFormatSymbols;
28import com.ibm.icu.text.DateIntervalFormat;
29import com.ibm.icu.text.DateIntervalInfo;
30import com.ibm.icu.text.DecimalFormat;
31import com.ibm.icu.text.DecimalFormatSymbols;
32import com.ibm.icu.text.DurationFormat;
33import com.ibm.icu.text.MessageFormat;
34import com.ibm.icu.text.NumberFormat;
35import com.ibm.icu.text.PluralFormat;
36import com.ibm.icu.text.PluralRules;
37import com.ibm.icu.text.RuleBasedNumberFormat;
38import com.ibm.icu.text.SelectFormat;
39import com.ibm.icu.text.SimpleDateFormat;
40import com.ibm.icu.text.TimeUnitFormat;
41import com.ibm.icu.text.TimeZoneFormat;
42import com.ibm.icu.text.TimeZoneFormat.Style;
43import com.ibm.icu.text.TimeZoneNames;
44import com.ibm.icu.text.TimeZoneNames.NameType;
45import com.ibm.icu.util.Calendar;
46import com.ibm.icu.util.DateInterval;
47import com.ibm.icu.util.GregorianCalendar;
48import com.ibm.icu.util.TimeUnit;
49import com.ibm.icu.util.TimeUnitAmount;
50import com.ibm.icu.util.TimeZone;
51import com.ibm.icu.util.ULocale;
52
53/**
54 * @author emader
55 *
56 * TODO To change the template for this generated type comment go to
57 * Window - Preferences - Java - Code Style - Code Templates
58 */
59public class FormatHandler
60{
61    /*
62     * The serialized form of a normally created DateFormatSymbols object
63     * will have locale-specific data in it that might change from one version
64     * of ICU4J to another. To guard against this, we store the following canned
65     * data into the test objects we create.
66     */
67    static HashMap cannedMonthNames      = new HashMap();
68    static HashMap cannedShortMonthNames = new HashMap();
69
70    static String en_CA_MonthNames[] = {
71        "January",
72        "February",
73        "March",
74        "April",
75        "May",
76        "June",
77        "July",
78        "August",
79        "September",
80        "October",
81        "November",
82        "December",
83    };
84
85    static String fr_CA_MonthNames[] = {
86        "janvier",
87        "f\u00E9vrier",
88        "mars",
89        "avril",
90        "mai",
91        "juin",
92        "juillet",
93        "ao\u00FBt",
94        "septembre",
95        "octobre",
96        "novembre",
97        "d\u00E9cembre",
98    };
99
100    static String zh_Hans_CN_MonthNames[] = {
101        "\u4E00\u6708",
102        "\u4E8C\u6708",
103        "\u4E09\u6708",
104        "\u56DB\u6708",
105        "\u4E94\u6708",
106        "\u516D\u6708",
107        "\u4E03\u6708",
108        "\u516B\u6708",
109        "\u4E5D\u6708",
110        "\u5341\u6708",
111        "\u5341\u4E00\u6708",
112        "\u5341\u4E8C\u6708",
113    };
114
115    static String zh_CN_MonthNames[] = {
116        "\u4E00\u6708",
117        "\u4E8C\u6708",
118        "\u4E09\u6708",
119        "\u56DB\u6708",
120        "\u4E94\u6708",
121        "\u516D\u6708",
122        "\u4E03\u6708",
123        "\u516B\u6708",
124        "\u4E5D\u6708",
125        "\u5341\u6708",
126        "\u5341\u4E00\u6708",
127        "\u5341\u4E8C\u6708",
128    };
129
130    static String zh_MonthNames[] = {
131        "\u4E00\u6708",
132        "\u4E8C\u6708",
133        "\u4E09\u6708",
134        "\u56DB\u6708",
135        "\u4E94\u6708",
136        "\u516D\u6708",
137        "\u4E03\u6708",
138        "\u516B\u6708",
139        "\u4E5D\u6708",
140        "\u5341\u6708",
141        "\u5341\u4E00\u6708",
142        "\u5341\u4E8C\u6708",
143    };
144
145    static String en_MonthNames[] = {
146        "January",
147        "February",
148        "March",
149        "April",
150        "May",
151        "June",
152        "July",
153        "August",
154        "September",
155        "October",
156        "November",
157        "December",
158    };
159
160    static String fr_FR_MonthNames[] = {
161        "janvier",
162        "f\u00E9vrier",
163        "mars",
164        "avril",
165        "mai",
166        "juin",
167        "juillet",
168        "ao\u00FBt",
169        "septembre",
170        "octobre",
171        "novembre",
172        "d\u00E9cembre",
173    };
174
175    static String fr_MonthNames[] = {
176        "janvier",
177        "f\u00E9vrier",
178        "mars",
179        "avril",
180        "mai",
181        "juin",
182        "juillet",
183        "ao\u00FBt",
184        "septembre",
185        "octobre",
186        "novembre",
187        "d\u00E9cembre",
188    };
189
190    static String de_MonthNames[] = {
191        "Januar",
192        "Februar",
193        "M\u00E4rz",
194        "April",
195        "Mai",
196        "Juni",
197        "Juli",
198        "August",
199        "September",
200        "Oktober",
201        "November",
202        "Dezember",
203    };
204
205    static String de_DE_MonthNames[] = {
206        "Januar",
207        "Februar",
208        "M\u00E4rz",
209        "April",
210        "Mai",
211        "Juni",
212        "Juli",
213        "August",
214        "September",
215        "Oktober",
216        "November",
217        "Dezember",
218    };
219
220    static String it_MonthNames[] = {
221        "gennaio",
222        "febbraio",
223        "marzo",
224        "aprile",
225        "maggio",
226        "giugno",
227        "luglio",
228        "agosto",
229        "settembre",
230        "ottobre",
231        "novembre",
232        "dicembre",
233    };
234
235    static String it_IT_MonthNames[] = {
236        "gennaio",
237        "febbraio",
238        "marzo",
239        "aprile",
240        "maggio",
241        "giugno",
242        "luglio",
243        "agosto",
244        "settembre",
245        "ottobre",
246        "novembre",
247        "dicembre",
248    };
249
250    static String ja_JP_MonthNames[] = {
251        "1\u6708",
252        "2\u6708",
253        "3\u6708",
254        "4\u6708",
255        "5\u6708",
256        "6\u6708",
257        "7\u6708",
258        "8\u6708",
259        "9\u6708",
260        "10\u6708",
261        "11\u6708",
262        "12\u6708",
263    };
264
265    static String ja_MonthNames[] = {
266        "1\u6708",
267        "2\u6708",
268        "3\u6708",
269        "4\u6708",
270        "5\u6708",
271        "6\u6708",
272        "7\u6708",
273        "8\u6708",
274        "9\u6708",
275        "10\u6708",
276        "11\u6708",
277        "12\u6708",
278    };
279
280    static String ko_KR_MonthNames[] = {
281        "1\uC6D4",
282        "2\uC6D4",
283        "3\uC6D4",
284        "4\uC6D4",
285        "5\uC6D4",
286        "6\uC6D4",
287        "7\uC6D4",
288        "8\uC6D4",
289        "9\uC6D4",
290        "10\uC6D4",
291        "11\uC6D4",
292        "12\uC6D4",
293    };
294
295    static String ko_MonthNames[] = {
296        "1\uC6D4",
297        "2\uC6D4",
298        "3\uC6D4",
299        "4\uC6D4",
300        "5\uC6D4",
301        "6\uC6D4",
302        "7\uC6D4",
303        "8\uC6D4",
304        "9\uC6D4",
305        "10\uC6D4",
306        "11\uC6D4",
307        "12\uC6D4",
308    };
309
310    static String zh_Hant_TW_MonthNames[] = {
311        "\u4E00\u6708",
312        "\u4E8C\u6708",
313        "\u4E09\u6708",
314        "\u56DB\u6708",
315        "\u4E94\u6708",
316        "\u516D\u6708",
317        "\u4E03\u6708",
318        "\u516B\u6708",
319        "\u4E5D\u6708",
320        "\u5341\u6708",
321        "\u5341\u4E00\u6708",
322        "\u5341\u4E8C\u6708",
323    };
324
325    static String zh_TW_MonthNames[] = {
326        "\u4E00\u6708",
327        "\u4E8C\u6708",
328        "\u4E09\u6708",
329        "\u56DB\u6708",
330        "\u4E94\u6708",
331        "\u516D\u6708",
332        "\u4E03\u6708",
333        "\u516B\u6708",
334        "\u4E5D\u6708",
335        "\u5341\u6708",
336        "\u5341\u4E00\u6708",
337        "\u5341\u4E8C\u6708",
338        };
339
340    static String en_GB_MonthNames[] = {
341        "January",
342        "February",
343        "March",
344        "April",
345        "May",
346        "June",
347        "July",
348        "August",
349        "September",
350        "October",
351        "November",
352        "December",
353    };
354
355    static String en_US_MonthNames[] = {
356        "January",
357        "February",
358        "March",
359        "April",
360        "May",
361        "June",
362        "July",
363        "August",
364        "September",
365        "October",
366        "November",
367        "December",
368    };
369
370    static String en_CA_ShortMonthNames[] = {
371        "Jan",
372        "Feb",
373        "Mar",
374        "Apr",
375        "May",
376        "Jun",
377        "Jul",
378        "Aug",
379        "Sep",
380        "Oct",
381        "Nov",
382        "Dec",
383    };
384
385    static String fr_CA_ShortMonthNames[] = {
386        "janv.",
387        "f\u00E9vr.",
388        "mars",
389        "avr.",
390        "mai",
391        "juin",
392        "juil.",
393        "ao\u00FBt",
394        "sept.",
395        "oct.",
396        "nov.",
397        "d\u00E9c.",
398    };
399
400    static String zh_Hans_CN_ShortMonthNames[] = {
401        "\u4E00\u6708",
402        "\u4E8C\u6708",
403        "\u4E09\u6708",
404        "\u56DB\u6708",
405        "\u4E94\u6708",
406        "\u516D\u6708",
407        "\u4E03\u6708",
408        "\u516B\u6708",
409        "\u4E5D\u6708",
410        "\u5341\u6708",
411        "\u5341\u4E00\u6708",
412        "\u5341\u4E8C\u6708",
413    };
414
415    static String zh_CN_ShortMonthNames[] = {
416        "\u4E00\u6708",
417        "\u4E8C\u6708",
418        "\u4E09\u6708",
419        "\u56DB\u6708",
420        "\u4E94\u6708",
421        "\u516D\u6708",
422        "\u4E03\u6708",
423        "\u516B\u6708",
424        "\u4E5D\u6708",
425        "\u5341\u6708",
426        "\u5341\u4E00\u6708",
427        "\u5341\u4E8C\u6708",
428    };
429
430    static String zh_ShortMonthNames[] = {
431        "\u4E00\u6708",
432        "\u4E8C\u6708",
433        "\u4E09\u6708",
434        "\u56DB\u6708",
435        "\u4E94\u6708",
436        "\u516D\u6708",
437        "\u4E03\u6708",
438        "\u516B\u6708",
439        "\u4E5D\u6708",
440        "\u5341\u6708",
441        "\u5341\u4E00\u6708",
442        "\u5341\u4E8C\u6708",
443    };
444
445    static String en_ShortMonthNames[] = {
446        "Jan",
447        "Feb",
448        "Mar",
449        "Apr",
450        "May",
451        "Jun",
452        "Jul",
453        "Aug",
454        "Sep",
455        "Oct",
456        "Nov",
457        "Dec",
458    };
459
460    static String fr_FR_ShortMonthNames[] = {
461        "janv.",
462        "f\u00E9vr.",
463        "mars",
464        "avr.",
465        "mai",
466        "juin",
467        "juil.",
468        "ao\u00FBt",
469        "sept.",
470        "oct.",
471        "nov.",
472        "d\u00E9c.",
473    };
474
475   static String fr_ShortMonthNames[] = {
476        "janv.",
477        "f\u00E9vr.",
478        "mars",
479        "avr.",
480        "mai",
481        "juin",
482        "juil.",
483        "ao\u00FBt",
484        "sept.",
485        "oct.",
486        "nov.",
487        "d\u00E9c.",
488    };
489
490    static String de_ShortMonthNames[] = {
491        "Jan",
492        "Feb",
493        "Mrz",
494        "Apr",
495        "Mai",
496        "Jun",
497        "Jul",
498        "Aug",
499        "Sep",
500        "Okt",
501        "Nov",
502        "Dez",
503    };
504
505    static String de_DE_ShortMonthNames[] = {
506        "Jan",
507        "Feb",
508        "Mrz",
509        "Apr",
510        "Mai",
511        "Jun",
512        "Jul",
513        "Aug",
514        "Sep",
515        "Okt",
516        "Nov",
517        "Dez",
518    };
519
520    static String it_ShortMonthNames[] = {
521        "gen",
522        "feb",
523        "mar",
524        "apr",
525        "mag",
526        "giu",
527        "lug",
528        "ago",
529        "set",
530        "ott",
531        "nov",
532        "dic",
533    };
534
535    static String it_IT_ShortMonthNames[] = {
536        "gen",
537        "feb",
538        "mar",
539        "apr",
540        "mag",
541        "giu",
542        "lug",
543        "ago",
544        "set",
545        "ott",
546        "nov",
547        "dic",
548    };
549
550    static String ja_JP_ShortMonthNames[] = {
551        "1 \u6708",
552        "2 \u6708",
553        "3 \u6708",
554        "4 \u6708",
555        "5 \u6708",
556        "6 \u6708",
557        "7 \u6708",
558        "8 \u6708",
559        "9 \u6708",
560        "10 \u6708",
561        "11 \u6708",
562        "12 \u6708",
563    };
564
565    static String ja_ShortMonthNames[] = {
566        "1 \u6708",
567        "2 \u6708",
568        "3 \u6708",
569        "4 \u6708",
570        "5 \u6708",
571        "6 \u6708",
572        "7 \u6708",
573        "8 \u6708",
574        "9 \u6708",
575        "10 \u6708",
576        "11 \u6708",
577        "12 \u6708",
578    };
579
580    static String ko_KR_ShortMonthNames[] = {
581        "1\uC6D4",
582        "2\uC6D4",
583        "3\uC6D4",
584        "4\uC6D4",
585        "5\uC6D4",
586        "6\uC6D4",
587        "7\uC6D4",
588        "8\uC6D4",
589        "9\uC6D4",
590        "10\uC6D4",
591        "11\uC6D4",
592        "12\uC6D4",
593    };
594
595    static String ko_ShortMonthNames[] = {
596        "1\uC6D4",
597        "2\uC6D4",
598        "3\uC6D4",
599        "4\uC6D4",
600        "5\uC6D4",
601        "6\uC6D4",
602        "7\uC6D4",
603        "8\uC6D4",
604        "9\uC6D4",
605        "10\uC6D4",
606        "11\uC6D4",
607        "12\uC6D4",
608    };
609
610    static String zh_Hant_TW_ShortMonthNames[] = {
611        "\u4E00\u6708",
612        "\u4E8C\u6708",
613        "\u4E09\u6708",
614        "\u56DB\u6708",
615        "\u4E94\u6708",
616        "\u516D\u6708",
617        "\u4E03\u6708",
618        "\u516B\u6708",
619        "\u4E5D\u6708",
620        "\u5341\u6708",
621        "\u5341\u4E00\u6708",
622        "\u5341\u4E8C\u6708",
623    };
624
625    static String zh_TW_ShortMonthNames[] = {
626        "\u4E00\u6708",
627        "\u4E8C\u6708",
628        "\u4E09\u6708",
629        "\u56DB\u6708",
630        "\u4E94\u6708",
631        "\u516D\u6708",
632        "\u4E03\u6708",
633        "\u516B\u6708",
634        "\u4E5D\u6708",
635        "\u5341\u6708",
636        "\u5341\u4E00\u6708",
637        "\u5341\u4E8C\u6708",
638    };
639
640    static String en_GB_ShortMonthNames[] = {
641        "Jan",
642        "Feb",
643        "Mar",
644        "Apr",
645        "May",
646        "Jun",
647        "Jul",
648        "Aug",
649        "Sep",
650        "Oct",
651        "Nov",
652        "Dec",
653    };
654
655    static String en_US_ShortMonthNames[] = {
656        "Jan",
657        "Feb",
658        "Mar",
659        "Apr",
660        "May",
661        "Jun",
662        "Jul",
663        "Aug",
664        "Sep",
665        "Oct",
666        "Nov",
667        "Dec",
668    };
669
670    static {
671        cannedMonthNames.put("en_CA",      en_CA_MonthNames);
672        cannedMonthNames.put("fr_CA",      fr_CA_MonthNames);
673        cannedMonthNames.put("zh_Hans_CN", zh_Hans_CN_MonthNames);
674        cannedMonthNames.put("zh_CN",      zh_CN_MonthNames);
675        cannedMonthNames.put("zh",         zh_MonthNames);
676        cannedMonthNames.put("en",         en_MonthNames);
677        cannedMonthNames.put("fr_FR",      fr_FR_MonthNames);
678        cannedMonthNames.put("fr",         fr_MonthNames);
679        cannedMonthNames.put("de",         de_MonthNames);
680        cannedMonthNames.put("de_DE",      de_DE_MonthNames);
681        cannedMonthNames.put("it",         it_MonthNames);
682        cannedMonthNames.put("it_IT",      it_IT_MonthNames);
683        cannedMonthNames.put("ja_JP",      ja_JP_MonthNames);
684        cannedMonthNames.put("ja",         ja_MonthNames);
685        cannedMonthNames.put("ko_KR",      ko_KR_MonthNames);
686        cannedMonthNames.put("ko",         ko_MonthNames);
687        cannedMonthNames.put("zh_Hant_TW", zh_Hant_TW_MonthNames);
688        cannedMonthNames.put("zh_TW",      zh_TW_MonthNames);
689        cannedMonthNames.put("en_GB",      en_GB_MonthNames);
690        cannedMonthNames.put("en_US",      en_US_MonthNames);
691
692        cannedShortMonthNames.put("en_CA",      en_CA_ShortMonthNames);
693        cannedShortMonthNames.put("fr_CA",      fr_CA_ShortMonthNames);
694        cannedShortMonthNames.put("zh_Hans_CN", zh_Hans_CN_ShortMonthNames);
695        cannedShortMonthNames.put("zh_CN",      zh_CN_ShortMonthNames);
696        cannedShortMonthNames.put("zh",         zh_ShortMonthNames);
697        cannedShortMonthNames.put("en",         en_ShortMonthNames);
698        cannedShortMonthNames.put("fr_FR",      fr_FR_ShortMonthNames);
699        cannedShortMonthNames.put("fr",         fr_ShortMonthNames);
700        cannedShortMonthNames.put("de",         de_ShortMonthNames);
701        cannedShortMonthNames.put("de_DE",      de_DE_ShortMonthNames);
702        cannedShortMonthNames.put("it",         it_ShortMonthNames);
703        cannedShortMonthNames.put("it_IT",      it_IT_ShortMonthNames);
704        cannedShortMonthNames.put("ja_JP",      ja_JP_ShortMonthNames);
705        cannedShortMonthNames.put("ja",         ja_ShortMonthNames);
706        cannedShortMonthNames.put("ko_KR",      ko_KR_ShortMonthNames);
707        cannedShortMonthNames.put("ko",         ko_ShortMonthNames);
708        cannedShortMonthNames.put("zh_Hant_TW", zh_Hant_TW_ShortMonthNames);
709        cannedShortMonthNames.put("zh_TW",      zh_TW_ShortMonthNames);
710        cannedShortMonthNames.put("en_GB",      en_GB_ShortMonthNames);
711        cannedShortMonthNames.put("en_US",      en_US_ShortMonthNames);
712    }
713
714    private static DateFormatSymbols getCannedDateFormatSymbols(ULocale uloc)
715    {
716        DateFormatSymbols dfs =new DateFormatSymbols(GregorianCalendar.class, uloc);
717        String key = uloc.toString();
718
719        dfs.setMonths((String[]) cannedMonthNames.get(key));
720        dfs.setShortMonths((String[]) cannedShortMonthNames.get(key));
721
722        return dfs;
723    }
724
725    private static SimpleDateFormat getCannedSimpleDateFormat(String pattern, ULocale uloc)
726    {
727        DateFormatSymbols dfs = getCannedDateFormatSymbols(uloc);
728
729        // Force PT
730        TimeZone pt = TimeZone.getTimeZone("America/Los_Angeles");
731        SimpleDateFormat cannedSDF = new SimpleDateFormat(pattern, dfs, uloc);
732        cannedSDF.setTimeZone(pt);
733        return cannedSDF;
734    }
735
736    /*
737     * The serialized form of a normally created DecimalFormatSymbols object
738     * will have locale-specific data in it that might change from one version
739     * of ICU4J to another. To guard against this, we store the following canned
740     * data into the test objects we create.
741     */
742    static HashMap cannedDecimalFormatSymbols = new HashMap();
743
744    static String en_CA_StringSymbols[] = {
745        "$",
746        "E",
747        "\u221E",
748        "CAD",
749        "\uFFFD",
750        ".#,-.*;%\u2030+@0"
751    };
752
753    static String fr_CA_StringSymbols[] = {
754        "$",
755        "E",
756        "\u221E",
757        "CAD",
758        "\uFFFD",
759        ",#\u00A0-,*;%\u2030+@0"
760    };
761
762    static String zh_CN_StringSymbols[] = {
763        "\uFFE5",
764        "E",
765        "\u221E",
766        "CNY",
767        "\uFFFD",
768        ".#,-.*;%\u2030+@0"
769    };
770
771    static String zh_StringSymbols[] = {
772        "\u00A4",
773        "E",
774        "\u221E",
775        "XXX",
776        "\uFFFD",
777        ".#,-.*;%\u2030+@0"
778    };
779
780    static String en_StringSymbols[] = {
781        "\u00A4",
782        "E",
783        "\u221E",
784        "XXX",
785        "\uFFFD",
786        ".#,-.*;%\u2030+@0"
787    };
788
789    static String fr_FR_StringSymbols[] = {
790        "\u20AC",
791        "E",
792        "\u221E",
793        "EUR",
794        "\uFFFD",
795        ",#\u00A0-,*;%\u2030+@0"
796    };
797
798    static String fr_StringSymbols[] = {
799        "\u00A4",
800        "E",
801        "\u221E",
802        "XXX",
803        "\uFFFD",
804        ",#\u00A0-,*;%\u2030+@0"
805    };
806
807    static String de_StringSymbols[] = {
808        "\u00A4",
809        "E",
810        "\u221E",
811        "XXX",
812        "\uFFFD",
813        ",#.-,*;%\u2030+@0"
814    };
815
816    static String de_DE_StringSymbols[] = {
817        "\u20AC",
818        "E",
819        "\u221E",
820        "EUR",
821        "\uFFFD",
822        ",#.-,*;%\u2030+@0"
823    };
824
825    static String it_StringSymbols[] = {
826        "\u00A4",
827        "E",
828        "\u221E",
829        "XXX",
830        "\uFFFD",
831        ",#.-,*;%\u2030+@0"
832    };
833
834    static String it_IT_StringSymbols[] = {
835        "\u20AC",
836        "E",
837        "\u221E",
838        "EUR",
839        "\uFFFD",
840        ",#.-,*;%\u2030+@0"
841    };
842
843    static String ja_JP_StringSymbols[] = {
844        "\uFFE5",
845        "E",
846        "\u221E",
847        "JPY",
848        "\uFFFD",
849        ".#,-.*;%\u2030+@0"
850    };
851
852    static String ja_StringSymbols[] = {
853        "\u00A4",
854        "E",
855        "\u221E",
856        "XXX",
857        "\uFFFD",
858        ".#,-.*;%\u2030+@0"
859    };
860
861    static String ko_KR_StringSymbols[] = {
862        "\uFFE6",
863        "E",
864        "\u221E",
865        "KRW",
866        "\uFFFD",
867        ".#,-.*;%\u2030+@0"
868    };
869
870    static String ko_StringSymbols[] = {
871        "\u00A4",
872        "E",
873        "\u221E",
874        "XXX",
875        "\uFFFD",
876        ".#,-.*;%\u2030+@0"
877    };
878
879    static String zh_Hans_CN_StringSymbols[] = {
880        "\uFFE5",
881        "E",
882        "\u221E",
883        "CNY",
884        "\uFFFD",
885        ".#,-.*;%\u2030+@0"
886    };
887
888    static String zh_Hant_TW_StringSymbols[] = {
889        "NT$",
890        "E",
891        "\u221E",
892        "TWD",
893        "\uFFFD",
894        ".#,-.*;%\u2030+@0"
895    };
896
897    static String zh_TW_StringSymbols[] = {
898        "NT$",
899        "E",
900        "\u221E",
901        "TWD",
902        "\uFFFD",
903        ".#,-.*;%\u2030+@0"
904    };
905
906    static String en_GB_StringSymbols[] = {
907        "\u00A3",
908        "E",
909        "\u221E",
910        "GBP",
911        "\uFFFD",
912        ".#,-.*;%\u2030+@0"
913    };
914
915    static String en_US_StringSymbols[] = {
916        "$",
917        "E",
918        "\u221E",
919        "USD",
920        "\uFFFD",
921        ".#,-.*;%\u2030+@0"
922    };
923
924    static {
925        cannedDecimalFormatSymbols.put("en_CA",      en_CA_StringSymbols);
926        cannedDecimalFormatSymbols.put("fr_CA",      fr_CA_StringSymbols);
927        cannedDecimalFormatSymbols.put("zh_CN",      zh_CN_StringSymbols);
928        cannedDecimalFormatSymbols.put("zh",         zh_StringSymbols);
929        cannedDecimalFormatSymbols.put("en",         en_StringSymbols);
930        cannedDecimalFormatSymbols.put("fr_FR",      fr_FR_StringSymbols);
931        cannedDecimalFormatSymbols.put("fr",         fr_StringSymbols);
932        cannedDecimalFormatSymbols.put("de",         de_StringSymbols);
933        cannedDecimalFormatSymbols.put("de_DE",      de_DE_StringSymbols);
934        cannedDecimalFormatSymbols.put("it",         it_StringSymbols);
935        cannedDecimalFormatSymbols.put("it_IT",      it_IT_StringSymbols);
936        cannedDecimalFormatSymbols.put("ja_JP",      ja_JP_StringSymbols);
937        cannedDecimalFormatSymbols.put("ja",         ja_StringSymbols);
938        cannedDecimalFormatSymbols.put("ko_KR",      ko_KR_StringSymbols);
939        cannedDecimalFormatSymbols.put("ko",         ko_StringSymbols);
940        cannedDecimalFormatSymbols.put("zh_Hans_CN", zh_Hans_CN_StringSymbols);
941        cannedDecimalFormatSymbols.put("zh_Hant_TW", zh_Hant_TW_StringSymbols);
942        cannedDecimalFormatSymbols.put("zh_TW",      zh_TW_StringSymbols);
943        cannedDecimalFormatSymbols.put("en_GB",      en_GB_StringSymbols);
944        cannedDecimalFormatSymbols.put("en_US",      en_US_StringSymbols);
945    }
946
947    private static char[] getCharSymbols(DecimalFormatSymbols dfs)
948    {
949        char symbols[] = {
950            dfs.getDecimalSeparator(),
951            dfs.getDigit(),
952            dfs.getGroupingSeparator(),
953            dfs.getMinusSign(),
954            dfs.getMonetaryDecimalSeparator(),
955            dfs.getPadEscape(),
956            dfs.getPatternSeparator(),
957            dfs.getPercent(),
958            dfs.getPerMill(),
959            dfs.getPlusSign(),
960            dfs.getSignificantDigit(),
961            dfs.getZeroDigit()
962        };
963
964        return symbols;
965    }
966
967    private static void setCharSymbols(DecimalFormatSymbols dfs, char symbols[])
968    {
969        dfs.setDecimalSeparator(symbols[0]);
970        dfs.setDigit(symbols[1]);
971        dfs.setGroupingSeparator(symbols[2]);
972        dfs.setMinusSign(symbols[3]);
973        dfs.setMonetaryDecimalSeparator(symbols[4]);
974        dfs.setPadEscape(symbols[5]);
975        dfs.setPatternSeparator(symbols[6]);
976        dfs.setPercent(symbols[7]);
977        dfs.setPerMill(symbols[8]);
978        dfs.setPlusSign(symbols[9]);
979        dfs.setSignificantDigit(symbols[10]);
980        dfs.setZeroDigit(symbols[11]);
981    }
982
983    private static String[] getStringSymbols(DecimalFormatSymbols dfs)
984    {
985        String symbols[] = {
986            dfs.getCurrencySymbol(),
987            dfs.getExponentSeparator(),
988            dfs.getInfinity(),
989            dfs.getInternationalCurrencySymbol(),
990            dfs.getNaN()
991        };
992
993        return symbols;
994    }
995
996    private static DecimalFormatSymbols getCannedDecimalFormatSymbols(ULocale uloc)
997    {
998        DecimalFormatSymbols dfs = new DecimalFormatSymbols(uloc);
999
1000        setSymbols(dfs, (String[]) cannedDecimalFormatSymbols.get(uloc.toString()));
1001
1002        return dfs;
1003    }
1004
1005    private static DecimalFormat getCannedDecimalFormat(String pattern, ULocale uloc)
1006    {
1007        return new DecimalFormat(pattern, getCannedDecimalFormatSymbols(uloc));
1008    }
1009
1010    private static void setSymbols(DecimalFormatSymbols dfs, String symbols[])
1011    {
1012        dfs.setCurrencySymbol(symbols[0]);
1013        dfs.setExponentSeparator(symbols[1]);
1014        dfs.setInfinity(symbols[2]);
1015        dfs.setInternationalCurrencySymbol(symbols[3]);
1016        dfs.setNaN(symbols[4]);
1017
1018        setCharSymbols(dfs, symbols[5].toCharArray());
1019    }
1020
1021    public static class RelativeDateFormatHandler implements SerializableTestUtility.Handler
1022    {
1023        @Override
1024        public Object[] getTestObjects()
1025        {
1026            DateFormat formats[] = {
1027                    DateFormat.getDateInstance(DateFormat.RELATIVE_LONG,new ULocale("en")),
1028                    DateFormat.getDateInstance(DateFormat.RELATIVE_SHORT,new ULocale("ru")),
1029            };
1030
1031            return formats;
1032        }
1033
1034        @Override
1035        public boolean hasSameBehavior(Object a, Object b) {
1036            DateFormat da = (DateFormat)a;
1037            DateFormat db = (DateFormat)b;
1038
1039            Date d = new Date(System.currentTimeMillis());
1040            return da.format(d).equals(db.format(d));
1041        }
1042    }
1043
1044    public static class BasicDurationFormatHandler implements SerializableTestUtility.Handler
1045    {
1046        @Override
1047        public Object[] getTestObjects()
1048        {
1049            DurationFormat formats[] = {
1050                    DurationFormat.getInstance(new ULocale("en"))
1051
1052            };
1053
1054            return formats;
1055        }
1056
1057        //TODO: Revisit this after 3.8
1058        @Override
1059        public boolean hasSameBehavior(Object a, Object b) {
1060            //DurationFormat da = (DurationFormat)a;
1061            //DurationFormat db = (DurationFormat)b;
1062
1063            //Date d = new Date(12345);
1064            //System.err.println("Warning: BasicDurationFormat test is being skipped for now.");
1065            return true;
1066            //return da.format(d).equals(db.format(d));
1067        }
1068    }
1069
1070    public static class NumberFormatHandler implements SerializableTestUtility.Handler
1071    {
1072        @Override
1073        public Object[] getTestObjects()
1074        {
1075            ULocale uloc = ULocale.forLocale(Locale.US);
1076            NumberFormat formats[] = {
1077                /*
1078                 * The code below was used to genereate the
1079                 * serialized NumberFormat objects in ICU 3.6:
1080                 *
1081                 *    NumberFormat.getInstance(Locale.US)
1082                 *    NumberFormat.getCurrencyInstance(Locale.US)
1083                 *    NumberFormat.getPercentInstance(Locale.US)
1084                 *    NumberFormat.getScientificInstance(Locale.US)
1085                 *
1086                 * Because the locale data might now be different that it was in
1087                 * ICU 3.6, the only way to guarantee that the object we generate
1088                 * will match the ICU 3.6 objects is to generate DecimalFormat objects
1089                 * that use the same patterns and DecimalFormatSymbols that
1090                 * were used in ICU 3.6.
1091                 */
1092                getCannedDecimalFormat("#,##0.###", uloc),
1093                getCannedDecimalFormat("\u00A4#,##0.00;(\u00A4#,##0.00)", uloc),
1094                getCannedDecimalFormat("#,##0%", uloc),
1095                getCannedDecimalFormat("#E0", uloc)
1096
1097            };
1098
1099            return formats;
1100        }
1101
1102        @Override
1103        public boolean hasSameBehavior(Object a, Object b)
1104        {
1105            NumberFormat format_a = (NumberFormat) a;
1106            NumberFormat format_b = (NumberFormat) b;
1107            double number = 1234.56;
1108
1109            return format_a.format(number).equals(format_b.format(number));
1110        }
1111    }
1112
1113    public static class DecimalFormatHandler extends NumberFormatHandler
1114    {
1115        @Override
1116        public Object[] getTestObjects()
1117        {
1118            Locale locales[] = SerializableTestUtility.getLocales();
1119            DecimalFormat formats[] = new DecimalFormat[locales.length];
1120
1121            for (int i = 0; i < locales.length; i += 1) {
1122                ULocale uloc = ULocale.forLocale(locales[i]);
1123
1124                formats[i] = getCannedDecimalFormat("#,##0.###", uloc);
1125            }
1126            if (formats[0] != null) {
1127                // Ticket#6449
1128                // Once formatToCharacterIterator is called, NumberFormat.Field
1129                // instances are created and stored in the private List field.
1130                // NumberForamt.Field is not a serializable, so serializing such
1131                // instances end up NotSerializableException.  This problem was
1132                // reproduced since formatToCharacterIterator was introduced,
1133                // up to ICU 4.0.
1134
1135                AttributedCharacterIterator aci = formats[0].formatToCharacterIterator(new Double(12.345D));
1136                if (aci == null) {} // NOP - for resolving 'Unused local variable' warning.
1137            }
1138            return formats;
1139        }
1140    }
1141
1142    public static class RuleBasedNumberFormatHandler extends NumberFormatHandler
1143    {
1144        // default rules, from root.txt
1145        String xx_SpelloutRules = "=#,##0.######=;\n";
1146        String xx_OrdinalRules = "=#,##0=;\n";
1147        String xx_DurationRules = "=#,##0=;\n";
1148
1149        String ja_spelloutRules =
1150            "%financial:\n" +
1151                "\u96f6; \u58f1; \u5f10; \u53c2; \u56db; \u4f0d; \u516d; \u4e03; \u516b; \u4e5d;\n" +
1152                "\u62fe[>>];\n" +
1153                "20: <<\u62fe[>>];\n" +
1154                "100: <<\u767e[>>];\n" +
1155                "1000: <<\u5343[>>];\n" +
1156                "10,000: <<\u4e07[>>];\n" +
1157                "100,000,000: <<\u5104[>>];\n" +
1158                "1,000,000,000,000: <<\u5146[>>];\n" +
1159                "10,000,000,000,000,000: =#,##0=;\n" +
1160
1161            "%traditional:\n" +
1162                "\u96f6; \u4e00; \u4e8c; \u4e09; \u56db; \u4e94; \u516d; \u4e03; \u516b; \u4e5d;\n" +
1163                "\u5341[>>];\n" +
1164                "20: <<\u5341[>>];\n" +
1165                "100: <<\u767e[>>];\n" +
1166                "1000: <<\u5343[>>];\n" +
1167                "10,000: <<\u4e07[>>];\n" +
1168                "100,000,000: <<\u5104[>>];\n" +
1169                "1,000,000,000,000: <<\u5146[>>];\n" +
1170                "10,000,000,000,000,000: =#,##0=;";
1171
1172        String en_SpelloutRules =
1173            // This rule set shows the normal simple formatting rules for English
1174            "%simplified:\n" +
1175                   // negative number rule.  This rule is used to format negative
1176                   // numbers.  The result of formatting the number's absolute
1177                   // value is placed where the >> is.
1178                "-x: minus >>;\n" +
1179                   // faction rule.  This rule is used for formatting numbers
1180                   // with fractional parts.  The result of formatting the
1181                   // number's integral part is substituted for the <<, and
1182                   // the result of formatting the number's fractional part
1183                   // (one digit at a time, e.g., 0.123 is "zero point one two
1184                   // three") replaces the >>.
1185                "x.x: << point >>;\n" +
1186                   // the rules for the values from 0 to 19 are simply the
1187                   // words for those numbers
1188                "zero; one; two; three; four; five; six; seven; eight; nine;\n" +
1189                "ten; eleven; twelve; thirteen; fourteen; fifteen; sixteen;\n" +
1190                    "seventeen; eighteen; nineteen;\n" +
1191                   // beginning at 20, we use the >> to mark the position where
1192                   // the result of formatting the number's ones digit.  Thus,
1193                   // we only need a new rule at every multiple of 10.  Text in
1194                   // backets is omitted if the value being formatted is an
1195                   // even multiple of 10.
1196                "20: twenty[->>];\n" +
1197                "30: thirty[->>];\n" +
1198                "40: forty[->>];\n" +
1199                "50: fifty[->>];\n" +
1200                "60: sixty[->>];\n" +
1201                "70: seventy[->>];\n" +
1202                "80: eighty[->>];\n" +
1203                "90: ninety[->>];\n" +
1204                   // beginning at 100, we can use << to mark the position where
1205                   // the result of formatting the multiple of 100 is to be
1206                   // inserted.  Notice also that the meaning of >> has shifted:
1207                   // here, it refers to both the ones place and the tens place.
1208                   // The meanings of the << and >> tokens depend on the base value
1209                   // of the rule.  A rule's divisor is (usually) the highest
1210                   // power of 10 that is less than or equal to the rule's base
1211                   // value.  The value being formatted is divided by the rule's
1212                   // divisor, and the integral quotient is used to get the text
1213                   // for <<, while the remainder is used to produce the text
1214                   // for >>.  Again, text in brackets is omitted if the value
1215                   // being formatted is an even multiple of the rule's divisor
1216                   // (in this case, an even multiple of 100)
1217                "100: << hundred[ >>];\n" +
1218                   // The rules for the higher numbers work the same way as the
1219                   // rule for 100: Again, the << and >> tokens depend on the
1220                   // rule's divisor, which for all these rules is also the rule's
1221                   // base value.  To group by thousand, we simply don't have any
1222                   // rules between 1,000 and 1,000,000.
1223                "1000: << thousand[ >>];\n" +
1224                "1,000,000: << million[ >>];\n" +
1225                "1,000,000,000: << billion[ >>];\n" +
1226                "1,000,000,000,000: << trillion[ >>];\n" +
1227                   // overflow rule.  This rule specifies that values of a
1228                   // quadrillion or more are shown in numerals rather than words.
1229                   // The == token means to format (with new rules) the value
1230                   // being formatted by this rule and place the result where
1231                   // the == is.  The #,##0 inside the == signs is a
1232                   // DecimalFormat pattern.  It specifies that the value should
1233                   // be formatted with a DecimalFormat object, and that it
1234                   // should be formatted with no decimal places, at least one
1235                   // digit, and a thousands separator.
1236                "1,000,000,000,000,000: =#,##0=;\n" +
1237
1238            // %default is a more elaborate form of %simplified;  It is basically
1239            // the same, except that it introduces "and" before the ones digit
1240            // when appropriate (basically, between the tens and ones digits) and
1241            // separates the thousands groups with commas in values over 100,000.
1242            "%default:\n" +
1243                   // negative-number and fraction rules.  These are the same
1244                   // as those for %simplified, but have to be stated here too
1245                   // because this is an entry point
1246                "-x: minus >>;\n" +
1247                "x.x: << point >>;\n" +
1248                   // just use %simplified for values below 100
1249                "=%simplified=;\n" +
1250                   // for values from 100 to 9,999 use %%and to decide whether or
1251                   // not to interpose the "and"
1252                "100: << hundred[ >%%and>];\n" +
1253                "1000: << thousand[ >%%and>];\n" +
1254                   // for values of 100,000 and up, use %%commas to interpose the
1255                   // commas in the right places (and also to interpose the "and")
1256                "100,000>>: << thousand[>%%commas>];\n" +
1257                "1,000,000: << million[>%%commas>];\n" +
1258                "1,000,000,000: << billion[>%%commas>];\n" +
1259                "1,000,000,000,000: << trillion[>%%commas>];\n" +
1260                "1,000,000,000,000,000: =#,##0=;\n" +
1261            // if the value passed to this rule set is greater than 100, don't
1262            // add the "and"; if it's less than 100, add "and" before the last
1263            // digits
1264            "%%and:\n" +
1265                "and =%default=;\n" +
1266                "100: =%default=;\n" +
1267            // this rule set is used to place the commas
1268            "%%commas:\n" +
1269                   // for values below 100, add "and" (the apostrophe at the
1270                   // beginning is ignored, but causes the space that follows it
1271                   // to be significant: this is necessary because the rules
1272                   // calling %%commas don't put a space before it)
1273                "' and =%default=;\n" +
1274                   // put a comma after the thousands (or whatever preceded the
1275                   // hundreds)
1276                "100: , =%default=;\n" +
1277                   // put a comma after the millions (or whatever precedes the
1278                   // thousands)
1279                "1000: , <%default< thousand, >%default>;\n" +
1280                   // and so on...
1281                "1,000,000: , =%default=;" +
1282            // %%lenient-parse isn't really a set of number formatting rules;
1283            // it's a set of collation rules.  Lenient-parse mode uses a Collator
1284            // object to compare fragments of the text being parsed to the text
1285            // in the rules, allowing more leeway in the matching text.  This set
1286            // of rules tells the formatter to ignore commas when parsing (it
1287            // already ignores spaces, which is why we refer to the space; it also
1288            // ignores hyphens, making "twenty one" and "twenty-one" parse
1289            // identically)
1290            "%%lenient-parse:\n" +
1291            //                "& ' ' , ',' ;\n" +
1292            "   &\u0000 << ' ' << ',' << '-'; \n";
1293
1294        String en_GB_SpelloutRules =
1295            "%simplified:\n" +
1296            "-x: minus >>;\n" +
1297            "x.x: << point >>;\n" +
1298            "zero; one; two; three; four; five; six; seven; eight; nine;\n" +
1299            "ten; eleven; twelve; thirteen; fourteen; fifteen; sixteen;\n" +
1300            "    seventeen; eighteen; nineteen;\n" +
1301            "20: twenty[->>];\n" +
1302            "30: thirty[->>];\n" +
1303            "40: forty[->>];\n" +
1304            "50: fifty[->>];\n" +
1305            "60: sixty[->>];\n" +
1306            "70: seventy[->>];\n" +
1307            "80: eighty[->>];\n" +
1308            "90: ninety[->>];\n" +
1309            "100: << hundred[ >>];\n" +
1310            "1000: << thousand[ >>];\n" +
1311            "1,000,000: << million[ >>];\n" +
1312            "1,000,000,000,000: << billion[ >>];\n" +
1313            "1,000,000,000,000,000: =#,##0=;\n" +
1314        "%default:\n" +
1315            "-x: minus >>;\n" +
1316            "x.x: << point >>;\n" +
1317            "=%simplified=;\n" +
1318            "100: << hundred[ >%%and>];\n" +
1319            "1000: << thousand[ >%%and>];\n" +
1320            "100,000>>: << thousand[>%%commas>];\n" +
1321            "1,000,000: << million[>%%commas>];\n" +
1322            "1,000,000,000,000: << billion[>%%commas>];\n" +
1323            "1,000,000,000,000,000: =#,##0=;\n" +
1324        "%%and:\n" +
1325            "and =%default=;\n" +
1326            "100: =%default=;\n" +
1327        "%%commas:\n" +
1328            "' and =%default=;\n" +
1329            "100: , =%default=;\n" +
1330            "1000: , <%default< thousand, >%default>;\n" +
1331            "1,000,000: , =%default=;" +
1332        "%%lenient-parse:\n" +
1333            "& ' ' , ',' ;\n";
1334
1335        String fr_SpelloutRules =
1336            // the main rule set
1337            "%main:\n" +
1338                "-x: moins >>;\n" +
1339                "x.x: << virgule >>;\n" +
1340                   // words for numbers from 0 to 10
1341                "z\u00e9ro; un; deux; trois; quatre; cinq; six; sept; huit; neuf;\n" +
1342                "dix; onze; douze; treize; quatorze; quinze; seize;\n" +
1343                "    dix-sept; dix-huit; dix-neuf;\n" +
1344                   // ords for the multiples of 10: %%alt-ones inserts "et"
1345                   // when needed
1346                "20: vingt[->%%alt-ones>];\n" +
1347                "30: trente[->%%alt-ones>];\n" +
1348                "40: quarante[->%%alt-ones>];\n" +
1349                "50: cinquante[->%%alt-ones>];\n" +
1350                   // rule for 60.  The /20 causes this rule's multiplier to be
1351                   // 20 rather than 10, allowinhg us to recurse for all values
1352                   // from 60 to 79...
1353                "60/20: soixante[->%%alt-ones>];\n" +
1354                   // ...except for 71, which must be special-cased
1355                "71: soixante et onze;\n" +
1356                   // at 72, we have to repeat the rule for 60 to get us to 79
1357                "72/20: soixante->%%alt-ones>;\n" +
1358                   // at 80, we state a new rule with the phrase for 80.  Since
1359                   // it changes form when there's a ones digit, we need a second
1360                   // rule at 81.  This rule also includes "/20," allowing it to
1361                   // be used correctly for all values up to 99
1362                "80: quatre-vingts; 81/20: quatre-vingt->>;\n" +
1363                   // "cent" becomes plural when preceded by a multiplier, and
1364                   // the multiplier is omitted from the singular form
1365                "100: cent[ >>];\n" +
1366                "200: << cents[ >>];\n" +
1367                "1000: mille[ >>];\n" +
1368                   // values from 1,100 to 1,199 are rendered as "onze cents..."
1369                   // instead of "mille cent..."  The > after "1000" decreases
1370                   // the rule's exponent, causing its multiplier to be 100 instead
1371                   // of 1,000.  This prevents us from getting "onze cents cent
1372                   // vingt-deux" ("eleven hundred one hundred twenty-two").
1373                "1100>: onze cents[ >>];\n" +
1374                   // at 1,200, we go back to formating in thousands, so we
1375                   // repeat the rule for 1,000
1376                "1200: mille >>;\n" +
1377                   // at 2,000, the multiplier is added
1378                "2000: << mille[ >>];\n" +
1379                "1,000,000: << million[ >>];\n" +
1380                "1,000,000,000: << milliard[ >>];\n" +
1381                "1,000,000,000,000: << billion[ >>];\n" +
1382                "1,000,000,000,000,000: =#,##0=;\n" +
1383            // %%alt-ones is used to insert "et" when the ones digit is 1
1384            "%%alt-ones:\n" +
1385                "; et-un; =%main=;\n" +
1386            "%%lenient-parse:\n" +
1387                "&\u0000 << ' ' << ',' << '-';\n";
1388
1389        String de_SpelloutRules =
1390            // 1 is "eins" when by itself, but turns into "ein" in most
1391            // combinations
1392            "%alt-ones:\n" +
1393                "-x: minus >>;\n" +
1394                "x.x: << komma >>;\n" +
1395                "null; eins; =%%main=;\n" +
1396            "%%main:\n" +
1397                   // words for numbers from 0 to 12.  Notice that the values
1398                   // from 13 to 19 can derived algorithmically, unlike in most
1399                   // other languages
1400                "null; ein; zwei; drei; vier; f\u00fcnf; sechs; sieben; acht; neun;\n" +
1401                "zehn; elf; zw\u00f6lf; >>zehn;\n" +
1402                   // rules for the multiples of 10.  Notice that the ones digit
1403                   // goes on the front
1404                "20: [>>und]zwanzig;\n" +
1405                "30: [>>und]drei\u00dfig;\n" +
1406                "40: [>>und]vierzig;\n" +
1407                "50: [>>und]f\u00fcnfzig;\n" +
1408                "60: [>>und]sechzig;\n" +
1409                "70: [>>und]siebzig;\n" +
1410                "80: [>>und]achtzig;\n" +
1411                "90: [>>und]neunzig;\n" +
1412                "100: hundert[>%alt-ones>];\n" +
1413                "200: <<hundert[>%alt-ones>];\n" +
1414                "1000: tausend[>%alt-ones>];\n" +
1415                "2000: <<tausend[>%alt-ones>];\n" +
1416                "1,000,000: eine Million[ >%alt-ones>];\n" +
1417                "2,000,000: << Millionen[ >%alt-ones>];\n" +
1418                "1,000,000,000: eine Milliarde[ >%alt-ones>];\n" +
1419                "2,000,000,000: << Milliarden[ >%alt-ones>];\n" +
1420                "1,000,000,000,000: eine Billion[ >%alt-ones>];\n" +
1421                "2,000,000,000,000: << Billionen[ >%alt-ones>];\n" +
1422                "1,000,000,000,000,000: =#,##0=;" +
1423            "%%lenient-parse:\n" +
1424                "&\u0000 << ' ' << '-'\n" +
1425                "& ae , \u00e4 & ae , \u00c4\n" +
1426                "& oe , \u00f6 & oe , \u00d6\n" +
1427                "& ue , \u00fc & ue , \u00dc\n";
1428
1429        String it_SpelloutRules =
1430            // main rule set.  Follows the patterns of the preceding rule sets,
1431            // except that the final vowel is omitted from words ending in
1432            // vowels when they are followed by another word; instead, we have
1433            // separate rule sets that are identical to this one, except that
1434            // all the words that don't begin with a vowel have a vowel tacked
1435            // onto them at the front.  A word ending in a vowel calls a
1436            // substitution that will supply that vowel, unless that vowel is to
1437            // be elided.
1438            "%main:\n" +
1439                "-x: meno >>;\n" +
1440                "x.x: << virgola >>;\n" +
1441                "zero; uno; due; tre; quattro; cinque; sei; sette; otto; nove;\n" +
1442                "dieci; undici; dodici; tredici; quattordici; quindici; sedici;\n" +
1443                "    diciasette; diciotto; diciannove;\n" +
1444                "20: venti; vent>%%with-i>;\n" +
1445                "30: trenta; trent>%%with-i>;\n" +
1446                "40: quaranta; quarant>%%with-a>;\n" +
1447                "50: cinquanta; cinquant>%%with-a>;\n" +
1448                "60: sessanta; sessant>%%with-a>;\n" +
1449                "70: settanta; settant>%%with-a>;\n" +
1450                "80: ottanta; ottant>%%with-a>;\n" +
1451                "90: novanta; novant>%%with-a>;\n" +
1452                "100: cento; cent[>%%with-o>];\n" +
1453                "200: <<cento; <<cent[>%%with-o>];\n" +
1454                "1000: mille; mill[>%%with-i>];\n" +
1455                "2000: <<mila; <<mil[>%%with-a>];\n" +
1456                "100,000>>: <<mila[ >>];\n" +
1457                "1,000,000: =#,##0= (incomplete data);\n" +
1458            "%%with-a:\n" +
1459                "azero; uno; adue; atre; aquattro; acinque; asei; asette; otto; anove;\n" +
1460                "adieci; undici; adodici; atredici; aquattordici; aquindici; asedici;\n" +
1461                "    adiciasette; adiciotto; adiciannove;\n" +
1462                "20: aventi; avent>%%with-i>;\n" +
1463                "30: atrenta; atrent>%%with-i>;\n" +
1464                "40: aquaranta; aquarant>%%with-a>;\n" +
1465                "50: acinquanta; acinquant>%%with-a>;\n" +
1466                "60: asessanta; asessant>%%with-a>;\n" +
1467                "70: asettanta; asettant>%%with-a>;\n" +
1468                "80: ottanta; ottant>%%with-a>;\n" +
1469                "90: anovanta; anovant>%%with-a>;\n" +
1470                "100: acento; acent[>%%with-o>];\n" +
1471                "200: <%%with-a<cento; <%%with-a<cent[>%%with-o>];\n" +
1472                "1000: amille; amill[>%%with-i>];\n" +
1473                "2000: <%%with-a<mila; <%%with-a<mil[>%%with-a>];\n" +
1474                "100,000: =%main=;\n" +
1475            "%%with-i:\n" +
1476                "izero; uno; idue; itre; iquattro; icinque; isei; isette; otto; inove;\n" +
1477                "idieci; undici; idodici; itredici; iquattordici; iquindici; isedici;\n" +
1478                "    idiciasette; idiciotto; idiciannove;\n" +
1479                "20: iventi; ivent>%%with-i>;\n" +
1480                "30: itrenta; itrent>%%with-i>;\n" +
1481                "40: iquaranta; iquarant>%%with-a>;\n" +
1482                "50: icinquanta; icinquant>%%with-a>;\n" +
1483                "60: isessanta; isessant>%%with-a>;\n" +
1484                "70: isettanta; isettant>%%with-a>;\n" +
1485                "80: ottanta; ottant>%%with-a>;\n" +
1486                "90: inovanta; inovant>%%with-a>;\n" +
1487                "100: icento; icent[>%%with-o>];\n" +
1488                "200: <%%with-i<cento; <%%with-i<cent[>%%with-o>];\n" +
1489                "1000: imille; imill[>%%with-i>];\n" +
1490                "2000: <%%with-i<mila; <%%with-i<mil[>%%with-a>];\n" +
1491                "100,000: =%main=;\n" +
1492            "%%with-o:\n" +
1493                "ozero; uno; odue; otre; oquattro; ocinque; osei; osette; otto; onove;\n" +
1494                "odieci; undici; ododici; otredici; oquattordici; oquindici; osedici;\n" +
1495                "    odiciasette; odiciotto; odiciannove;\n" +
1496                "20: oventi; ovent>%%with-i>;\n" +
1497                "30: otrenta; otrent>%%with-i>;\n" +
1498                "40: oquaranta; oquarant>%%with-a>;\n" +
1499                "50: ocinquanta; ocinquant>%%with-a>;\n" +
1500                "60: osessanta; osessant>%%with-a>;\n" +
1501                "70: osettanta; osettant>%%with-a>;\n" +
1502                "80: ottanta; ottant>%%with-a>;\n" +
1503                "90: onovanta; onovant>%%with-a>;\n" +
1504                "100: ocento; ocent[>%%with-o>];\n" +
1505                "200: <%%with-o<cento; <%%with-o<cent[>%%with-o>];\n" +
1506                "1000: omille; omill[>%%with-i>];\n" +
1507                "2000: <%%with-o<mila; <%%with-o<mil[>%%with-a>];\n" +
1508                "100,000: =%main=;\n" ;
1509
1510        String en_OrdinalRules =
1511            // this rule set formats the numeral and calls %%abbrev to
1512            // supply the abbreviation
1513            "%main:\n" +
1514                "=#,##0==%%abbrev=;\n" +
1515            // this rule set supplies the abbreviation
1516            "%%abbrev:\n" +
1517                   // the abbreviations.  Everything from 4 to 19 ends in "th"
1518                "th; st; nd; rd; th;\n" +
1519                   // at 20, we begin repeating the cycle every 10 (13 is "13th",
1520                   // but 23 and 33 are "23rd" and "33rd")  We do this by
1521                   // ignoring all bug the ones digit in selecting the abbreviation
1522                "20: >>;\n" +
1523                   // at 100, we repeat the whole cycle by considering only the
1524                   // tens and ones digits in picking an abbreviation
1525                "100: >>;\n";
1526
1527        String en_DurationRules =
1528            // main rule set for formatting with words
1529            "%with-words:\n" +
1530                   // take care of singular and plural forms of "second"
1531                "0 seconds; 1 second; =0= seconds;\n" +
1532                   // use %%min to format values greater than 60 seconds
1533                "60/60: <%%min<[, >>];\n" +
1534                   // use %%hr to format values greater than 3,600 seconds
1535                   // (the ">>>" below causes us to see the number of minutes
1536                   // when when there are zero minutes)
1537                "3600/60: <%%hr<[, >>>];\n" +
1538            // this rule set takes care of the singular and plural forms
1539            // of "minute"
1540            "%%min:\n" +
1541                "0 minutes; 1 minute; =0= minutes;\n" +
1542            // this rule set takes care of the singular and plural forms
1543            // of "hour"
1544            "%%hr:\n" +
1545                "0 hours; 1 hour; =0= hours;\n" +
1546
1547            // main rule set for formatting in numerals
1548            "%in-numerals:\n" +
1549                   // values below 60 seconds are shown with "sec."
1550                "=0= sec.;\n" +
1551                   // higher values are shown with colons: %%min-sec is used for
1552                   // values below 3,600 seconds...
1553                "60: =%%min-sec=;\n" +
1554                   // ...and %%hr-min-sec is used for values of 3,600 seconds
1555                   // and above
1556                "3600: =%%hr-min-sec=;\n" +
1557            // this rule causes values of less than 10 minutes to show without
1558            // a leading zero
1559            "%%min-sec:\n" +
1560                "0: :=00=;\n" +
1561                "60/60: <0<>>;\n" +
1562            // this rule set is used for values of 3,600 or more.  Minutes are always
1563            // shown, and always shown with two digits
1564            "%%hr-min-sec:\n" +
1565                "0: :=00=;\n" +
1566                "60/60: <00<>>;\n" +
1567                "3600/60: <#,##0<:>>>;\n" +
1568            // the lenient-parse rules allow several different characters to be used
1569            // as delimiters between hours, minutes, and seconds
1570            "%%lenient-parse:\n" +
1571                "& ':' = '.' = ' ' = '-';\n";
1572
1573            HashMap cannedData = new HashMap();
1574
1575        {
1576            cannedData.put("en_CA/SpelloutRules",      en_SpelloutRules);
1577            cannedData.put("en_CA/OrdinalRules",       en_OrdinalRules);
1578            cannedData.put("en_CA/DurationRules",      en_DurationRules);
1579
1580            cannedData.put("fr_CA/SpelloutRules",      fr_SpelloutRules);
1581            cannedData.put("fr_CA/OrdinalRules",       xx_OrdinalRules);
1582            cannedData.put("fr_CA/DurationRules",      xx_DurationRules);
1583
1584            cannedData.put("zh_CN/SpelloutRules",      en_SpelloutRules);
1585            cannedData.put("zh_CN/OrdinalRules",       en_OrdinalRules);
1586            cannedData.put("zh_CH/DurationRules",      xx_DurationRules);
1587
1588            cannedData.put("zh/SpelloutRules",         en_SpelloutRules);
1589            cannedData.put("zh/OrdinalRules",          en_OrdinalRules);
1590            cannedData.put("zh_DurationRules",         xx_DurationRules);
1591
1592            cannedData.put("en/SpelloutRules",         en_SpelloutRules);
1593            cannedData.put("en/OrdinalRules",          en_OrdinalRules);
1594            cannedData.put("en/DurationRules",         en_DurationRules);
1595
1596            cannedData.put("fr_FR/SpelloutRules",      fr_SpelloutRules);
1597            cannedData.put("fr_FR/OrdinalRules",       xx_OrdinalRules);
1598            cannedData.put("fr_FR/DurationRules",      xx_DurationRules);
1599
1600            cannedData.put("fr/SpelloutRules",         fr_SpelloutRules);
1601            cannedData.put("fr/OrdinalRules",          xx_OrdinalRules);
1602            cannedData.put("fr/DurationRules",         xx_DurationRules);
1603
1604            cannedData.put("de/SpelloutRules",         de_SpelloutRules);
1605            cannedData.put("de/OrdinalRules",          xx_OrdinalRules);
1606            cannedData.put("de/DurationRules",         xx_DurationRules);
1607
1608            cannedData.put("de_DE/SpelloutRules",      de_SpelloutRules);
1609            cannedData.put("de_DE/OrdinalRules",       xx_OrdinalRules);
1610            cannedData.put("de_DE/DurationRules",      xx_DurationRules);
1611
1612            cannedData.put("it/SpelloutRules",         it_SpelloutRules);
1613            cannedData.put("it/OrdinalRules",          xx_OrdinalRules);
1614            cannedData.put("it/DurationRules",         xx_DurationRules);
1615
1616            cannedData.put("it_IT/SpelloutRules",      it_SpelloutRules);
1617            cannedData.put("it_IT/OrdinalRules",       xx_OrdinalRules);
1618            cannedData.put("it_IT/DuratonRules",       xx_DurationRules);
1619
1620            cannedData.put("ko_KR/SpelloutRules",      en_SpelloutRules);
1621            cannedData.put("ko_KR/OrdinalRules",       en_OrdinalRules);
1622            cannedData.put("ko_KR/DurationRules",      en_DurationRules);
1623
1624            cannedData.put("ko/SpelloutRules",         en_SpelloutRules);
1625            cannedData.put("ko/OrdinalRules",          en_OrdinalRules);
1626            cannedData.put("ko/DurationRules",         en_DurationRules);
1627
1628            cannedData.put("zh_Hans_CN/SpelloutRules", en_SpelloutRules);
1629            cannedData.put("zh_Hans_CN/OrdinalRules",  en_OrdinalRules);
1630            cannedData.put("zh_Hans_CH/DurationRules", xx_DurationRules);
1631
1632            cannedData.put("zh_Hant_TW/SpelloutRules", en_SpelloutRules);
1633            cannedData.put("zh_Hant_TW/OrdinalRules",  en_OrdinalRules);
1634            cannedData.put("zh_Hant_TW/DurationRules", en_DurationRules);
1635
1636            cannedData.put("zh_TW/SpelloutRules",      en_SpelloutRules);
1637            cannedData.put("zh_TW/OrdinalRules",       en_OrdinalRules);
1638            cannedData.put("zh_TW/DurationRules",      en_DurationRules);
1639
1640            cannedData.put("en_GB/SpelloutRules",      en_GB_SpelloutRules);
1641            cannedData.put("en_GB/OrdinalRules",       en_OrdinalRules);
1642            cannedData.put("en_GB/DurationRules",      en_DurationRules);
1643
1644            cannedData.put("en_US/SpelloutRules",      en_SpelloutRules);
1645            cannedData.put("en_US/OrdinalRules",       en_OrdinalRules);
1646            cannedData.put("en_US/DurationRules",      en_DurationRules);
1647
1648            cannedData.put("ja/SpelloutRules",         ja_spelloutRules);
1649            cannedData.put("ja/OrdinalRules",          xx_OrdinalRules);
1650            cannedData.put("ja/DurationRules",         xx_DurationRules);
1651
1652            cannedData.put("ja_JP/SpelloutRules",      ja_spelloutRules);
1653            cannedData.put("ja_JP/OrdinalRules",       xx_OrdinalRules);
1654            cannedData.put("ja_JP/DurationRules",      xx_DurationRules);
1655        }
1656
1657        int types[]        = {RuleBasedNumberFormat.SPELLOUT, RuleBasedNumberFormat.ORDINAL, RuleBasedNumberFormat.DURATION};
1658        String typeNames[] = {"SpelloutRules", "OrdinalRules", "DurationRules"};
1659
1660        @Override
1661        public Object[] getTestObjects()
1662        {
1663            Locale locales[] = SerializableTestUtility.getLocales();
1664            RuleBasedNumberFormat formats[] = new RuleBasedNumberFormat[types.length * locales.length];
1665            int i = 0;
1666
1667            for (int t = 0; t < types.length; t += 1) {
1668                for (int l = 0; l < locales.length; l += 1) {
1669                    String cannedRules = (String) cannedData.get(locales[l].toString() + "/" + typeNames[t]);
1670
1671                    if (cannedRules != null) {
1672                        formats[i++] = new RuleBasedNumberFormat(cannedRules, locales[l]);
1673                    } else {
1674                        formats[i++] = new RuleBasedNumberFormat(locales[l], types[t]);
1675                    }
1676                }
1677            }
1678
1679            return formats;
1680        }
1681    }
1682
1683    public static class DecimalFormatSymbolsHandler implements SerializableTestUtility.Handler
1684    {
1685        @Override
1686        public Object[] getTestObjects()
1687        {
1688            Locale locales[] = SerializableTestUtility.getLocales();
1689            DecimalFormatSymbols dfs[] = new DecimalFormatSymbols[locales.length];
1690
1691            for (int i = 0; i < locales.length; i += 1) {
1692                ULocale uloc = ULocale.forLocale(locales[i]);
1693
1694                dfs[i] = getCannedDecimalFormatSymbols(uloc);
1695
1696//                System.out.println("\n    " + uloc.toString() + " = \"" +
1697//                        com.ibm.icu.impl.Utility.escape(String.valueOf(getCharSymbols(dfs[i]), 0, 12)) + "\"");
1698            }
1699
1700            return dfs;
1701        }
1702
1703        @Override
1704        public boolean hasSameBehavior(Object a, Object b)
1705        {
1706            DecimalFormatSymbols dfs_a = (DecimalFormatSymbols) a;
1707            DecimalFormatSymbols dfs_b = (DecimalFormatSymbols) b;
1708            String strings_a[] = getStringSymbols(dfs_a);
1709            String strings_b[] = getStringSymbols(dfs_b);
1710            char chars_a[] = getCharSymbols(dfs_a);
1711            char chars_b[] = getCharSymbols(dfs_b);
1712
1713            return SerializableTestUtility.compareStrings(strings_a, strings_b) && SerializableTestUtility.compareChars(chars_a, chars_b);
1714        }
1715    }
1716
1717    public static class CurrencyPluralInfoHandler implements SerializableTestUtility.Handler
1718    {
1719        @Override
1720        public Object[] getTestObjects()
1721        {
1722            CurrencyPluralInfo currencyPluralInfo[] = {
1723                new CurrencyPluralInfo(), new CurrencyPluralInfo(new ULocale("en_US")),
1724                CurrencyPluralInfo.getInstance(), CurrencyPluralInfo.getInstance(new Locale("en_US")),
1725                CurrencyPluralInfo.getInstance(new ULocale("en_US"))
1726            };
1727            for(int i=0; i<currencyPluralInfo.length; i++){
1728                currencyPluralInfo[i].setPluralRules("one: n is 1; few: n in 2..4");
1729                currencyPluralInfo[i].setCurrencyPluralPattern("few", "few currency");
1730            }
1731            return currencyPluralInfo;
1732        }
1733
1734        @Override
1735        public boolean hasSameBehavior(Object a, Object b)
1736        {
1737            return a.equals(b);
1738        }
1739    }
1740
1741    public static class CompactDecimalFormatHandler extends NumberFormatHandler {
1742        @Override
1743        public Object[] getTestObjects() {
1744            return new CompactDecimalFormat[0];
1745        }
1746    }
1747
1748    public static class MessageFormatHandler implements SerializableTestUtility.Handler
1749    {
1750        @Override
1751        public Object[] getTestObjects()
1752        {
1753            MessageFormat formats[] = {new MessageFormat("pattern{0}")};
1754
1755            return formats;
1756        }
1757
1758        @Override
1759        public boolean hasSameBehavior(Object a, Object b)
1760        {
1761            MessageFormat mfa = (MessageFormat) a;
1762            MessageFormat mfb = (MessageFormat) b;
1763            Object arguments[] = {new Integer(123456)};
1764
1765            return mfa.format(arguments) != mfb.format(arguments);
1766        }
1767    }
1768
1769    public static class MessageFormatFieldHandler implements SerializableTestUtility.Handler
1770    {
1771        @Override
1772        public Object[] getTestObjects()
1773        {
1774            return new Object[] {MessageFormat.Field.ARGUMENT};
1775        }
1776
1777        @Override
1778        public boolean hasSameBehavior(Object a, Object b)
1779        {
1780            return (a == b);
1781        }
1782    }
1783
1784    public static class DateFormatHandler implements SerializableTestUtility.Handler
1785    {
1786        static HashMap cannedPatterns = new HashMap();
1787        static Date fixedDate;
1788
1789        {
1790            cannedPatterns.put("en_CA",      "EEEE, MMMM d, yyyy h:mm:ss a z");
1791            cannedPatterns.put("fr_CA",      "EEEE d MMMM yyyy HH' h 'mm' min 'ss' s 'z");
1792            cannedPatterns.put("zh_Hans_CN", "yyyy'\u5E74'M'\u6708'd'\u65E5'EEEE ahh'\u65F6'mm'\u5206'ss'\u79D2' z");
1793            cannedPatterns.put("zh_CN",      "yyyy'\u5E74'M'\u6708'd'\u65E5'EEEE ahh'\u65F6'mm'\u5206'ss'\u79D2' z");
1794            cannedPatterns.put("zh",         "EEEE, yyyy MMMM dd HH:mm:ss z");
1795            cannedPatterns.put("en",         "EEEE, MMMM d, yyyy h:mm:ss a z");
1796            cannedPatterns.put("fr_FR",      "EEEE d MMMM yyyy HH' h 'mm z");
1797            cannedPatterns.put("fr",         "EEEE d MMMM yyyy HH' h 'mm z");
1798            cannedPatterns.put("de",         "EEEE, d. MMMM yyyy H:mm' Uhr 'z");
1799            cannedPatterns.put("de_DE",      "EEEE, d. MMMM yyyy H:mm' Uhr 'z");
1800            cannedPatterns.put("it",         "EEEE d MMMM yyyy HH:mm:ss z");
1801            cannedPatterns.put("it_IT",      "EEEE d MMMM yyyy HH:mm:ss z");
1802            cannedPatterns.put("ja_JP",      "yyyy'\u5E74'M'\u6708'd'\u65E5'EEEE H'\u6642'mm'\u5206'ss'\u79D2'z");
1803            cannedPatterns.put("ja",         "yyyy'\u5E74'M'\u6708'd'\u65E5'EEEE H'\u6642'mm'\u5206'ss'\u79D2'z");
1804            cannedPatterns.put("ko_KR",      "yyyy'\uB144' M'\uC6D4' d'\uC77C' EEEE a hh'\uC2DC' mm'\uBD84' ss'\uCD08' z");
1805            cannedPatterns.put("ko",         "yyyy'\uB144' M'\uC6D4' d'\uC77C' EEEE a hh'\uC2DC' mm'\uBD84' ss'\uCD08' z");
1806            cannedPatterns.put("zh_Hant_TW", "yyyy'\u5E74'M'\u6708'd'\u65E5'EEEE ahh'\u6642'mm'\u5206'ss'\u79D2' z");
1807            cannedPatterns.put("zh_TW",      "yyyy'\u5E74'M'\u6708'd'\u65E5'EEEE ahh'\u6642'mm'\u5206'ss'\u79D2' z");
1808            cannedPatterns.put("en_GB",      "EEEE, d MMMM yyyy HH:mm:ss z");
1809            cannedPatterns.put("en_US",      "EEEE, MMMM d, yyyy h:mm:ss a z");
1810
1811            // Get a date that will likely not move in or out of Daylight savings time...
1812            Calendar cal = Calendar.getInstance(Locale.US);
1813
1814            cal.clear();
1815            cal.set(2007, Calendar.JANUARY, 1, 12, 0, 0); // January 1, 2007 12:00:00 PM.
1816            fixedDate = cal.getTime();
1817        }
1818
1819        @Override
1820        public Object[] getTestObjects()
1821        {
1822            Locale locales[] = SerializableTestUtility.getLocales();
1823            DateFormat formats[] = new DateFormat[locales.length];
1824
1825            for (int i = 0; i < locales.length; i += 1) {
1826                ULocale uloc = ULocale.forLocale(locales[i]);
1827
1828              //formats[i] = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, locales[i]);
1829                formats[i] = getCannedSimpleDateFormat((String)cannedPatterns.get(uloc.toString()), uloc);
1830            }
1831
1832            return formats;
1833        }
1834
1835        @Override
1836        public boolean hasSameBehavior(Object a, Object b)
1837        {
1838            DateFormat dfa = (DateFormat) a;
1839            DateFormat dfb = (DateFormat) b;
1840
1841            // We previously did not use 'canned' time zone.
1842            TimeZone tza = dfa.getTimeZone();
1843            TimeZone tzb = dfb.getTimeZone();
1844            if (!tza.getID().equals(tzb.getID())) {
1845                // If IDs do not match, reset TimeZone in dfa.
1846                dfa.setTimeZone(tzb);
1847            }
1848
1849            String sfa = dfa.format(fixedDate);
1850            String sfb = dfb.format(fixedDate);
1851
1852            if (!sfa.equals(sfb)) {
1853                // TODO
1854                // In ICU3.8, localized GMT format pattern was added in
1855                // DateFormatSymbols, which has no public setter.
1856                // The difference of locale data for localized GMT format
1857                // will produce different format result.  This is a temporary
1858                // workaround for the issue.
1859                DateFormatSymbols dfsa = ((SimpleDateFormat)dfa).getDateFormatSymbols();
1860                DateFormatSymbols tmp = (DateFormatSymbols)((SimpleDateFormat)dfb).getDateFormatSymbols().clone();
1861
1862                TimeZoneFormat tmptzf = (TimeZoneFormat)((SimpleDateFormat)dfb).getTimeZoneFormat().clone();
1863
1864                tmp.setMonths(dfsa.getMonths());
1865                tmp.setShortMonths(dfsa.getShortMonths());
1866                tmp.setWeekdays(dfsa.getWeekdays());
1867                tmp.setShortWeekdays(dfsa.getShortWeekdays());
1868                tmp.setAmPmStrings(dfsa.getAmPmStrings());
1869
1870                ((SimpleDateFormat)dfa).setDateFormatSymbols(tmp);
1871                ((SimpleDateFormat)dfa).setTimeZoneFormat(tmptzf);
1872
1873                sfa = dfa.format(fixedDate);
1874            }
1875
1876            //return sfa.equals(sfb);
1877            if (!sfa.equals(sfb)) {
1878                return false;
1879            }
1880            return true;
1881        }
1882
1883    }
1884
1885    public static class DateFormatFieldHandler implements SerializableTestUtility.Handler
1886    {
1887        @Override
1888        public Object[] getTestObjects() {
1889            return new Object[] {
1890                    DateFormat.Field.AM_PM,
1891                    DateFormat.Field.DAY_OF_MONTH,
1892                    DateFormat.Field.DAY_OF_WEEK,
1893                    DateFormat.Field.DAY_OF_WEEK_IN_MONTH,
1894                    DateFormat.Field.DAY_OF_YEAR,
1895                    DateFormat.Field.ERA,
1896                    DateFormat.Field.HOUR_OF_DAY0,
1897                    DateFormat.Field.HOUR_OF_DAY1,
1898                    DateFormat.Field.HOUR0,
1899                    DateFormat.Field.HOUR1,
1900                    DateFormat.Field.MILLISECOND,
1901                    DateFormat.Field.MINUTE,
1902                    DateFormat.Field.MONTH,
1903                    DateFormat.Field.SECOND,
1904                    DateFormat.Field.TIME_ZONE,
1905                    DateFormat.Field.WEEK_OF_MONTH,
1906                    DateFormat.Field.WEEK_OF_YEAR,
1907                    DateFormat.Field.YEAR,
1908                    DateFormat.Field.DOW_LOCAL,
1909                    DateFormat.Field.EXTENDED_YEAR,
1910                    DateFormat.Field.JULIAN_DAY,
1911                    DateFormat.Field.MILLISECONDS_IN_DAY,
1912                    DateFormat.Field.YEAR_WOY,
1913                    DateFormat.Field.QUARTER
1914            };
1915        }
1916        @Override
1917        public boolean hasSameBehavior(Object a, Object b)
1918        {
1919            return (a == b);
1920        }
1921    }
1922
1923    public static class DateFormatSymbolsHandler implements SerializableTestUtility.Handler
1924    {
1925
1926        @Override
1927        public Object[] getTestObjects()
1928        {
1929            Locale locales[] = SerializableTestUtility.getLocales();
1930            DateFormatSymbols dfs[] = new DateFormatSymbols[locales.length];
1931
1932            for (int i = 0; i < locales.length; i += 1) {
1933                ULocale uloc = ULocale.forLocale(locales[i]);
1934
1935                dfs[i] = getCannedDateFormatSymbols(uloc);
1936            }
1937
1938            return dfs;
1939        }
1940
1941        @Override
1942        public boolean hasSameBehavior(Object a, Object b)
1943        {
1944            DateFormatSymbols dfs_a = (DateFormatSymbols) a;
1945            DateFormatSymbols dfs_b = (DateFormatSymbols) b;
1946            String months_a[] = dfs_a.getMonths();
1947            String months_b[] = dfs_b.getMonths();
1948
1949            return SerializableTestUtility.compareStrings(months_a, months_b);
1950        }
1951    }
1952
1953    public static class SimpleDateFormatHandler extends DateFormatHandler
1954    {
1955        String patterns[] = {
1956            "EEEE, yyyy MMMM dd",
1957            "yyyy MMMM d",
1958            "yyyy MMM d",
1959            "yy/MM/dd"
1960        };
1961
1962        @Override
1963        public Object[] getTestObjects()
1964        {
1965            Locale locales[] = SerializableTestUtility.getLocales();
1966            SimpleDateFormat dateFormats[] = new SimpleDateFormat[patterns.length * locales.length];
1967            int i = 0;
1968
1969            for (int p = 0; p < patterns.length; p += 1) {
1970                for (int l = 0; l < locales.length; l += 1) {
1971                    dateFormats[i++] = getCannedSimpleDateFormat(patterns[p], ULocale.forLocale(locales[l]));
1972                }
1973            }
1974
1975            return dateFormats;
1976        }
1977    }
1978
1979    public static class DateIntervalFormatHandler implements SerializableTestUtility.Handler
1980    {
1981        @Override
1982        public Object[] getTestObjects()
1983        {
1984            DateIntervalFormat dateIntervalFormats[] = {
1985                DateIntervalFormat.getInstance("yMMMMEEEEd")
1986            };
1987            return dateIntervalFormats;
1988        }
1989
1990        @Override
1991        public boolean hasSameBehavior(Object a, Object b)
1992        {
1993            DateIntervalFormat dfa = (DateIntervalFormat) a;
1994            DateIntervalFormat dfb = (DateIntervalFormat) b;
1995            DateInterval dateInterval = new DateInterval(1, System.currentTimeMillis());
1996            String sfa = dfa.format(dateInterval);
1997            String sfb = dfb.format(dateInterval);
1998
1999            return sfa.equals(sfb);
2000        }
2001    }
2002
2003
2004    public static class DateIntervalInfoHandler implements SerializableTestUtility.Handler
2005    {
2006        @Override
2007        public Object[] getTestObjects()
2008        {
2009            DateIntervalInfo dateIntervalInfo[] = {
2010                new DateIntervalInfo()
2011            };
2012            dateIntervalInfo[0].setIntervalPattern("yMd", Calendar.YEAR, "yy/MM/dd - yy/MM/dd");
2013            dateIntervalInfo[0].setIntervalPattern("yMd", Calendar.MONTH, "yy/MM - MM/dd");
2014            return dateIntervalInfo;
2015        }
2016
2017        @Override
2018        public boolean hasSameBehavior(Object a, Object b)
2019        {
2020            return a.equals(b);
2021        }
2022    }
2023
2024
2025    public static class PatternInfoHandler implements SerializableTestUtility.Handler
2026    {
2027        @Override
2028        public Object[] getTestObjects()
2029        {
2030            DateIntervalInfo.PatternInfo patternInfo[] = {
2031                new DateIntervalInfo.PatternInfo("yyyy MMM dd - ",
2032                                                 "dd",
2033                                                 false)
2034            };
2035            return patternInfo;
2036        }
2037
2038        @Override
2039        public boolean hasSameBehavior(Object a, Object b)
2040        {
2041            return a.equals(b);
2042        }
2043    }
2044
2045    public static class ChineseDateFormatHandler extends DateFormatHandler
2046    {
2047        String patterns[] = {
2048            "EEEE y'x'G-Ml-d",
2049            "y'x'G-Ml-d",
2050            "y'x'G-Ml-d",
2051            "y'x'G-Ml-d"
2052        };
2053
2054        @Override
2055        public Object[] getTestObjects()
2056        {
2057            Locale locales[] = SerializableTestUtility.getLocales();
2058            ChineseDateFormat dateFormats[] = new ChineseDateFormat[patterns.length * locales.length];
2059            int i = 0;
2060
2061            for (int p = 0; p < patterns.length; p += 1) {
2062                for (int l = 0; l < locales.length; l += 1) {
2063                    ULocale locale = new ULocale(locales[l].toString() + "@calendar=chinese");
2064
2065                    dateFormats[i++] = new ChineseDateFormat(patterns[p], locale);
2066                }
2067            }
2068
2069            return dateFormats;
2070        }
2071    }
2072
2073    public static class ChineseDateFormatFieldHandler implements SerializableTestUtility.Handler
2074    {
2075        @Override
2076        public Object[] getTestObjects() {
2077            return new Object[] {
2078                    ChineseDateFormat.Field.IS_LEAP_MONTH
2079            };
2080        }
2081        @Override
2082        public boolean hasSameBehavior(Object a, Object b)
2083        {
2084            return (a == b);
2085        }
2086    }
2087
2088    public static class ChineseDateFormatSymbolsHandler extends DateFormatSymbolsHandler
2089    {
2090        @Override
2091        public Object[] getTestObjects()
2092        {
2093            Locale locales[] = SerializableTestUtility.getLocales();
2094            ChineseDateFormatSymbols cdfs[] = new ChineseDateFormatSymbols[locales.length];
2095
2096            for (int i = 0; i < locales.length; i += 1) {
2097                ULocale uloc = ULocale.forLocale(locales[i]);
2098
2099                cdfs[i] = new ChineseDateFormatSymbols(uloc);
2100                cdfs[i].setMonths((String[]) cannedMonthNames.get(uloc.toString()));
2101            }
2102
2103            return cdfs;
2104        }
2105
2106        @Override
2107        public boolean hasSameBehavior(Object a, Object b)
2108        {
2109            if (! super.hasSameBehavior(a, b)) {
2110                return false;
2111            }
2112
2113            ChineseDateFormatSymbols cdfs_a = (ChineseDateFormatSymbols) a;
2114            ChineseDateFormatSymbols cdfs_b = (ChineseDateFormatSymbols) b;
2115
2116            // The old test did this, which tested that the leap month marker never
2117            // changed from one ICU version to the next; this is not a valid test.
2118            //return cdfs_a.getLeapMonth(0).equals(cdfs_b.getLeapMonth(0)) &&
2119            //     cdfs_a.getLeapMonth(1).equals(cdfs_b.getLeapMonth(1));
2120            //
2121            // A more valid test is that from one version to the next, the
2122            // marker for getLeapMonth(0) does not change and is empty, while
2123            // the marker for getLeapMonth(1) is non-empty in both versions:
2124            return cdfs_a.getLeapMonth(0).equals(cdfs_b.getLeapMonth(0)) &&
2125                   cdfs_a.getLeapMonth(0).length() == 0 &&
2126                   cdfs_a.getLeapMonth(1).length() > 0 &&
2127                   cdfs_b.getLeapMonth(1).length() > 0;
2128        }
2129    }
2130
2131    public static class NumberFormatFieldHandler implements SerializableTestUtility.Handler
2132    {
2133        @Override
2134        public Object[] getTestObjects()
2135        {
2136            NumberFormat.Field fields[] = {
2137                NumberFormat.Field.CURRENCY, NumberFormat.Field.DECIMAL_SEPARATOR, NumberFormat.Field.EXPONENT,
2138                NumberFormat.Field.EXPONENT_SIGN, NumberFormat.Field.EXPONENT_SYMBOL, NumberFormat.Field.FRACTION,
2139                NumberFormat.Field.GROUPING_SEPARATOR, NumberFormat.Field.INTEGER, NumberFormat.Field.PERCENT,
2140                NumberFormat.Field.PERMILLE, NumberFormat.Field.SIGN
2141            };
2142
2143            return fields;
2144        }
2145
2146        @Override
2147        public boolean hasSameBehavior(Object a, Object b)
2148        {
2149            NumberFormat.Field field_a = (NumberFormat.Field) a;
2150            NumberFormat.Field field_b = (NumberFormat.Field) b;
2151
2152            return field_a.toString().equals(field_b.toString());
2153        }
2154    }
2155
2156    public static class DateNumberFormatHandler implements SerializableTestUtility.Handler
2157    {
2158        @Override
2159        public Object[] getTestObjects()
2160        {
2161            Locale locales[] = SerializableTestUtility.getLocales();
2162            DateNumberFormat[] dnfmts = new DateNumberFormat[locales.length];
2163            for (int i = 0; i < locales.length; i++) {
2164                ULocale uloc = ULocale.forLocale(locales[i]);
2165                dnfmts[i] = new DateNumberFormat(uloc,'0',"latn");
2166            }
2167            return dnfmts;
2168        }
2169
2170        @Override
2171        public boolean hasSameBehavior(Object a, Object b) {
2172            return a.equals(b);
2173        }
2174    }
2175
2176    public static class SelectFormatHandler implements SerializableTestUtility.Handler {
2177
2178        @Override
2179        public Object[] getTestObjects() {
2180            SelectFormat[] selfmts = {new SelectFormat("keyword{phrase} other{otherPhrase}")};
2181
2182            return selfmts;
2183        }
2184
2185        @Override
2186        public boolean hasSameBehavior(Object a, Object b) {
2187            SelectFormat sfa = (SelectFormat) a;
2188            SelectFormat sfb = (SelectFormat) b;
2189            String argument = "keyword";
2190
2191            return sfa.format(argument) != sfb.format(argument);
2192        }
2193    }
2194
2195    public static class PluralFormatHandler implements SerializableTestUtility.Handler {
2196        @Override
2197        public Object[] getTestObjects() {
2198            Locale[] locales = { Locale.US }; // main test is in plural rules handler
2199            PluralFormat[] plfmts = new PluralFormat[locales.length];
2200            for (int i = 0; i < locales.length; i++) {
2201                ULocale uloc = ULocale.forLocale(locales[i]);
2202                try {
2203                    plfmts[i] = new PluralFormat(uloc, "one{1 foo} other{# foo}");
2204                } catch (Exception e) {
2205                    e.printStackTrace();
2206                }
2207            }
2208            return plfmts;
2209        }
2210        @Override
2211        public boolean hasSameBehavior(Object a, Object b) {
2212            PluralFormat pfa = (PluralFormat)a;
2213            PluralFormat pfb = (PluralFormat)b;
2214            boolean isSame = true;
2215            for (int i = 0; i < 10; i++) {
2216                String texta = pfa.format(i);
2217                String textb = pfb.format(i);
2218                if (!texta.equals(textb)) {
2219                    isSame = false;
2220                    break;
2221                }
2222            }
2223            return isSame;
2224        }
2225    }
2226
2227    public static class PluralRulesHandler implements SerializableTestUtility.Handler {
2228        // canned rules as of 4.2
2229        final String[] cannedRules = {
2230                "", // ja
2231                "one: n is 1", // da
2232                "one: n within 0..2 and n is not 2", // fr
2233                "one: n mod 10 is 1 and n mod 100 is not 11; zero: n is 0", // lv
2234                "one: n is 1; two: n is 2", // ga
2235                "few: n is 0 OR n is not 1 AND n mod 100 in 1..19; one: n is 1", // ro
2236                "few: n mod 10 in 2..9 and n mod 100 not in 11..19; one: n mod 10 is 1 and n mod 100 not in 11..19", // lt
2237                "few: n mod 10 in 2..4 and n mod 100 not in 12..14; many: n mod 10 is 0 or n mod 10 in 5..9 or n mod 100 in 11..14; one: n mod 10 is 1 and n mod 100 is not 11", // hr
2238                "few: n in 2..4; one: n is 1", // cs
2239                "few: n mod 10 in 2..4 and n mod 100 not in 12..14 and n mod 100 not in 22..24; one: n is 1", // pl
2240                "few: n mod 100 in 3..4; one: n mod 100 is 1; two: n mod 100 is 2", // sl
2241        };
2242
2243        @Override
2244        public Object[] getTestObjects() {
2245            PluralRules[] plrulz = new PluralRules[cannedRules.length];
2246            for (int i = 0; i < cannedRules.length; i++) {
2247                try {
2248                    plrulz[i] = PluralRules.parseDescription(cannedRules[i]);
2249                } catch (Exception e) {
2250                    e.printStackTrace();
2251                }
2252            }
2253            return plrulz;
2254        }
2255        @Override
2256        public boolean hasSameBehavior(Object a, Object b) {
2257            return a.equals(b);
2258        }
2259    }
2260
2261    public static class PluralRulesSerialProxyHandler implements SerializableTestUtility.Handler {
2262        // Tested through PluralRules, so just a stub here to keep CoverageTest happy
2263        final String[] cannedRules = {};
2264
2265        @Override
2266        public Object[] getTestObjects() {
2267            return new PluralRules[cannedRules.length];
2268        }
2269        @Override
2270        public boolean hasSameBehavior(Object a, Object b) {
2271            return a.equals(b);
2272        }
2273    }
2274
2275
2276
2277    public static class TimeUnitFormatHandler implements SerializableTestUtility.Handler {
2278        // TODO - more test coverage!
2279        @Override
2280        public Object[] getTestObjects() {
2281            return new Object[] { new TimeUnitFormat().setLocale(ULocale.ENGLISH) };
2282        }
2283        @Override
2284        public boolean hasSameBehavior(Object a, Object b) {
2285            TimeUnitFormat tufa = (TimeUnitFormat)a;
2286            TimeUnitFormat tufb = (TimeUnitFormat)b;
2287
2288            TimeUnitAmount amount = new TimeUnitAmount(3, TimeUnit.HOUR);
2289            String resa = tufa.format(amount);
2290            String resb = tufb.format(amount);
2291
2292            return resa.equals(resb);
2293        }
2294    }
2295
2296    public static class TimeZoneNamesHandler implements SerializableTestUtility.Handler {
2297        @Override
2298        public Object[] getTestObjects() {
2299            return new Object[] {
2300                    TimeZoneNames.getInstance(ULocale.ENGLISH),
2301                    TimeZoneNames.getInstance(ULocale.JAPAN)
2302            };
2303        }
2304        @Override
2305        public boolean hasSameBehavior(Object a, Object b) {
2306            TimeZoneNames tzna = (TimeZoneNames)a;
2307            TimeZoneNames tznb = (TimeZoneNames)b;
2308
2309            final String tzid = "America/Los_Angeles";
2310
2311            String eca = tzna.getExemplarLocationName(tzid);
2312            String ecb = tznb.getExemplarLocationName(tzid);
2313
2314            if (!eca.equals(ecb)) {
2315                return false;
2316            }
2317
2318            final String mzID = "America_Pacific";
2319            final String region = "US";
2320
2321            String refza = tzna.getReferenceZoneID(mzID, region);
2322            String refzb = tznb.getReferenceZoneID(mzID, region);
2323
2324            if (!refza.equals(refzb)) {
2325                return false;
2326            }
2327
2328            return true;
2329        }
2330    }
2331
2332    public static class TimeZoneGenericNamesHandler implements SerializableTestUtility.Handler {
2333        @Override
2334        public Object[] getTestObjects() {
2335            return new Object[] {
2336                    TimeZoneGenericNames.getInstance(ULocale.ENGLISH),
2337                    TimeZoneGenericNames.getInstance(ULocale.JAPAN)
2338            };
2339        }
2340        @Override
2341        public boolean hasSameBehavior(Object a, Object b) {
2342            TimeZoneGenericNames tzgna = (TimeZoneGenericNames)a;
2343            TimeZoneGenericNames tzgnb = (TimeZoneGenericNames)b;
2344
2345            final String[] TZIDS = {
2346                "America/Los_Angeles",
2347                "America/Argentina/Buenos_Aires",
2348                "Etc/GMT"
2349            };
2350
2351            final long[] DATES = {
2352                1277942400000L, // 2010-07-01 00:00:00 GMT
2353                1293840000000L, // 2011-01-01 00:00:00 GMT
2354            };
2355
2356            for (String tzid : TZIDS) {
2357                TimeZone tz = TimeZone.getTimeZone(tzid);
2358                for (GenericNameType nt : GenericNameType.values()) {
2359                    for (long date : DATES) {
2360                        String nameA = tzgna.getDisplayName(tz, nt, date);
2361                        String nameB = tzgnb.getDisplayName(tz, nt, date);
2362                        if (!Utility.objectEquals(nameA, nameB)) {
2363                            return false;
2364                        }
2365                    }
2366                }
2367            }
2368
2369            return true;
2370        }
2371    }
2372
2373    public static class TZDBTimeZoneNamesHandler implements SerializableTestUtility.Handler {
2374        @Override
2375        public Object[] getTestObjects() {
2376            return new Object[] {
2377                    TimeZoneNames.getTZDBInstance(ULocale.ENGLISH),
2378                    TimeZoneNames.getTZDBInstance(ULocale.JAPAN)
2379            };
2380        }
2381        @Override
2382        public boolean hasSameBehavior(Object a, Object b) {
2383            TZDBTimeZoneNames tzdbna = (TZDBTimeZoneNames)a;
2384            TZDBTimeZoneNames tzdbnb = (TZDBTimeZoneNames)b;
2385
2386            final String[] TZIDS = {
2387                "America/Los_Angeles",
2388                "America/Argentina/Buenos_Aires",
2389                "Asia/Shanghai",
2390                "Etc/GMT"
2391            };
2392
2393            final long[] DATES = {
2394                1277942400000L, // 2010-07-01 00:00:00 GMT
2395                1293840000000L, // 2011-01-01 00:00:00 GMT
2396            };
2397
2398            final NameType[] nTypes = {
2399                    NameType.SHORT_STANDARD,
2400                    NameType.SHORT_DAYLIGHT
2401            };
2402
2403            for (String tzid : TZIDS) {
2404                for (NameType nt : nTypes) {
2405                    for (long date : DATES) {
2406                        String nameA = tzdbna.getDisplayName(tzid, nt, date);
2407                        String nameB = tzdbnb.getDisplayName(tzid, nt, date);
2408                        if (!Utility.objectEquals(nameA, nameB)) {
2409                            return false;
2410                        }
2411                    }
2412                }
2413            }
2414
2415            return true;
2416        }
2417    }
2418
2419    public static class TimeZoneFormatHandler implements SerializableTestUtility.Handler {
2420        static final String CUSTOM_GMT_PATTERN = "Offset {0} from UTC";
2421
2422        @Override
2423        public Object[] getTestObjects() {
2424            TimeZoneFormat tzfmt = TimeZoneFormat.getInstance(ULocale.ENGLISH).cloneAsThawed();
2425            tzfmt.setGMTPattern(CUSTOM_GMT_PATTERN);
2426
2427            return new Object[] {tzfmt};
2428        }
2429        @Override
2430        public boolean hasSameBehavior(Object a, Object b) {
2431            TimeZoneFormat tzfa = (TimeZoneFormat)a;
2432            TimeZoneFormat tzfb = (TimeZoneFormat)b;
2433
2434            if (!tzfa.getGMTPattern().equals(tzfb.getGMTPattern())) {
2435                return false;
2436            }
2437
2438            final int offset = -5 * 60 * 60 * 1000;
2439
2440            String gmta = tzfa.formatOffsetLocalizedGMT(offset);
2441            String gmtb = tzfb.formatOffsetLocalizedGMT(offset);
2442
2443            if (!gmta.equals(gmtb)) {
2444                return false;
2445            }
2446
2447            long now = System.currentTimeMillis();
2448            TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
2449
2450            String genloca = tzfa.format(Style.GENERIC_LOCATION, tz, now);
2451            String genlocb = tzfb.format(Style.GENERIC_LOCATION, tz, now);
2452
2453            if (!genloca.equals(genlocb)) {
2454                return false;
2455            }
2456
2457            return true;
2458        }
2459    }
2460
2461    public static void main(String[] args)
2462    {
2463        // nothing needed...
2464    }
2465
2466}
2467//eof
2468