1aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin/* GENERATED SOURCE. DO NOT MODIFY. */
2f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert// © 2016 and later: Unicode, Inc. and others.
3f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html#License
4aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin/*
5aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin *******************************************************************************
6aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * Copyright (C) 2008-2015, International Business Machines Corporation and
7aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * others. All Rights Reserved.
8aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin *******************************************************************************
9aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin */
10aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinpackage android.icu.dev.test.collator;
11aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.util.ArrayList;
12aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.util.Arrays;
13aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.util.Collection;
14aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.util.Iterator;
15aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.util.LinkedHashSet;
16aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.util.List;
17aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.util.Locale;
18aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.util.Set;
19aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.util.TreeSet;
20aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
21f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubertimport org.junit.Test;
2205fa7802d0874812c234a29745586677ee5837eaFredrik Roubertimport org.junit.runner.RunWith;
2305fa7802d0874812c234a29745586677ee5837eaFredrik Roubertimport org.junit.runners.JUnit4;
24f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
25aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.dev.test.TestFmwk;
26aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.dev.util.CollectionUtilities;
27aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.impl.ICUDebug;
28aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.impl.Row;
29aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.impl.Row.R4;
30aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.lang.UCharacter;
31aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.lang.UProperty;
32aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.lang.UScript;
33aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.text.AlphabeticIndex;
34aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.text.AlphabeticIndex.Bucket;
35aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.text.AlphabeticIndex.Bucket.LabelType;
36aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.text.AlphabeticIndex.ImmutableIndex;
37aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.text.AlphabeticIndex.Record;
38aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.text.Collator;
39aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.text.Normalizer2;
40aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.text.RawCollationKey;
41aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.text.RuleBasedCollator;
42aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.text.UTF16;
43aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.text.UnicodeSet;
44aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.util.ULocale;
452e13a2bdade5cd0a635f0bd89805931a6fd710daPete Gillinimport android.icu.testsharding.MainTestShard;
46aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
47aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin/**
48aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * @author Mark Davis
49aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin */
502e13a2bdade5cd0a635f0bd89805931a6fd710daPete Gillin@MainTestShard
5105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert@RunWith(JUnit4.class)
52aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinpublic class AlphabeticIndexTest extends TestFmwk {
53aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    /**
54f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert     *
55aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     */
56aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private static final String ARROW = "\u2192";
57aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private static final boolean DEBUG = ICUDebug.enabled("alphabeticindex");
58aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
59aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public static Set<String> KEY_LOCALES = new LinkedHashSet(Arrays.asList(
60f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            "en", "es", "de", "fr", "ja", "it", "tr", "pt", "zh", "nl",
61f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            "pl", "ar", "ru", "zh_Hant", "ko", "th", "sv", "fi", "da",
62f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            "he", "nb", "el", "hr", "bg", "sk", "lt", "vi", "lv", "sr",
63f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            "pt_PT", "ro", "hu", "cs", "id", "sl", "fil", "fa", "uk",
64f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            "ca", "hi", "et", "eu", "is", "sw", "ms", "bn", "am", "ta",
65aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "te", "mr", "ur", "ml", "kn", "gu", "or"));
66aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private String[][] localeAndIndexCharactersLists = new String[][] {
67aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            /* Arabic*/ {"ar", "\u0627:\u0628:\u062A:\u062B:\u062C:\u062D:\u062E:\u062F:\u0630:\u0631:\u0632:\u0633:\u0634:\u0635:\u0636:\u0637:\u0638:\u0639:\u063A:\u0641:\u0642:\u0643:\u0644:\u0645:\u0646:\u0647:\u0648:\u064A"},
68aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            /* Bulgarian*/  {"bg", "\u0410:\u0411:\u0412:\u0413:\u0414:\u0415:\u0416:\u0417:\u0418:\u0419:\u041A:\u041B:\u041C:\u041D:\u041E:\u041F:\u0420:\u0421:\u0422:\u0423:\u0424:\u0425:\u0426:\u0427:\u0428:\u0429:\u042E:\u042F"},
69aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            /* Catalan*/    {"ca", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z"},
70aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            /* Czech*/  {"cs", "A:B:C:\u010C:D:E:F:G:H:CH:I:J:K:L:M:N:O:P:Q:R:\u0158:S:\u0160:T:U:V:W:X:Y:Z:\u017D"},
71aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            /* Danish*/ {"da", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z:\u00C6:\u00D8:\u00C5"},
72aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            /* German*/ {"de", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z"},
73aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            /* Greek*/  {"el", "\u0391:\u0392:\u0393:\u0394:\u0395:\u0396:\u0397:\u0398:\u0399:\u039A:\u039B:\u039C:\u039D:\u039E:\u039F:\u03A0:\u03A1:\u03A3:\u03A4:\u03A5:\u03A6:\u03A7:\u03A8:\u03A9"},
74aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            /* English*/    {"en", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z"},
75aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            /* Spanish*/    {"es", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:\u00D1:O:P:Q:R:S:T:U:V:W:X:Y:Z"},
76aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            /* Estonian*/   {"et", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:\u0160:Z:\u017D:T:U:V:\u00D5:\u00C4:\u00D6:\u00DC:X:Y"},
77aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            /* Basque*/ {"eu", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z"},
78aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            /* Finnish*/    {"fi", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z:\u00C5:\u00C4:\u00D6"},
79f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            /* Filipino*/   {"fil", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:\u00D1:Ng:O:P:Q:R:S:T:U:V:W:X:Y:Z"},
80aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            /* French*/ {"fr", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z"},
81aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            /* Hebrew*/ {"he", "\u05D0:\u05D1:\u05D2:\u05D3:\u05D4:\u05D5:\u05D6:\u05D7:\u05D8:\u05D9:\u05DB:\u05DC:\u05DE:\u05E0:\u05E1:\u05E2:\u05E4:\u05E6:\u05E7:\u05E8:\u05E9:\u05EA"},
82aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            /* Icelandic*/  {"is", "A:\u00C1:B:C:D:\u00D0:E:\u00C9:F:G:H:I:\u00CD:J:K:L:M:N:O:\u00D3:P:Q:R:S:T:U:\u00DA:V:W:X:Y:\u00DD:Z:\u00DE:\u00C6:\u00D6"},
83aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            /* Italian*/    {"it", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z"},
84aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            /* Japanese*/   {"ja", "\u3042:\u304B:\u3055:\u305F:\u306A:\u306F:\u307E:\u3084:\u3089:\u308F"},
85aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            /* Korean*/ {"ko", "\u3131:\u3134:\u3137:\u3139:\u3141:\u3142:\u3145:\u3147:\u3148:\u314A:\u314B:\u314C:\u314D:\u314E"},
86aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            /* Lithuanian*/ {"lt", "A:B:C:\u010C:D:E:F:G:H:I:J:K:L:M:N:O:P:R:S:\u0160:T:U:V:Z:\u017D"},
87aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            /* Latvian*/    {"lv", "A:B:C:\u010C:D:E:F:G:\u0122:H:I:J:K:\u0136:L:\u013B:M:N:\u0145:O:P:Q:R:S:\u0160:T:U:V:W:X:Z:\u017D"},
88aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            /* Norwegian Bokm\u00E5l*/  {"nb", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z:\u00C6:\u00D8:\u00C5"},
89aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            /* Dutch*/  {"nl", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z"},
90aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            /* Polish*/ {"pl", "A:\u0104:B:C:\u0106:D:E:\u0118:F:G:H:I:J:K:L:\u0141:M:N:\u0143:O:\u00D3:P:Q:R:S:\u015A:T:U:V:W:X:Y:Z:\u0179:\u017B"},
91aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            /* Portuguese*/ {"pt", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z"},
92aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            /* Romanian*/   {"ro", "A:\u0102:\u00C2:B:C:D:E:F:G:H:I:\u00CE:J:K:L:M:N:O:P:Q:R:S:\u0218:T:\u021A:U:V:W:X:Y:Z"},
93aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            /* Russian*/    {"ru", "\u0410:\u0411:\u0412:\u0413:\u0414:\u0415:\u0416:\u0417:\u0418:\u0419:\u041A:\u041B:\u041C:\u041D:\u041E:\u041F:\u0420:\u0421:\u0422:\u0423:\u0424:\u0425:\u0426:\u0427:\u0428:\u0429:\u042B:\u042D:\u042E:\u042F"},
94aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            /* Slovak*/ {"sk", "A:\u00C4:B:C:\u010C:D:E:F:G:H:CH:I:J:K:L:M:N:O:\u00D4:P:Q:R:S:\u0160:T:U:V:W:X:Y:Z:\u017D"},
95aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            /* Slovenian*/  {"sl", "A:B:C:\u010C:\u0106:D:\u0110:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:\u0160:T:U:V:W:X:Y:Z:\u017D"},
96aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            /* Serbian*/    {"sr", "\u0410:\u0411:\u0412:\u0413:\u0414:\u0402:\u0415:\u0416:\u0417:\u0418:\u0408:\u041A:\u041B:\u0409:\u041C:\u041D:\u040A:\u041E:\u041F:\u0420:\u0421:\u0422:\u040B:\u0423:\u0424:\u0425:\u0426:\u0427:\u040F:\u0428"},
97aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            /* Swedish*/    {"sv", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z:\u00C5:\u00C4:\u00D6"},
98aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            /* Turkish*/    {"tr", "A:B:C:\u00C7:D:E:F:G:H:I:\u0130:J:K:L:M:N:O:\u00D6:P:Q:R:S:\u015E:T:U:\u00DC:V:W:X:Y:Z"},
99aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            /* Ukrainian*/  {"uk", "\u0410:\u0411:\u0412:\u0413:\u0490:\u0414:\u0415:\u0404:\u0416:\u0417:\u0418:\u0406:\u0407:\u0419:\u041A:\u041B:\u041C:\u041D:\u041E:\u041F:\u0420:\u0421:\u0422:\u0423:\u0424:\u0425:\u0426:\u0427:\u0428:\u0429:\u042E:\u042F"},
100aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            /* Vietnamese*/ {"vi", "A:\u0102:\u00C2:B:C:D:\u0110:E:\u00CA:F:G:H:I:J:K:L:M:N:O:\u00D4:\u01A0:P:Q:R:S:T:U:\u01AF:V:W:X:Y:Z"},
101aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            /* Chinese*/    {"zh", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z"},
102aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            /* Chinese (Traditional Han)*/  {"zh_Hant", "1\u5283:2\u5283:3\u5283:4\u5283:5\u5283:6\u5283:7\u5283:8\u5283:9\u5283:10\u5283:11\u5283:12\u5283:13\u5283:14\u5283:15\u5283:16\u5283:17\u5283:18\u5283:19\u5283:20\u5283:21\u5283:22\u5283:23\u5283:24\u5283:25\u5283:26\u5283:27\u5283:28\u5283:29\u5283:30\u5283:31\u5283:32\u5283:33\u5283:35\u5283:36\u5283:39\u5283:48\u5283"},
103aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
104aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            // Comment these out to make the test run faster. Later, make these run under extended
105aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
106aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Afrikaans*/  {"af", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z"},
107aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Akan*/   {"ak", "A:B:C:D:E:\u0190:F:G:H:I:J:K:L:M:N:O:\u0186:P:Q:R:S:T:U:V:W:X:Y:Z"},
108aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Asu*/    {"asa", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:R:S:T:U:V:W:Y:Z"},
109aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Azerbaijani*/    {"az", "A:B:C:\u00C7:D:E:\u018F:F:G:\u011E:H:X:I:\u0130:J:K:Q:L:M:N:O:\u00D6:P:R:S:\u015E:T:U:\u00DC:V:W:Y:Z"},
110aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Belarusian*/ {"be", "\u0410:\u0411:\u0412:\u0413:\u0414:\u0415:\u0416:\u0417:\u0406:\u0419:\u041A:\u041B:\u041C:\u041D:\u041E:\u041F:\u0420:\u0421:\u0422:\u0423:\u0424:\u0425:\u0426:\u0427:\u0428:\u042B:\u042D:\u042E:\u042F"},
111aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Bemba*/  {"bem", "A:B:C:E:F:G:I:J:K:L:M:N:O:P:S:T:U:W:Y"},
112aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Bena*/   {"bez", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:Y:Z"},
113aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Bambara*/    {"bm", "A:B:C:D:E:\u0190:F:G:H:I:J:K:L:M:N:\u019D:\u014A:O:\u0186:P:R:S:T:U:W:Y:Z"},
114aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Tibetan*/    {"bo", "\u0F40:\u0F41:\u0F42:\u0F44:\u0F45:\u0F46:\u0F47:\u0F49:\u0F4F:\u0F50:\u0F51:\u0F53:\u0F54:\u0F55:\u0F56:\u0F58:\u0F59:\u0F5A:\u0F5B:\u0F5D:\u0F5E:\u0F5F:\u0F60:\u0F61:\u0F62:\u0F63:\u0F64:\u0F66:\u0F67:\u0F68"},
115aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Chiga*/  {"cgg", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z"},
116aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Cherokee*/   {"chr", "\u13A0:\u13A6:\u13AD:\u13B3:\u13B9:\u13BE:\u13C6:\u13CC:\u13D3:\u13DC:\u13E3:\u13E9:\u13EF"},
117aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Welsh*/  {"cy", "A:B:C:CH:D:E:F:FF:G:H:I:J:L:LL:M:N:O:P:PH:R:RH:S:T:TH:U:W:Y"},
118aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Taita*/  {"dav", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:R:S:T:U:V:W:Y:Z"},
119aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Embu*/   {"ebu", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z"},
120aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Ewe*/    {"ee", "A:B:C:D:\u0189:E:\u0190:F:\u0191:G:\u0194:H:I:J:K:L:M:N:\u014A:O:\u0186:P:Q:R:S:T:U:V:\u01B2:W:X:Y:Z"},
121aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Esperanto*/  {"eo", "A:B:C:\u0108:D:E:F:G:\u011C:H:\u0124:I:J:\u0134:K:L:M:N:O:P:R:S:\u015C:T:U:\u016C:V:Z"},
122aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Fulah*/  {"ff", "A:B:\u0181:C:D:\u018A:E:F:G:H:I:J:K:L:M:N:\u014A:O:P:R:S:T:U:W:Y:\u01B3"},
123aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Faroese*/    {"fo", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z:\u00C6:\u00D8"},
124aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Gusii*/  {"guz", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:R:S:T:U:V:W:Y:Z"},
125aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Hausa*/  {"ha", "A:B:\u0181:C:D:\u018A:E:F:G:H:I:J:K:\u0198:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z"},
126aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Igbo*/   {"ig", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z"},
127aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Machame*/    {"jmc", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:R:S:T:U:V:W:Y:Z"},
128aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Kabyle*/ {"kab", "A:B:C:D:E:\u0190:F:G:\u0194:H:I:J:K:L:M:N:P:Q:R:S:T:U:W:X:Y:Z"},
129aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Kamba*/  {"kam", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z"},
130aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Makonde*/    {"kde", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z"},
131aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Kabuverdianu*/   {"kea", "A:B:D:E:F:G:H:I:J:K:L:M:N:O:P:R:S:T:U:V:X:Z"},
132aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Koyra Chiini*/   {"khq", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:\u019D:\u014A:O:P:Q:R:S:T:U:W:X:Y:Z"},
133aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Kikuyu*/ {"ki", "A:B:C:D:E:G:H:I:J:K:M:N:O:R:T:U:W:Y"},
134aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Kalenjin*/   {"kln", "A:B:C:D:E:G:H:I:J:K:L:M:N:O:P:R:S:T:U:W:Y"},
135aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Langi*/  {"lag", "A:B:C:D:E:F:G:H:I:\u0197:J:K:L:M:N:O:P:Q:R:S:T:U:\u0244:V:W:X:Y:Z"},
136aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Ganda*/  {"lg", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z"},
137aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Luo*/    {"luo", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:R:S:T:U:V:W:Y"},
138aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Luyia*/  {"luy", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z"},
139aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Masai*/  {"mas", "A:B:C:D:E:\u0190:G:H:I:\u0197:J:K:L:M:N:\u014A:O:\u0186:P:R:S:T:U:\u0244:W:Y"},
140aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Meru*/   {"mer", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z"},
141aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Morisyen*/   {"mfe", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:R:S:T:U:V:W:X:Y:Z"},
142aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Malagasy*/   {"mg", "A:B:D:E:F:G:H:I:J:K:L:M:N:O:P:R:S:T:V:Y:Z"},
143aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            // This should be the correct data.  Commented till it is fixed in CLDR collation data.
144aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            // {"mk", "\u0410:\u0411:\u0412:\u0413:\u0403:\u0414:\u0415:\u0416:\u0417:\u0405:\u0418:\u0408:\u041A:\u040C:\u041B:\u0409:\u041C:\u041D:\u040A:\u041E:\u041F:\u0420:\u0421:\u0422:\u0423:\u0424:\u0425:\u0426:\u0427:\u040F:\u0428"},
145aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Macedonian*/ {"mk", "\u0410:\u0411:\u0412:\u0413:\u0414:\u0403:\u0415:\u0416:\u0417:\u0405:\u0418:\u0408:\u041A:\u041B:\u0409:\u041C:\u041D:\u040A:\u041E:\u041F:\u0420:\u0421:\u0422:\u040C:\u0423:\u0424:\u0425:\u0426:\u0427:\u040F:\u0428"},
146aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            // This should be the correct data.  Commented till it is fixed in CLDR collation data.
147aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            // {"mt", "A:B:C:\u010A:D:E:F:\u0120:G:G\u0126:H:\u0126:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:\u017B:Z"},
148aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Maltese*/    {"mt", "A:B:\u010A:C:D:E:F:\u0120:G:G\u0126:H:\u0126:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:\u017B:Z"},
149aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Nama*/   {"naq", "A:B:C:D:E:F:G:H:I:K:M:N:O:P:Q:R:S:T:U:W:X:Y:Z"},
150aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* North Ndebele*/  {"nd", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:S:T:U:V:W:X:Y:Z"},
151aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Norwegian Nynorsk*/  {"nn", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z:\u00C6:\u00D8:\u00C5"},
152aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Nyankole*/   {"nyn", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z"},
153aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Oromo*/  {"om", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z"},
154aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Romansh*/    {"rm", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z"},
155aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Rombo*/  {"rof", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:R:S:T:U:V:W:Y:Z"},
156aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Kinyarwanda*/    {"rw", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z"},
157aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Rwa*/    {"rwk", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:R:S:T:U:V:W:Y:Z"},
158aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Samburu*/    {"saq", "A:B:C:D:E:G:H:I:J:K:L:M:N:O:P:R:S:T:U:V:W:Y"},
159aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Sena*/   {"seh", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z"},
160aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Koyraboro Senni*/    {"ses", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:\u019D:\u014A:O:P:Q:R:S:T:U:W:X:Y:Z"},
161aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Sango*/  {"sg", "A:B:D:E:F:G:H:I:J:K:L:M:N:O:P:R:S:T:U:V:W:Y:Z"},
162aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Tachelhit*/  {"shi", "A:B:C:D:E:\u0190:F:G:\u0194:H:I:J:K:L:M:N:Q:R:S:T:U:W:X:Y:Z"},
163aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Tachelhit (Tifinagh)*/   {"shi_Tfng", "\u2D30:\u2D31:\u2D33:\u2D37:\u2D39:\u2D3B:\u2D3C:\u2D3D:\u2D40:\u2D43:\u2D44:\u2D45:\u2D47:\u2D49:\u2D4A:\u2D4D:\u2D4E:\u2D4F:\u2D53:\u2D54:\u2D55:\u2D56:\u2D59:\u2D5A:\u2D5B:\u2D5C:\u2D5F:\u2D61:\u2D62:\u2D63:\u2D65"},
164aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Shona*/  {"sn", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:R:S:T:U:V:W:Y:Z"},
165aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Teso*/   {"teo", "A:B:C:D:E:G:H:I:J:K:L:M:N:O:P:R:S:T:U:V:W:X:Y"},
166aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Tonga*/  {"to", "A:B:C:D:E:F:G:H:\u02BB:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z"},
167aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Central Morocco Tamazight*/  {"tzm", "A:B:C:D:E:\u0190:F:G:\u0194:H:I:J:K:L:M:N:Q:R:S:T:U:W:X:Y:Z"},
168aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Uzbek (Latin)*/  {"uz_Latn", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z:\u02BF"},
169aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Vunjo*/  {"vun", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:R:S:T:U:V:W:Y:Z"},
170aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Soga*/   {"xog", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z"},
171aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            //            /* Yoruba*/ {"yo", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z"},
172aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
173aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    };
174f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
175aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//    public void TestAAKeyword() {
176aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//    ICUResourceBundle rb = (ICUResourceBundle) UResourceBundle.getBundleInstance(
177aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//            ICUResourceBundle.ICU_COLLATION_BASE_NAME, "zh");
178aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//    showBundle(rb, 0);
179aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//        String[] keywords = Collator.getKeywords();
180aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//        System.out.println(Arrays.asList(keywords));
181aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//        String locale = "zh";
182aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//        ULocale ulocale = new ULocale(locale);
183aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//        for (String keyword : keywords) {
184aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//            List<String> values = Arrays.asList(Collator.getKeywordValuesForLocale(keyword, ulocale, false));
185aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//            List<String> allValues = Arrays.asList(Collator.getKeywordValues(keyword));
186aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//            for (String value : allValues) {
187aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//                System.out.println(keyword + "=" + value);
188aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//                checkKeyword(locale, value, values.contains(value));
189aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//            }
190aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//        }
191aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//    }
192aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//
193aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//    private void checkKeyword(String locale, String collationValue, boolean shouldExist) {
194aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//        final ULocale base = new ULocale(locale);
195aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//        final ULocale desired = new ULocale(locale + "@collation=" + collationValue);
196aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//        Collator foo = Collator.getInstance(desired);
197aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//        ULocale actual = foo.getLocale(ULocale.ACTUAL_LOCALE);
198aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//        if (shouldExist) {
199aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//            assertEquals("actual should match desired", desired, actual);
200aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//        } else {
201aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//            assertEquals("actual should match base", base, actual);
202aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//        }
203aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//        int comp = foo.compare("a", "ā");
204aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//        assertEquals("should fall back to default for zh", -1, comp);
205aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//    }
206f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert//
207aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//    /**
208aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//     * @param rb
209aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//     * @param i
210aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//     */
211aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//    private static void showBundle(UResourceBundle rb, int i) {
212aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//        for (String key : rb.keySet()) {
213aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//            System.out.print("\n" + Utility.repeat("  ", i) + key);
214aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//            UResourceBundle rb2 = rb.get(key);
215aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//            showBundle(rb2, i+1);
216aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//        }
217aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin//    }
218aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
219f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
220f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
221aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public void TestA() {
222aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        String[][] tests = {{"zh_Hant", "渡辺", "12劃"},
223aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                {"zh", "渡辺", "D"}
224f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                /*, "zh@collation=unihan", "ja@collation=unihan", "ko@collation=unihan"*/
225aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                };
226aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        for (String[] test : tests) {
227aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            AlphabeticIndex<Integer> alphabeticIndex = new AlphabeticIndex<Integer>(new ULocale(test[0]));
228aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            final String probe = test[1];
229aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            final String expectedLabel = test[2];
230aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            alphabeticIndex.addRecord(probe, 1);
231aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            List labels = alphabeticIndex.getBucketLabels();
232aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            logln(labels.toString());
233aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            Bucket<Integer> bucket = find(alphabeticIndex, probe);
234aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            assertEquals("locale " + test[0] + " name=" + probe + " in bucket",
235aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    expectedLabel, bucket.getLabel());
236aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
237aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
238aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
239aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private Bucket<Integer> find(AlphabeticIndex<Integer> alphabeticIndex, final String probe) {
240aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        for (Bucket<Integer> bucket : alphabeticIndex) {
241aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            for (Record<Integer> record : bucket) {
242aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                if (record.getName().equals(probe)) {
243aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    return bucket;
244aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                }
245aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
246aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
247aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        return null;
248aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
249aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
250f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
251aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public void TestFirstCharacters() {
252aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
253aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        AlphabeticIndex alphabeticIndex = new AlphabeticIndex(Locale.ENGLISH);
254aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        RuleBasedCollator collator = alphabeticIndex.getCollator();
255aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        collator.setStrength(Collator.IDENTICAL);
256aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        Collection<String> firsts = alphabeticIndex.getFirstCharactersInScripts();
257aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // Verify that each script is represented exactly once.
258aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // Exclude pseudo-scripts like Common (no letters).
259aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // Exclude scripts like Braille and Sutton SignWriting
260aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // because they only have symbols, not letters.
261aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        UnicodeSet missingScripts = new UnicodeSet(
262aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                "[^[:inherited:][:unknown:][:common:][:Braille:][:SignWriting:]]");
263aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        String last = "";
264aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        for (String index : firsts) {
265aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            if (collator.compare(last,index) >= 0) {
266aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                errln("Characters not in order: " + last + " !< " + index);
267aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
268aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            int script = getFirstRealScript(index);
269aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            if (script == UScript.UNKNOWN) { continue; }
270aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            UnicodeSet s = new UnicodeSet().applyIntPropertyValue(UProperty.SCRIPT, script);
271aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            if (missingScripts.containsNone(s)) {
272aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                errln("2nd character in script: " + index + "\t" + new UnicodeSet(missingScripts).retainAll(s).toPattern(false));
273aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
274aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            missingScripts.removeAll(s);
275aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
276aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        if (missingScripts.size() != 0) {
277aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            String missingScriptNames = "";
278aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            UnicodeSet missingChars = new UnicodeSet(missingScripts);
279aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            for(;;) {
280aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                int c = missingChars.charAt(0);
281aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                if (c < 0) {
282aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    break;
283aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                }
284aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                int script = UScript.getScript(c);
285aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                missingScriptNames += " " +
286aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        UCharacter.getPropertyValueName(
287aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                UProperty.SCRIPT, script, UProperty.NameChoice.SHORT);
288aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                missingChars.removeAll(new UnicodeSet().applyIntPropertyValue(UProperty.SCRIPT, script));
289aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
290aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            errln("Missing character from:" + missingScriptNames + " -- " + missingScripts);
291aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
292aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
293aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
294aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private static final int getFirstRealScript(CharSequence s) {
295aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        for (int i = 0; i < s.length();) {
296aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            int c = Character.codePointAt(s, i);
297aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            int script = UScript.getScript(c);
298aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            if (script != UScript.UNKNOWN && script != UScript.INHERITED && script != UScript.COMMON) {
299aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                return script;
300aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
301aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            i += Character.charCount(c);
302aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
303aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        return UScript.UNKNOWN;
304aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
305aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
306f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
307aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public void TestBuckets() {
308aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        ULocale additionalLocale = ULocale.ENGLISH;
309aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
310aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        for (String[] pair : localeAndIndexCharactersLists) {
311aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            checkBuckets(pair[0], SimpleTests, additionalLocale, "E", "edgar", "Effron", "Effron");
312aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
313aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
314aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
315f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
316aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public void TestEmpty() {
317aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // just verify that it doesn't blow up.
318aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        Set<ULocale> locales = new LinkedHashSet<ULocale>();
319aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        locales.add(ULocale.ROOT);
320aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        locales.addAll(Arrays.asList(ULocale.getAvailableLocales()));
321aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        for (ULocale locale : locales) {
322aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            try {
323aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                AlphabeticIndex<String> alphabeticIndex = new AlphabeticIndex(locale);
324aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                alphabeticIndex.addRecord("hi", "HI");
325aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                for (Bucket<String> bucket : alphabeticIndex) {
326aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    @SuppressWarnings("unused")
327aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    LabelType labelType = bucket.getLabelType();
328aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                }
329aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            } catch (Exception e) {
330aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                errln("Exception when creating AlphabeticIndex for:\t" + locale.toLanguageTag());
331aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                errln(e.toString());
332aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
333aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
334aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
335aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
336f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
337f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    public void TestSetGetSpecialLabels() {
338f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        AlphabeticIndex index = new AlphabeticIndex(Locale.GERMAN).addLabels(new Locale("ru"));
339f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        index.setUnderflowLabel("__");
340f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        index.setInflowLabel("--");
341f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        index.setOverflowLabel("^^");
342f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        assertEquals("underflow label", "__", index.getUnderflowLabel());
343f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        assertEquals("inflow label", "--", index.getInflowLabel());
344f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        assertEquals("overflow label", "^^", index.getOverflowLabel());
345f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
346f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        ImmutableIndex ii = index.buildImmutableIndex();
347f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        assertEquals("0 -> underflow", "__", ii.getBucket(ii.getBucketIndex("0")).getLabel());
348f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        assertEquals("Ω -> inflow", "--", ii.getBucket(ii.getBucketIndex("Ω")).getLabel());
349f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        assertEquals("字 -> overflow", "^^", ii.getBucket(ii.getBucketIndex("字")).getLabel());
350f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    }
351f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
352f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
353aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public void TestInflow() {
354aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        Object[][] tests = {
355aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                {0, ULocale.ENGLISH},
356aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                {0, ULocale.ENGLISH, new ULocale("el")},
357aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                {1, ULocale.ENGLISH, new ULocale("ru")},
358aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                {0, ULocale.ENGLISH, new ULocale("el"), new UnicodeSet("[\u2C80]"), new ULocale("ru")},
359aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                {0, ULocale.ENGLISH},
360aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                {2, ULocale.ENGLISH, new ULocale("ru"), ULocale.JAPANESE},
361aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        };
362aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        for (Object[] test : tests) {
363aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            int expected = (Integer) test[0];
364aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            AlphabeticIndex<Double> alphabeticIndex = new AlphabeticIndex((ULocale)test[1]);
365aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            for (int i = 2; i < test.length; ++i) {
366aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                if (test[i] instanceof ULocale) {
367aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    alphabeticIndex.addLabels((ULocale)test[i]);
368aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                } else {
369aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    alphabeticIndex.addLabels((UnicodeSet)test[i]);
370aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                }
371aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
372aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            Counter<AlphabeticIndex.Bucket.LabelType> counter = new Counter();
373aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            for (Bucket<Double> bucket : alphabeticIndex) {
374aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                LabelType labelType = bucket.getLabelType();
375aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                counter.add(labelType, 1);
376aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
377aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            String printList = Arrays.asList(test).toString();
378aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            assertEquals(LabelType.UNDERFLOW + "\t" + printList, 1, counter.get(LabelType.UNDERFLOW));
379aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            assertEquals(LabelType.INFLOW + "\t" + printList, expected, counter.get(LabelType.INFLOW));
380aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            if (expected != counter.get(LabelType.INFLOW)) {
381aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                // for debugging
382aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                AlphabeticIndex<Double> indexCharacters2 = new AlphabeticIndex((ULocale)test[1]);
383aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                for (int i = 2; i < test.length; ++i) {
384aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    if (test[i] instanceof ULocale) {
385aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        indexCharacters2.addLabels((ULocale)test[i]);
386aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    } else {
387aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        indexCharacters2.addLabels((UnicodeSet)test[i]);
388aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    }
389aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                }
390aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                List<Bucket<Double>> buckets = CollectionUtilities.addAll(alphabeticIndex.iterator(), new ArrayList<Bucket<Double>>());
391aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                logln(buckets.toString());
392aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
393aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            assertEquals(LabelType.OVERFLOW + "\t" + printList, 1, counter.get(LabelType.OVERFLOW));
394aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
395aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
396aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
397aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private void checkBuckets(String localeString, String[] test, ULocale additionalLocale, String testBucket, String... items) {
398aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        StringBuilder UI = new StringBuilder();
399aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        ULocale desiredLocale = new ULocale(localeString);
400aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
401aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // Create a simple index where the values for the strings are Integers, and add the strings
402aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        AlphabeticIndex<Integer> index = new AlphabeticIndex<Integer>(desiredLocale).addLabels(additionalLocale);
403aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        int counter = 0;
404aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        Counter<String> itemCount = new Counter();
405aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        for (String item : test) {
406f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            index.addRecord(item, counter++);
407aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            itemCount.add(item, 1);
408aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
409f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        assertEquals("getRecordCount()", (int)itemCount.getTotal(), index.getRecordCount());  // code coverage
410aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
411aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        List<String> labels = index.getBucketLabels();
412aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        ImmutableIndex<Integer> immIndex = index.buildImmutableIndex();
413aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
414aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        logln(desiredLocale + "\t" + desiredLocale.getDisplayName(ULocale.ENGLISH) + " - " + desiredLocale.getDisplayName(desiredLocale) + "\t"
415aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                + index.getCollator().getLocale(ULocale.ACTUAL_LOCALE));
416aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        UI.setLength(0);
417aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        UI.append(desiredLocale + "\t");
418aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        boolean showAll = true;
419aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
420aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // Show index at top. We could skip or gray out empty buckets
421aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        for (AlphabeticIndex.Bucket<Integer> bucket : index) {
422aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            if (showAll || bucket.size() != 0) {
423aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                showLabelAtTop(UI, bucket.getLabel());
424aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
425aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
426aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        logln(UI.toString());
427aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
428aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // Show the buckets with their contents, skipping empty buckets
429aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        int bucketIndex = 0;
430aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        for (Bucket<Integer> bucket : index) {
431aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            assertEquals("bucket label vs. iterator",
432aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    labels.get(bucketIndex), bucket.getLabel());
433aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            assertEquals("bucket label vs. immutable",
434aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    labels.get(bucketIndex), immIndex.getBucket(bucketIndex).getLabel());
435aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            assertEquals("bucket label type vs. immutable",
436aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    bucket.getLabelType(), immIndex.getBucket(bucketIndex).getLabelType());
437aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            for (Record<Integer> r : bucket) {
438aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                CharSequence name = r.getName();
439aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                assertEquals("getBucketIndex(" + name + ")",
440aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        bucketIndex, index.getBucketIndex(name));
441aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                assertEquals("immutable getBucketIndex(" + name + ")",
442aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        bucketIndex, immIndex.getBucketIndex(name));
443aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
444aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            if (bucket.getLabel().equals(testBucket)) {
445aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                Counter<String> keys = getKeys(bucket);
446aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                for (String item : items) {
447aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    long globalCount = itemCount.get(item);
448aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    long localeCount = keys.get(item);
449aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    if (globalCount != localeCount) {
450aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        errln("Error: in " + "'" + testBucket + "', '" + item + "' should have count "
451aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                + globalCount + " but has count " + localeCount);
452aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    }
453aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
454aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                }
455aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
456aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
457aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            if (bucket.size() != 0) {
458aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                showLabelInList(UI, bucket.getLabel());
459aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                for (AlphabeticIndex.Record<Integer> item : bucket) {
460aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    showIndexedItem(UI, item.getName(), item.getData());
461aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                }
462aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                logln(UI.toString());
463aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
464aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            ++bucketIndex;
465aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
466aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        assertEquals("getBucketCount()", bucketIndex, index.getBucketCount());
467aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        assertEquals("immutable getBucketCount()", bucketIndex, immIndex.getBucketCount());
468aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
469aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        assertNull("immutable getBucket(-1)", immIndex.getBucket(-1));
470aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        assertNull("immutable getBucket(count)", immIndex.getBucket(bucketIndex));
471aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
472aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        for (Bucket<Integer> bucket : immIndex) {
473aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            assertEquals("immutable bucket size", 0, bucket.size());
474aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            assertFalse("immutable bucket iterator.hasNext()", bucket.iterator().hasNext());
475aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
476aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
477aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
478aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public <T> void showIndex(AlphabeticIndex<T> index, boolean showEmpty) {
479aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        logln("Actual");
480aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        StringBuilder UI = new StringBuilder();
481aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        for (Bucket<T> bucket : index) {
482aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            if (showEmpty || bucket.size() != 0) {
483aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                showLabelInList(UI, bucket.getLabel());
484aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                for (Record<T> item : bucket) {
485aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    showIndexedItem(UI, item.getName(), item.getData());
486aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                }
487aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                logln(UI.toString());
488aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
489aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
490aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
491aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
492aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    /**
493aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * @param myBucketLabels
494aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * @param myBucketContents
495aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * @param b
496aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     */
497aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private void showIndex(List<String> myBucketLabels, ArrayList<Set<R4<RawCollationKey, String, Integer, Double>>> myBucketContents, boolean showEmpty) {
498aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        logln("Alternative");
499aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        StringBuilder UI = new StringBuilder();
500aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
501aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        for (int i = 0; i < myBucketLabels.size(); ++i) {
502aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            Set<R4<RawCollationKey, String, Integer, Double>> bucket = myBucketContents.get(i);
503aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            if (!showEmpty && bucket.size() == 0) {
504aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                continue;
505aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
506aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            UI.setLength(0);
507aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            UI.append("*").append(myBucketLabels.get(i));
508aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            for (R4<RawCollationKey, String, Integer, Double> item : bucket) {
509aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                UI.append("\t ").append(item.get1().toString()).append(ARROW).append(item.get3().toString());
510aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
511aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            logln(UI.toString());
512aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
513aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
514aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
515aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private void showLabelAtTop(StringBuilder buffer, String label) {
516aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        buffer.append(label + " ");
517aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
518aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
519aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private <T> void showIndexedItem(StringBuilder buffer, CharSequence key, T value) {
520aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        buffer.append("\t " + key + ARROW + value);
521aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
522aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
523aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private void showLabelInList(StringBuilder buffer, String label) {
524aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        buffer.setLength(0);
525aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        buffer.append(label);
526aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
527aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
528aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private Counter<String> getKeys(AlphabeticIndex.Bucket<Integer> entry) {
529aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        Counter<String> keys = new Counter<String>();
530aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        for (AlphabeticIndex.Record x : entry) {
531aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            String key = x.getName().toString();
532aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            keys.add(key, 1);
533aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
534aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        return keys;
535aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
536aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
537f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
538aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public void TestIndexCharactersList() {
539aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        for (String[] localeAndIndexCharacters : localeAndIndexCharactersLists) {
540aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            ULocale locale = new ULocale(localeAndIndexCharacters[0]);
541aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            String expectedIndexCharacters = "\u2026:" + localeAndIndexCharacters[1] + ":\u2026";
542aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            Collection<String> alphabeticIndex = new AlphabeticIndex(locale).getBucketLabels();
543aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
544aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            // Join the elements of the list to a string with delimiter ":"
545aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            StringBuilder sb = new StringBuilder();
546aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            Iterator<String> iter = alphabeticIndex.iterator();
547aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            while (iter.hasNext()) {
548aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                sb.append(iter.next());
549aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                if (!iter.hasNext()) {
550aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    break;
551aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                }
552aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                sb.append(":");
553aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
554aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            String actualIndexCharacters = sb.toString();
555aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            if (!expectedIndexCharacters.equals(actualIndexCharacters)) {
556aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                errln("Test failed for locale " + localeAndIndexCharacters[0] +
557aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        "\n  Expected = |" + expectedIndexCharacters + "|\n  actual   = |" + actualIndexCharacters + "|");
558aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
559aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
560aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
561aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
562f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
563aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public void TestBasics() {
564aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        ULocale[] list = ULocale.getAvailableLocales();
565aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // get keywords combinations
566aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // don't bother with multiple combinations at this point
567aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        List keywords = new ArrayList();
568aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        keywords.add("");
569aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
570aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        String[] collationValues = Collator.getKeywordValues("collation");
571aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        for (int j = 0; j < collationValues.length; ++j) {
572aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            keywords.add("@collation=" + collationValues[j]);
573aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
574aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
575aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        for (int i = 0; i < list.length; ++i) {
576aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            for (Iterator it = keywords.iterator(); it.hasNext();) {
577aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                String collationValue = (String) it.next();
578aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                String localeString = list[i].toString();
579aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                if (!KEY_LOCALES.contains(localeString)) continue; // TODO change in exhaustive
580aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                ULocale locale = new ULocale(localeString + collationValue);
581aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                if (collationValue.length() > 0 && !Collator.getFunctionalEquivalent("collation", locale).equals(locale)) {
582aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    //logln("Skipping " + locale);
583aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    continue;
584aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                }
585aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
586aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                if (locale.getCountry().length() != 0) {
587aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    continue;
588aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                }
589aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                boolean isUnihan = collationValue.contains("unihan");
590aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                AlphabeticIndex alphabeticIndex = new AlphabeticIndex(locale);
591aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                if (isUnihan) {
592aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    // Unihan tailorings have a label per radical, and there are at least 214,
593aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    // if not more when simplified radicals are distinguished.
594aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    alphabeticIndex.setMaxLabelCount(500);
595aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                }
596aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                final Collection mainChars = alphabeticIndex.getBucketLabels();
597aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                String mainCharString = mainChars.toString();
598aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                if (mainCharString.length() > 500) {
599aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    mainCharString = mainCharString.substring(0,500) + "...";
600aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                }
601aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                logln(mainChars.size() + "\t" + locale + "\t" + locale.getDisplayName(ULocale.ENGLISH));
602aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                logln("Index:\t" + mainCharString);
603aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                if (!isUnihan && mainChars.size() > 100) {
604aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    errln("Index character set too large: " +
605aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                            locale + " [" + mainChars.size() + "]:\n    " + mainChars);
606aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                }
607aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
608aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
609aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
610aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
611f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
612aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public void TestClientSupport() {
613aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        for (String localeString : new String[] {"zh"}) { // KEY_LOCALES, new String[] {"zh"}
614aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            ULocale ulocale = new ULocale(localeString);
615f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            AlphabeticIndex<Double> alphabeticIndex = new AlphabeticIndex<Double>(ulocale).addLabels(Locale.ENGLISH);
616aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            RuleBasedCollator collator = alphabeticIndex.getCollator();
617aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            String [][] tests;
618aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
619aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            if (!localeString.equals("zh") ) {
620aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                tests = new String[][] {SimpleTests};
621aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            } else {
622aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                tests = new String[][] {SimpleTests, hackPinyin, simplifiedNames};
623aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
624aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
625aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            for (String [] shortTest : tests) {
626aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                double testValue = 100;
627aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                alphabeticIndex.clearRecords();
628aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                for (String name : shortTest) {
629aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    alphabeticIndex.addRecord(name, testValue++);
630aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                }
631aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
632aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                if (DEBUG) showIndex(alphabeticIndex, false);
633aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
634aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                // make my own copy
635aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                testValue = 100;
636aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                List<String> myBucketLabels = alphabeticIndex.getBucketLabels();
637aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                ArrayList<Set<R4<RawCollationKey, String, Integer, Double>>> myBucketContents = new ArrayList<Set<R4<RawCollationKey, String, Integer, Double>>>(myBucketLabels.size());
638aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                for (int i = 0; i < myBucketLabels.size(); ++i) {
639aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    myBucketContents.add(new TreeSet<R4<RawCollationKey, String, Integer, Double>>());
640aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                }
641aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                for (String name : shortTest) {
642aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    int bucketIndex = alphabeticIndex.getBucketIndex(name);
643aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    if (bucketIndex > myBucketContents.size()) {
644aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        alphabeticIndex.getBucketIndex(name); // call again for debugging
645aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    }
646aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    Set<R4<RawCollationKey, String, Integer, Double>> myBucket = myBucketContents.get(bucketIndex);
647aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    RawCollationKey rawCollationKey = collator.getRawCollationKey(name, null);
648aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    R4<RawCollationKey, String, Integer, Double> row = Row.of(rawCollationKey, name, name.length(), testValue++);
649aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    myBucket.add(row);
650aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                }
651aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                if (DEBUG) showIndex(myBucketLabels, myBucketContents, false);
652aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
653aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                // now compare
654aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                int index = 0;
655aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                boolean gotError = false;
656aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                for (AlphabeticIndex.Bucket<Double> bucket : alphabeticIndex) {
657aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    String bucketLabel = bucket.getLabel();
658aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    String myLabel = myBucketLabels.get(index);
659aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    if (!bucketLabel.equals(myLabel)) {
660aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        gotError |= !assertEquals(ulocale + "\tBucket Labels (" + index + ")", bucketLabel, myLabel);
661aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    }
662aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    Set<R4<RawCollationKey, String, Integer, Double>> myBucket = myBucketContents.get(index);
663aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    Iterator<R4<RawCollationKey, String, Integer, Double>> myBucketIterator = myBucket.iterator();
664aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    int recordIndex = 0;
665aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    for (Record<Double> record : bucket) {
666aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        String myName = null;
667aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        if (myBucketIterator.hasNext()) {
668aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                            R4<RawCollationKey, String, Integer, Double> myRecord = myBucketIterator.next();
669f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                            myName = myRecord.get1();
670aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        }
671aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        if (!record.getName().equals(myName)) {
672aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                            gotError |= !assertEquals(ulocale + "\t" + bucketLabel + "\t" + "Record Names (" + index + "." + recordIndex++ + ")", record.getName(), myName);
673aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        }
674aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    }
675aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    while (myBucketIterator.hasNext()) {
676aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        R4<RawCollationKey, String, Integer, Double> myRecord = myBucketIterator.next();
677f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                        String myName = myRecord.get1();
678aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        gotError |= !assertEquals(ulocale + "\t" + bucketLabel + "\t" + "Record Names (" + index + "." + recordIndex++ + ")", null, myName);
679aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    }
680aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    index++;
681aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                }
682aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                if (gotError) {
683aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    showIndex(myBucketLabels, myBucketContents, false);
684aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    showIndex(alphabeticIndex, false);
685aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                }
686aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
687aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
688aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
689aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
690f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
691aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public void TestFirstScriptCharacters() {
692aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        Collection<String> firstCharacters =
693aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                new AlphabeticIndex(ULocale.ENGLISH).getFirstCharactersInScripts();
694aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        Collection<String> expectedFirstCharacters = firstStringsInScript((RuleBasedCollator) Collator.getInstance(ULocale.ROOT));
695aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        Collection<String> diff = new TreeSet<String>(firstCharacters);
696aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        diff.removeAll(expectedFirstCharacters);
697aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        assertTrue("First Characters contains unexpected ones: " + diff, diff.isEmpty());
698aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        diff.clear();
699aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        diff.addAll(expectedFirstCharacters);
700aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        diff.removeAll(firstCharacters);
701aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        assertTrue("First Characters missing expected ones: " + diff, diff.isEmpty());
702aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
703aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
704aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private static final UnicodeSet TO_TRY = new UnicodeSet("[[:^nfcqc=no:]-[:sc=Common:]-[:sc=Inherited:]-[:sc=Unknown:]]").freeze();
705aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
706aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    /**
707aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * Returns a collection of all the "First" characters of scripts, according to the collation.
708aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     */
709aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private static Collection<String> firstStringsInScript(RuleBasedCollator ruleBasedCollator) {
710aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        String[] results = new String[UScript.CODE_LIMIT];
711aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        for (String current : TO_TRY) {
712aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            if (ruleBasedCollator.compare(current, "a") < 0) { // we only want "real" script characters, not symbols.
713aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                continue;
714aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
715aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            int script = UScript.getScript(current.codePointAt(0));
716aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            if (results[script] == null) {
717aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                results[script] = current;
718aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            } else if (ruleBasedCollator.compare(current, results[script]) < 0) {
719aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                results[script] = current;
720aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
721aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
722aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
723aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        try {
724aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            UnicodeSet extras = new UnicodeSet();
725aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            UnicodeSet expansions = new UnicodeSet();
726aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            ruleBasedCollator.getContractionsAndExpansions(extras, expansions, true);
727aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            extras.addAll(expansions).removeAll(TO_TRY);
728aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            if (extras.size() != 0) {
729aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                Normalizer2 normalizer = Normalizer2.getNFKCInstance();
730aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                for (String current : extras) {
731aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    if (!normalizer.isNormalized(current) || ruleBasedCollator.compare(current, "9") <= 0) {
732aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        continue;
733aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    }
734aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    int script = getFirstRealScript(current);
735aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    if (script == UScript.UNKNOWN && !isUnassignedBoundary(current)) { continue; }
736aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    if (results[script] == null) {
737aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        results[script] = current;
738aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    } else if (ruleBasedCollator.compare(current, results[script]) < 0) {
739aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        results[script] = current;
740aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    }
741aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                }
742aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
743aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        } catch (Exception e) {
744aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        } // why have a checked exception???
745aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
746aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // TODO: We should not test that we get the same strings, but that we
747aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // get strings that sort primary-equal to those from the implementation.
748aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
749aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        Collection<String> result = new ArrayList<String>();
750aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        for (int i = 0; i < results.length; ++i) {
751aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            if (results[i] != null) {
752aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                result.add(results[i]);
753aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
754aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
755aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        return result;
756aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
757aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
758aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private static final boolean isUnassignedBoundary(CharSequence s) {
759aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // The root collator provides a script-first-primary boundary contraction
760aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // for the unassigned-implicit range.
761aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        return s.charAt(0) == 0xfdd1 &&
762aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                UScript.getScript(Character.codePointAt(s, 1)) == UScript.UNKNOWN;
763aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
764aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
765f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
766aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public void TestZZZ() {
767aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        //            int x = 3;
768aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        //            AlphabeticIndex index = new AlphabeticIndex(ULocale.ENGLISH);
769aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        //            UnicodeSet additions = new UnicodeSet();
770aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        //            additions.add(0x410).add(0x415);  // Cyrillic
771aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        //            // additions.add(0x391).add(0x393);     // Greek
772aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        //            index.addLabels(additions);
773aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        //            int lc = index.getLabels().size();
774aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        //            List  labels = index.getLabels();
775aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        //            System.out.println("Label Count = " + lc + "\t" + labels);
776aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        //            System.out.println("Bucket Count =" + index.getBucketCount());
777aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
778aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
779f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
780aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public void TestSimplified() {
781aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        checkBuckets("zh", simplifiedNames, ULocale.ENGLISH, "W", "\u897f");
782aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
783f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
784f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
785aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public void TestTraditional() {
786aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        checkBuckets("zh_Hant", traditionalNames, ULocale.ENGLISH, "\u4e9f", "\u5357\u9580");
787aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
788aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
789f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    static final String[] SimpleTests = {
790aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "斎藤",
791f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        "\u1f2d\u03c1\u03b1",
792f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        "$", "\u00a3", "12", "2",
793aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "Davis", "Davis", "Abbot", "\u1D05avis", "Zach", "\u1D05avis", "\u01b5", "\u0130stanbul", "Istanbul", "istanbul", "\u0131stanbul",
794aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u00deor", "\u00c5berg", "\u00d6stlund",
795f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        "\u1f2d\u03c1\u03b1", "\u1f08\u03b8\u03b7\u03bd\u1fb6",
796f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        "\u0396\u03b5\u03cd\u03c2", "\u03a0\u03bf\u03c3\u03b5\u03b9\u03b4\u1f63\u03bd", "\u1f0d\u03b9\u03b4\u03b7\u03c2", "\u0394\u03b7\u03bc\u03ae\u03c4\u03b7\u03c1", "\u1f19\u03c3\u03c4\u03b9\u03ac",
797aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        //"\u1f08\u03c0\u03cc\u03bb\u03bb\u03c9\u03bd", "\u1f0c\u03c1\u03c4\u03b5\u03bc\u03b9\u03c2", "\u1f19\u03c1\u03bc\u1f23\u03c2", "\u1f0c\u03c1\u03b7\u03c2", "\u1f08\u03c6\u03c1\u03bf\u03b4\u03af\u03c4\u03b7", "\u1f2d\u03c6\u03b1\u03b9\u03c3\u03c4\u03bf\u03c2", "\u0394\u03b9\u03cc\u03bd\u03c5\u03c3\u03bf\u03c2",
798aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u6589\u85e4", "\u4f50\u85e4", "\u9234\u6728", "\u9ad8\u6a4b", "\u7530\u4e2d", "\u6e21\u8fba", "\u4f0a\u85e4", "\u5c71\u672c", "\u4e2d\u6751", "\u5c0f\u6797", "\u658e\u85e4", "\u52a0\u85e4",
799aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        //"\u5409\u7530", "\u5c71\u7530", "\u4f50\u3005\u6728", "\u5c71\u53e3", "\u677e\u672c", "\u4e95\u4e0a", "\u6728\u6751", "\u6797", "\u6e05\u6c34"
800aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    };
801aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
802f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    static final String[] hackPinyin = {
803aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "a", "\u5416", "\u58ba", //
804aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "b", "\u516b", "\u62d4", "\u8500", //
805aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "c", "\u5693", "\u7938", "\u9e7e", //
806aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "d", "\u5491", "\u8fcf", "\u964a", //
807aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "e","\u59b8", "\u92e8", "\u834b", //
808aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "f", "\u53d1", "\u9197", "\u99a5", //
809aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "g", "\u7324", "\u91d3", "\u8142", //
810aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "h", "\u598e", "\u927f", "\u593b", //
811aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "j", "\u4e0c", "\u6785", "\u9d58", //
812aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "k", "\u5494", "\u958b", "\u7a52", //
813aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "l", "\u5783", "\u62c9", "\u9ba5", //
814aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "m", "\u5638", "\u9ebb", "\u65c0", //
815aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "n", "\u62ff", "\u80ad", "\u685b", //
816aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "o", "\u5662", "\u6bee", "\u8bb4", //
817aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "p", "\u5991", "\u8019", "\u8c31", //
818aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "q", "\u4e03", "\u6053", "\u7f56", //
819aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "r", "\u5465", "\u72aa", "\u6e03", //
820aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "s", "\u4ee8", "\u9491", "\u93c1", //
821aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "t", "\u4ed6", "\u9248", "\u67dd", //
822aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "w", "\u5c72", "\u5558", "\u5a7a", //
823aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "x", "\u5915", "\u5438", "\u6bbe", //
824aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "y", "\u4e2b", "\u82bd", "\u8574", //
825aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "z", "\u5e00", "\u707d", "\u5c0a"
826aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    };
827aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
828f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    static final String[] simplifiedNames = {
829aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "Abbot", "Morton", "Zachary", "Williams", "\u8d75", "\u94b1", "\u5b59", "\u674e", "\u5468", "\u5434", "\u90d1", "\u738b", "\u51af", "\u9648", "\u696e", "\u536b", "\u848b", "\u6c88",
830aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u97e9", "\u6768", "\u6731", "\u79e6", "\u5c24", "\u8bb8", "\u4f55", "\u5415", "\u65bd", "\u5f20", "\u5b54", "\u66f9", "\u4e25", "\u534e", "\u91d1", "\u9b4f", "\u9676", "\u59dc", "\u621a", "\u8c22", "\u90b9",
831aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u55bb", "\u67cf", "\u6c34", "\u7aa6", "\u7ae0", "\u4e91", "\u82cf", "\u6f58", "\u845b", "\u595a", "\u8303", "\u5f6d", "\u90ce", "\u9c81", "\u97e6", "\u660c", "\u9a6c", "\u82d7", "\u51e4", "\u82b1", "\u65b9",
832aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u4fde", "\u4efb", "\u8881", "\u67f3", "\u9146", "\u9c8d", "\u53f2", "\u5510", "\u8d39", "\u5ec9", "\u5c91", "\u859b", "\u96f7", "\u8d3a", "\u502a", "\u6c64", "\u6ed5", "\u6bb7", "\u7f57", "\u6bd5", "\u90dd",
833aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u90ac", "\u5b89", "\u5e38", "\u4e50", "\u4e8e", "\u65f6", "\u5085", "\u76ae", "\u535e", "\u9f50", "\u5eb7", "\u4f0d", "\u4f59", "\u5143", "\u535c", "\u987e", "\u5b5f", "\u5e73", "\u9ec4", "\u548c", "\u7a46",
834aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u8427", "\u5c39", "\u59da", "\u90b5", "\u6e5b", "\u6c6a", "\u7941", "\u6bdb", "\u79b9", "\u72c4", "\u7c73", "\u8d1d", "\u660e", "\u81e7", "\u8ba1", "\u4f0f", "\u6210", "\u6234", "\u8c08", "\u5b8b", "\u8305",
835aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u5e9e", "\u718a", "\u7eaa", "\u8212", "\u5c48", "\u9879", "\u795d", "\u8463", "\u6881", "\u675c", "\u962e", "\u84dd", "\u95fd", "\u5e2d", "\u5b63", "\u9ebb", "\u5f3a", "\u8d3e", "\u8def", "\u5a04", "\u5371",
836aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u6c5f", "\u7ae5", "\u989c", "\u90ed", "\u6885", "\u76db", "\u6797", "\u5201", "\u953a", "\u5f90", "\u4e18", "\u9a86", "\u9ad8", "\u590f", "\u8521", "\u7530", "\u6a0a", "\u80e1", "\u51cc", "\u970d", "\u865e",
837aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u4e07", "\u652f", "\u67ef", "\u661d", "\u7ba1", "\u5362", "\u83ab", "\u7ecf", "\u623f", "\u88d8", "\u7f2a", "\u5e72", "\u89e3", "\u5e94", "\u5b97", "\u4e01", "\u5ba3", "\u8d32", "\u9093", "\u90c1", "\u5355",
838aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u676d", "\u6d2a", "\u5305", "\u8bf8", "\u5de6", "\u77f3", "\u5d14", "\u5409", "\u94ae", "\u9f9a", "\u7a0b", "\u5d47", "\u90a2", "\u6ed1", "\u88f4", "\u9646", "\u8363", "\u7fc1", "\u8340", "\u7f8a", "\u65bc",
839aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u60e0", "\u7504", "\u9eb9", "\u5bb6", "\u5c01", "\u82ae", "\u7fbf", "\u50a8", "\u9773", "\u6c72", "\u90b4", "\u7cdc", "\u677e", "\u4e95", "\u6bb5", "\u5bcc", "\u5deb", "\u4e4c", "\u7126", "\u5df4", "\u5f13",
840aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u7267", "\u9697", "\u5c71", "\u8c37", "\u8f66", "\u4faf", "\u5b93", "\u84ec", "\u5168", "\u90d7", "\u73ed", "\u4ef0", "\u79cb", "\u4ef2", "\u4f0a", "\u5bab", "\u5b81", "\u4ec7", "\u683e", "\u66b4", "\u7518",
841aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u659c", "\u5389", "\u620e", "\u7956", "\u6b66", "\u7b26", "\u5218", "\u666f", "\u8a79", "\u675f", "\u9f99", "\u53f6", "\u5e78", "\u53f8", "\u97f6", "\u90dc", "\u9ece", "\u84df", "\u8584", "\u5370", "\u5bbf",
842aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u767d", "\u6000", "\u84b2", "\u90b0", "\u4ece", "\u9102", "\u7d22", "\u54b8", "\u7c4d", "\u8d56", "\u5353", "\u853a", "\u5c60", "\u8499", "\u6c60", "\u4e54", "\u9634", "\u90c1", "\u80e5", "\u80fd", "\u82cd",
843aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u53cc", "\u95fb", "\u8398", "\u515a", "\u7fdf", "\u8c2d", "\u8d21", "\u52b3", "\u9004", "\u59ec", "\u7533", "\u6276", "\u5835", "\u5189", "\u5bb0", "\u90e6", "\u96cd", "\u90e4", "\u74a9", "\u6851", "\u6842",
844aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u6fee", "\u725b", "\u5bff", "\u901a", "\u8fb9", "\u6248", "\u71d5", "\u5180", "\u90cf", "\u6d66", "\u5c1a", "\u519c", "\u6e29", "\u522b", "\u5e84", "\u664f", "\u67f4", "\u77bf", "\u960e", "\u5145", "\u6155",
845aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u8fde", "\u8339", "\u4e60", "\u5ba6", "\u827e", "\u9c7c", "\u5bb9", "\u5411", "\u53e4", "\u6613", "\u614e", "\u6208", "\u5ed6", "\u5ebe", "\u7ec8", "\u66a8", "\u5c45", "\u8861", "\u6b65", "\u90fd", "\u803f",
846aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u6ee1", "\u5f18", "\u5321", "\u56fd", "\u6587", "\u5bc7", "\u5e7f", "\u7984", "\u9619", "\u4e1c", "\u6b27", "\u6bb3", "\u6c83", "\u5229", "\u851a", "\u8d8a", "\u5914", "\u9686", "\u5e08", "\u5de9", "\u538d",
847aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u8042", "\u6641", "\u52fe", "\u6556", "\u878d", "\u51b7", "\u8a3e", "\u8f9b", "\u961a", "\u90a3", "\u7b80", "\u9976", "\u7a7a", "\u66fe", "\u6bcb", "\u6c99", "\u4e5c", "\u517b", "\u97a0", "\u987b", "\u4e30",
848aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u5de2", "\u5173", "\u84af", "\u76f8", "\u67e5", "\u540e", "\u8346", "\u7ea2", "\u6e38", "\u7afa", "\u6743", "\u9011", "\u76d6", "\u76ca", "\u6853", "\u516c", "\u4e07\u4fdf", "\u53f8\u9a6c", "\u4e0a\u5b98", "\u6b27\u9633",
849aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u590f\u4faf", "\u8bf8\u845b", "\u95fb\u4eba", "\u4e1c\u65b9", "\u8d6b\u8fde", "\u7687\u752b", "\u5c09\u8fdf", "\u516c\u7f8a", "\u6fb9\u53f0", "\u516c\u51b6", "\u5b97\u653f", "\u6fee\u9633", "\u6df3\u4e8e", "\u5355\u4e8e", "\u592a\u53d4", "\u7533\u5c60", "\u516c\u5b59", "\u4ef2\u5b59",
850aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u8f69\u8f95", "\u4ee4\u72d0", "\u953a\u79bb", "\u5b87\u6587", "\u957f\u5b59", "\u6155\u5bb9", "\u9c9c\u4e8e", "\u95fe\u4e18", "\u53f8\u5f92", "\u53f8\u7a7a", "\u4e0c\u5b98", "\u53f8\u5bc7", "\u4ec9", "\u7763", "\u5b50\u8f66", "\u989b\u5b59", "\u7aef\u6728", "\u5deb\u9a6c",
851aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u516c\u897f", "\u6f06\u96d5", "\u4e50\u6b63", "\u58e4\u9a77", "\u516c\u826f", "\u62d3\u62d4", "\u5939\u8c37", "\u5bb0\u7236", "\u8c37\u6881", "\u664b", "\u695a", "\u960e", "\u6cd5", "\u6c5d", "\u9122", "\u6d82", "\u94a6", "\u6bb5\u5e72", "\u767e\u91cc",
852aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u4e1c\u90ed", "\u5357\u95e8", "\u547c\u5ef6", "\u5f52", "\u6d77", "\u7f8a\u820c", "\u5fae\u751f", "\u5cb3", "\u5e05", "\u7f11", "\u4ea2", "\u51b5", "\u540e", "\u6709", "\u7434", "\u6881\u4e18", "\u5de6\u4e18", "\u4e1c\u95e8", "\u897f\u95e8",
853aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u5546", "\u725f", "\u4f58", "\u4f74", "\u4f2f", "\u8d4f", "\u5357\u5bab", "\u58a8", "\u54c8", "\u8c2f", "\u7b2a", "\u5e74", "\u7231", "\u9633", "\u4f5f"
854aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    };
855aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
856aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    static final String[] traditionalNames = { "丁", "Abbot", "Morton", "Zachary", "Williams", "\u8d99", "\u9322", "\u5b6b",
857aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u674e", "\u5468", "\u5433", "\u912d", "\u738b", "\u99ae", "\u9673", "\u696e", "\u885b", "\u8523",
858aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u6c88", "\u97d3", "\u694a", "\u6731", "\u79e6", "\u5c24", "\u8a31", "\u4f55", "\u5442", "\u65bd",
859aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u5f35", "\u5b54", "\u66f9", "\u56b4", "\u83ef", "\u91d1", "\u9b4f", "\u9676", "\u59dc", "\u621a",
860aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u8b1d", "\u9112", "\u55bb", "\u67cf", "\u6c34", "\u7ac7", "\u7ae0", "\u96f2", "\u8607", "\u6f58",
861aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u845b", "\u595a", "\u7bc4", "\u5f6d", "\u90ce", "\u9b6f", "\u97cb", "\u660c", "\u99ac", "\u82d7",
862aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u9cf3", "\u82b1", "\u65b9", "\u4fde", "\u4efb", "\u8881", "\u67f3", "\u9146", "\u9b91", "\u53f2",
863aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u5510", "\u8cbb", "\u5ec9", "\u5c91", "\u859b", "\u96f7", "\u8cc0", "\u502a", "\u6e6f", "\u6ed5",
864aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u6bb7", "\u7f85", "\u7562", "\u90dd", "\u9114", "\u5b89", "\u5e38", "\u6a02", "\u65bc", "\u6642",
865aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u5085", "\u76ae", "\u535e", "\u9f4a", "\u5eb7", "\u4f0d", "\u9918", "\u5143", "\u535c", "\u9867",
866aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u5b5f", "\u5e73", "\u9ec3", "\u548c", "\u7a46", "\u856d", "\u5c39", "\u59da", "\u90b5", "\u6e5b",
867aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u6c6a", "\u7941", "\u6bdb", "\u79b9", "\u72c4", "\u7c73", "\u8c9d", "\u660e", "\u81e7", "\u8a08",
868aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u4f0f", "\u6210", "\u6234", "\u8ac7", "\u5b8b", "\u8305", "\u9f90", "\u718a", "\u7d00", "\u8212",
869aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u5c48", "\u9805", "\u795d", "\u8463", "\u6881", "\u675c", "\u962e", "\u85cd", "\u95a9", "\u5e2d",
870aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u5b63", "\u9ebb", "\u5f37", "\u8cc8", "\u8def", "\u5a41", "\u5371", "\u6c5f", "\u7ae5", "\u984f",
871aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u90ed", "\u6885", "\u76db", "\u6797", "\u5201", "\u937e", "\u5f90", "\u4e18", "\u99f1", "\u9ad8",
872aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u590f", "\u8521", "\u7530", "\u6a0a", "\u80e1", "\u51cc", "\u970d", "\u865e", "\u842c", "\u652f",
873aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u67ef", "\u661d", "\u7ba1", "\u76e7", "\u83ab", "\u7d93", "\u623f", "\u88d8", "\u7e46", "\u5e79",
874aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u89e3", "\u61c9", "\u5b97", "\u4e01", "\u5ba3", "\u8cc1", "\u9127", "\u9b31", "\u55ae", "\u676d",
875aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u6d2a", "\u5305", "\u8af8", "\u5de6", "\u77f3", "\u5d14", "\u5409", "\u9215", "\u9f94", "\u7a0b",
876aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u5d47", "\u90a2", "\u6ed1", "\u88f4", "\u9678", "\u69ae", "\u7fc1", "\u8340", "\u7f8a", "\u65bc",
877aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u60e0", "\u7504", "\u9eb4", "\u5bb6", "\u5c01", "\u82ae", "\u7fbf", "\u5132", "\u9773", "\u6c72",
878aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u90b4", "\u7cdc", "\u677e", "\u4e95", "\u6bb5", "\u5bcc", "\u5deb", "\u70cf", "\u7126", "\u5df4",
879aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u5f13", "\u7267", "\u9697", "\u5c71", "\u8c37", "\u8eca", "\u4faf", "\u5b93", "\u84ec", "\u5168",
880aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u90d7", "\u73ed", "\u4ef0", "\u79cb", "\u4ef2", "\u4f0a", "\u5bae", "\u5be7", "\u4ec7", "\u6b12",
881aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u66b4", "\u7518", "\u659c", "\u53b2", "\u620e", "\u7956", "\u6b66", "\u7b26", "\u5289", "\u666f",
882aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u8a79", "\u675f", "\u9f8d", "\u8449", "\u5e78", "\u53f8", "\u97f6", "\u90dc", "\u9ece", "\u858a",
883aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u8584", "\u5370", "\u5bbf", "\u767d", "\u61f7", "\u84b2", "\u90b0", "\u5f9e", "\u9102", "\u7d22",
884aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u54b8", "\u7c4d", "\u8cf4", "\u5353", "\u85fa", "\u5c60", "\u8499", "\u6c60", "\u55ac", "\u9670",
885aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u9b31", "\u80e5", "\u80fd", "\u84bc", "\u96d9", "\u805e", "\u8398", "\u9ee8", "\u7fdf", "\u8b5a",
886aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u8ca2", "\u52de", "\u9004", "\u59ec", "\u7533", "\u6276", "\u5835", "\u5189", "\u5bb0", "\u9148",
887aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u96cd", "\u90e4", "\u74a9", "\u6851", "\u6842", "\u6fee", "\u725b", "\u58fd", "\u901a", "\u908a",
888aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u6248", "\u71d5", "\u5180", "\u90df", "\u6d66", "\u5c1a", "\u8fb2", "\u6eab", "\u5225", "\u838a",
889aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u664f", "\u67f4", "\u77bf", "\u95bb", "\u5145", "\u6155", "\u9023", "\u8339", "\u7fd2", "\u5ba6",
890aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u827e", "\u9b5a", "\u5bb9", "\u5411", "\u53e4", "\u6613", "\u614e", "\u6208", "\u5ed6", "\u5ebe",
891aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u7d42", "\u66a8", "\u5c45", "\u8861", "\u6b65", "\u90fd", "\u803f", "\u6eff", "\u5f18", "\u5321",
892aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u570b", "\u6587", "\u5bc7", "\u5ee3", "\u797f", "\u95d5", "\u6771", "\u6b50", "\u6bb3", "\u6c83",
893aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u5229", "\u851a", "\u8d8a", "\u5914", "\u9686", "\u5e2b", "\u978f", "\u5399", "\u8076", "\u6641",
894aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u52fe", "\u6556", "\u878d", "\u51b7", "\u8a3e", "\u8f9b", "\u95de", "\u90a3", "\u7c21", "\u9952",
895aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u7a7a", "\u66fe", "\u6bcb", "\u6c99", "\u4e5c", "\u990a", "\u97a0", "\u9808", "\u8c50", "\u5de2",
896aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u95dc", "\u84af", "\u76f8", "\u67e5", "\u5f8c", "\u834a", "\u7d05", "\u904a", "\u7afa", "\u6b0a",
897aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u9011", "\u84cb", "\u76ca", "\u6853", "\u516c", "\u4e07\u4fdf", "\u53f8\u99ac", "\u4e0a\u5b98",
898aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u6b50\u967d", "\u590f\u4faf", "\u8af8\u845b", "\u805e\u4eba", "\u6771\u65b9", "\u8d6b\u9023",
899aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u7687\u752b", "\u5c09\u9072", "\u516c\u7f8a", "\u6fb9\u53f0", "\u516c\u51b6", "\u5b97\u653f",
900aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u6fee\u967d", "\u6df3\u4e8e", "\u55ae\u4e8e", "\u592a\u53d4", "\u7533\u5c60", "\u516c\u5b6b",
901aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u4ef2\u5b6b", "\u8ed2\u8f45", "\u4ee4\u72d0", "\u937e\u96e2", "\u5b87\u6587", "\u9577\u5b6b",
902aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u6155\u5bb9", "\u9bae\u4e8e", "\u95ad\u4e18", "\u53f8\u5f92", "\u53f8\u7a7a", "\u4e0c\u5b98",
903aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u53f8\u5bc7", "\u4ec9", "\u7763", "\u5b50\u8eca", "\u9853\u5b6b", "\u7aef\u6728", "\u5deb\u99ac",
904aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u516c\u897f", "\u6f06\u96d5", "\u6a02\u6b63", "\u58e4\u99df", "\u516c\u826f", "\u62d3\u62d4",
905aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u593e\u8c37", "\u5bb0\u7236", "\u7a40\u6881", "\u6649", "\u695a", "\u95bb", "\u6cd5", "\u6c5d", "\u9122",
906aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u5857", "\u6b3d", "\u6bb5\u5e72", "\u767e\u91cc", "\u6771\u90ed", "\u5357\u9580", "\u547c\u5ef6",
907aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u6b78", "\u6d77", "\u7f8a\u820c", "\u5fae\u751f", "\u5cb3", "\u5e25", "\u7df1", "\u4ea2", "\u6cc1",
908aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u5f8c", "\u6709", "\u7434", "\u6881\u4e18", "\u5de6\u4e18", "\u6771\u9580", "\u897f\u9580", "\u5546",
909aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u725f", "\u4f58", "\u4f74", "\u4f2f", "\u8cde", "\u5357\u5bae", "\u58a8", "\u54c8", "\u8b59", "\u7b2a",
910aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u5e74", "\u611b", "\u967d", "\u4f5f", "\u3401", "\u3422", "\u3426", "\u3493", "\u34A5", "\u34A7",
911aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u34AA", "\u3536", "\u4A3B", "\u4E00", "\u4E01", "\u4E07", "\u4E0D", "\u4E17", "\u4E23", "\u4E26",
912aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u4E34", "\u4E82", "\u4EB8", "\u4EB9", "\u511F", "\u512D", "\u513D", "\u513E", "\u53B5", "\u56D4",
913aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u56D6", "\u7065", "\u7069", "\u706A", "\u7E9E", "\u9750", "\u9F49", "\u9F7E", "\u9F98", "\uD840\uDC35",
914aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\uD840\uDC3D", "\uD840\uDC3E", "\uD840\uDC41", "\uD840\uDC46", "\uD840\uDC4C", "\uD840\uDC4E",
915aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\uD840\uDC53", "\uD840\uDC55", "\uD840\uDC56", "\uD840\uDC5F", "\uD840\uDC60", "\uD840\uDC7A",
916aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\uD840\uDC7B", "\uD840\uDCC8", "\uD840\uDD9E", "\uD840\uDD9F", "\uD840\uDDA0", "\uD840\uDDA1",
917aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\uD841\uDD3B", "\uD842\uDCCA", "\uD842\uDCCB", "\uD842\uDD6C", "\uD842\uDE0B", "\uD842\uDE0C",
918aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\uD842\uDED1", "\uD844\uDD9F", "\uD845\uDD19", "\uD845\uDD1A", "\uD846\uDD3B", "\uD84C\uDF5C",
919aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\uD85A\uDDC4", "\uD85A\uDDC5", "\uD85C\uDD98", "\uD85E\uDCB1", "\uD861\uDC04", "\uD864\uDDD3",
920aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\uD865\uDE63", "\uD869\uDCCA", "\uD86B\uDE9A", };
921aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
922aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    /**
923aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * Test AlphabeticIndex vs. root with script reordering.
924aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     */
925f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
926aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public void TestHaniFirst() {
927aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        RuleBasedCollator coll = (RuleBasedCollator) Collator.getInstance(ULocale.ROOT);
928aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        coll.setReorderCodes(UScript.HAN);
929aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        AlphabeticIndex index = new AlphabeticIndex(coll);
930aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        assertEquals("getBucketCount()", 1, index.getBucketCount());   // ... (underflow only)
931f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        index.addLabels(Locale.ENGLISH);
932aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        assertEquals("getBucketCount()", 28, index.getBucketCount());  // ... A-Z ...
933aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        int bucketIndex = index.getBucketIndex("\u897f");
934aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        assertEquals("getBucketIndex(U+897F)", 0, bucketIndex);  // underflow bucket
935aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        bucketIndex = index.getBucketIndex("i");
936aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        assertEquals("getBucketIndex(i)", 9, bucketIndex);
937aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        bucketIndex = index.getBucketIndex("\u03B1");
938aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        assertEquals("getBucketIndex(Greek alpha)", 27, bucketIndex);
939aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // U+50005 is an unassigned code point which sorts at the end, independent of the Hani group.
940aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        bucketIndex = index.getBucketIndex(UTF16.valueOf(0x50005));
941aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        assertEquals("getBucketIndex(U+50005)", 27, bucketIndex);
942aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        bucketIndex = index.getBucketIndex("\uFFFF");
943aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        assertEquals("getBucketIndex(U+FFFF)", 27, bucketIndex);
944aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
945aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
946aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    /**
947aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * Test AlphabeticIndex vs. Pinyin with script reordering.
948aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     */
949f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
950aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public void TestPinyinFirst() {
951aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        RuleBasedCollator coll = (RuleBasedCollator) Collator.getInstance(ULocale.CHINESE);
952aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        coll.setReorderCodes(UScript.HAN);
953aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        AlphabeticIndex index = new AlphabeticIndex(coll);
954aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        assertEquals("getBucketCount()", 28, index.getBucketCount());   // ... A-Z ...
955f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        index.addLabels(Locale.CHINESE);
956aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        assertEquals("getBucketCount()", 28, index.getBucketCount());  // ... A-Z ...
957aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        int bucketIndex = index.getBucketIndex("\u897f");
958aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        assertEquals("getBucketIndex(U+897F)", 'X' - 'A' + 1, bucketIndex);
959aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        bucketIndex = index.getBucketIndex("i");
960aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        assertEquals("getBucketIndex(i)", 9, bucketIndex);
961aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        bucketIndex = index.getBucketIndex("\u03B1");
962aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        assertEquals("getBucketIndex(Greek alpha)", 27, bucketIndex);
963aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // U+50005 is an unassigned code point which sorts at the end, independent of the Hani group.
964aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        bucketIndex = index.getBucketIndex(UTF16.valueOf(0x50005));
965aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        assertEquals("getBucketIndex(U+50005)", 27, bucketIndex);
966aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        bucketIndex = index.getBucketIndex("\uFFFF");
967aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        assertEquals("getBucketIndex(U+FFFF)", 27, bucketIndex);
968aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
969aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
970aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    /**
971aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * Test labels with multiple primary weights.
972aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     */
973f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
974aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public void TestSchSt() {
975aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        AlphabeticIndex index = new AlphabeticIndex(ULocale.GERMAN);
976aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        index.addLabels(new UnicodeSet("[Æ{Sch*}{St*}]"));
977aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // ... A Æ B-R S Sch St T-Z ...
978aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        ImmutableIndex immIndex = index.buildImmutableIndex();
979aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        assertEquals("getBucketCount()", 31, index.getBucketCount());
980aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        assertEquals("immutable getBucketCount()", 31, immIndex.getBucketCount());
981aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        String[][] testCases = new String[][] {
982aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            // name, bucket index, bucket label
983aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            { "Adelbert", "1", "A" },
984aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            { "Afrika", "1", "A" },
985aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            { "Æsculap", "2", "Æ" },
986aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            { "Aesthet", "2", "Æ" },
987aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            { "Berlin", "3", "B" },
988aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            { "Rilke", "19", "R" },
989aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            { "Sacher", "20", "S" },
990aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            { "Seiler", "20", "S" },
991aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            { "Sultan", "20", "S" },
992aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            { "Schiller", "21", "Sch" },
993aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            { "Steiff", "22", "St" },
994aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            { "Thomas", "23", "T" }
995aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        };
996aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        List<String> labels = index.getBucketLabels();
997aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        for (String[] testCase : testCases) {
998aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            String name = testCase[0];
999aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            int bucketIndex = Integer.valueOf(testCase[1]);
1000aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            String label = testCase[2];
1001aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            String msg = "getBucketIndex(" + name + ")";
1002aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            assertEquals(msg, bucketIndex, index.getBucketIndex(name));
1003aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            msg = "immutable " + msg;
1004aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            assertEquals(msg, bucketIndex, immIndex.getBucketIndex(name));
1005aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            msg = "bucket label (" + name + ")";
1006aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            assertEquals(msg, label, labels.get(index.getBucketIndex(name)));
1007aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            msg = "immutable " + msg;
1008aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            assertEquals(msg, label, immIndex.getBucket(bucketIndex).getLabel());
1009aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
1010aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
1011aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
1012aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    /**
1013aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * With no real labels, there should be only the underflow label.
1014aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     */
1015f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
1016aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public void TestNoLabels() {
1017aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        RuleBasedCollator coll = (RuleBasedCollator) Collator.getInstance(ULocale.ROOT);
1018aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        AlphabeticIndex<Integer> index = new AlphabeticIndex<Integer>(coll);
1019aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        index.addRecord("\u897f", 0);
1020aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        index.addRecord("i", 0);
1021aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        index.addRecord("\u03B1", 0);
1022f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        assertEquals("getRecordCount()", 3, index.getRecordCount());  // code coverage
1023aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        assertEquals("getBucketCount()", 1, index.getBucketCount());  // ...
1024aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        Bucket<Integer> bucket = index.iterator().next();
1025aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        assertEquals("underflow label type", LabelType.UNDERFLOW, bucket.getLabelType());
1026aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        assertEquals("all records in the underflow bucket", 3, bucket.size());
1027aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
1028aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
1029aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    /**
1030aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * Test with the Bopomofo-phonetic tailoring.
1031aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     */
1032f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
1033aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public void TestChineseZhuyin() {
1034aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        AlphabeticIndex index = new AlphabeticIndex(ULocale.forLanguageTag("zh-u-co-zhuyin"));
1035aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        ImmutableIndex immIndex = index.buildImmutableIndex();
1036aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        assertEquals("getBucketCount()", 38, immIndex.getBucketCount());  // ... ㄅ ㄆ ㄇ ㄈ ㄉ -- ㄩ ...
1037aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        assertEquals("label 1", "ㄅ", immIndex.getBucket(1).getLabel());
1038aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        assertEquals("label 2", "ㄆ", immIndex.getBucket(2).getLabel());
1039aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        assertEquals("label 3", "ㄇ", immIndex.getBucket(3).getLabel());
1040aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        assertEquals("label 4", "ㄈ", immIndex.getBucket(4).getLabel());
1041aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        assertEquals("label 5", "ㄉ", immIndex.getBucket(5).getLabel());
1042aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
1043aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
1044f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
1045aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public void TestJapaneseKanji() {
1046aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        AlphabeticIndex index = new AlphabeticIndex(ULocale.JAPANESE);
1047aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        AlphabeticIndex.ImmutableIndex immIndex = index.buildImmutableIndex();
1048aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // There are no index characters for Kanji in the Japanese standard collator.
1049aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // They should all go into the overflow bucket.
1050aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        final int[] kanji = { 0x4E9C, 0x95C7, 0x4E00, 0x58F1 };
1051aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        int overflowIndex = immIndex.getBucketCount() - 1;
1052aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        for(int i = 0; i < kanji.length; ++i) {
1053aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            String msg = String.format("kanji[%d]=U+%04X in overflow bucket", i, kanji[i]);
1054aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            assertEquals(msg, overflowIndex, immIndex.getBucketIndex(UTF16.valueOf(kanji[i])));
1055aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
1056aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
1057aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
1058f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
1059aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public void TestFrozenCollator() {
1060aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // Ticket #9472
1061aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        RuleBasedCollator coll = (RuleBasedCollator) Collator.getInstance(new ULocale("da"));
1062aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        coll.setStrength(Collator.IDENTICAL);
1063aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        coll.freeze();
1064aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // The AlphabeticIndex constructor used to throw an exception
1065aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // because it cloned the collator (which preserves frozenness)
1066aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // and set the clone's strength to PRIMARY.
1067aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        AlphabeticIndex index = new AlphabeticIndex(coll);
1068aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        assertEquals("same strength as input Collator",
1069aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                Collator.IDENTICAL, index.getCollator().getStrength());
1070aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
1071aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
1072f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
1073aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public void TestChineseUnihan() {
1074aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        AlphabeticIndex index = new AlphabeticIndex(new ULocale("zh-u-co-unihan"));
1075aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        index.setMaxLabelCount(500);  // ICU 54 default is 99.
1076f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        assertEquals("getMaxLabelCount()", 500, index.getMaxLabelCount());  // code coverage
1077aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        AlphabeticIndex.ImmutableIndex immIndex = index.buildImmutableIndex();
1078aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        int bucketCount = immIndex.getBucketCount();
1079aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        if(bucketCount < 216) {
1080aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            // There should be at least an underflow and overflow label,
1081aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            // and one for each of 214 radicals,
1082aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            // and maybe additional labels for simplified radicals.
1083aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            // (ICU4C: dataerrln(), prints only a warning if the data is missing)
1084aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            errln("too few buckets/labels for Chinese/unihan: " + bucketCount +
1085aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    " (is zh/unihan data available?)");
1086aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return;
1087aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        } else {
1088aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            logln("Chinese/unihan has " + bucketCount + " buckets/labels");
1089aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
1090aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // bucketIndex = radical number, adjusted for simplified radicals in lower buckets.
1091aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        int bucketIndex = index.getBucketIndex("\u4e5d");
1092aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        assertEquals("getBucketIndex(U+4E5D)", 5, bucketIndex);
1093aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // radical 100, and there is a 90' since Unicode 8
1094aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        bucketIndex = index.getBucketIndex("\u7527");
1095aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        assertEquals("getBucketIndex(U+7527)", 101, bucketIndex);
1096aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
1097f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
1098f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
1099f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    public void testAddLabels_Locale() {
1100f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        AlphabeticIndex<?> ulocaleIndex = new AlphabeticIndex<String>(ULocale.CANADA);
1101f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        AlphabeticIndex<?> localeIndex = new AlphabeticIndex<String>(Locale.CANADA);
1102f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        ulocaleIndex.addLabels(ULocale.SIMPLIFIED_CHINESE);
1103f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        localeIndex.addLabels(Locale.SIMPLIFIED_CHINESE);
1104f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        assertEquals("getBucketLables() results of ulocaleIndex and localeIndex differ",
1105f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                ulocaleIndex.getBucketLabels(), localeIndex.getBucketLabels());
1106f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    }
1107f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
1108f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
1109f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    public void testGetRecordCount_empty() {
1110f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        assertEquals("Record count of empty index not 0", 0,
1111f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                new AlphabeticIndex<String>(ULocale.CANADA).getRecordCount());
1112f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    }
1113f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
1114f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
1115f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    public void testGetRecordCount_withRecords() {
1116f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        assertEquals("Record count of index with one record not 1", 1,
1117f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                new AlphabeticIndex<String>(ULocale.CANADA).addRecord("foo", null).getRecordCount());
1118f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    }
1119f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
1120f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    /**
1121f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert     * Check that setUnderflowLabel/setOverflowLabel/setInflowLabel correctly influence the name of
1122f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert     * generated labels.
1123f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert     */
1124f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
1125f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    public void testFlowLabels() {
1126f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        AlphabeticIndex<?> index = new AlphabeticIndex<String>(ULocale.ENGLISH)
1127f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                .addLabels(ULocale.forLanguageTag("ru"));
1128f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        index.setUnderflowLabel("underflow");
1129f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        index.setOverflowLabel("overflow");
1130f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        index.setInflowLabel("inflow");
1131f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        index.addRecord("!", null);
1132f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        index.addRecord("\u03B1", null); // GREEK SMALL LETTER ALPHA
1133f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        index.addRecord("\uab70", null); // CHEROKEE SMALL LETTER A
1134f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        AlphabeticIndex.Bucket<?> underflowBucket = null;
1135f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        AlphabeticIndex.Bucket<?> overflowBucket = null;
1136f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        AlphabeticIndex.Bucket<?> inflowBucket = null;
1137f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        for (AlphabeticIndex.Bucket<?> bucket : index) {
1138f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            switch (bucket.getLabelType()) {
1139f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                case UNDERFLOW:
1140f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                    assertNull("LabelType not null", underflowBucket);
1141f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                    underflowBucket = bucket;
1142f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                    break;
1143f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                case OVERFLOW:
1144f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                    assertNull("LabelType not null", overflowBucket);
1145f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                    overflowBucket = bucket;
1146f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                    break;
1147f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                case INFLOW:
1148f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                    assertNull("LabelType not null", inflowBucket);
1149f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                    inflowBucket = bucket;
1150f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                    break;
1151f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            }
1152f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        }
1153f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        assertNotNull("No bucket 'underflow'", underflowBucket);
1154f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        assertEquals("Wrong bucket label", "underflow", underflowBucket.getLabel());
1155f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        assertEquals("Wrong bucket label", "underflow", index.getUnderflowLabel());
1156f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        assertEquals("Bucket size not 1", 1, underflowBucket.size());
1157f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        assertNotNull("No bucket 'overflow'", overflowBucket);
1158f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        assertEquals("Wrong bucket label", "overflow", overflowBucket.getLabel());
1159f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        assertEquals("Wrong bucket label", "overflow", index.getOverflowLabel());
1160f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        assertEquals("Bucket size not 1", 1, overflowBucket.size());
1161f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        assertNotNull("No bucket 'inflow'", inflowBucket);
1162f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        assertEquals("Wrong bucket label", "inflow", inflowBucket.getLabel());
1163f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        assertEquals("Wrong bucket label", "inflow", index.getInflowLabel());
1164f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        assertEquals("Bucket size not 1", 1, inflowBucket.size());
1165f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    }
1166aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin}
1167