]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_4_2-src/main/classes/core/src/com/ibm/icu/util/OverlayBundle.java
go
[Dictionary.git] / jars / icu4j-4_4_2-src / main / classes / core / src / com / ibm / icu / util / OverlayBundle.java
1 /**\r
2  *******************************************************************************\r
3  * Copyright (C) 2001-2009, International Business Machines Corporation and    *\r
4  * others. All Rights Reserved.                                                *\r
5  *******************************************************************************\r
6  */\r
7 package com.ibm.icu.util;\r
8 \r
9 import java.util.Enumeration;\r
10 import java.util.Locale;\r
11 import java.util.MissingResourceException;\r
12 import java.util.ResourceBundle;\r
13 \r
14 /**\r
15  * A ResourceBundle that overlays one hierarchy atop another.  This is\r
16  * best explained by example.  Suppose one wants to use the\r
17  * resource hiararchy (in JDK 1.2 and 1.3, but not 1.4) at \r
18  * "java.text.resources.LocaleElements", but one wants to use\r
19  * a modified version of the "NumberPatterns" resource in the\r
20  * fr_FR locale.  One way to do this is to add special case code\r
21  * to the lookup operation to check for fr_FR and the key\r
22  * "NumberPatterns", and in that case, load up custom data.  However,\r
23  * this becomes unwieldy and places some information about the\r
24  * effective resource hierarchy into the code.\r
25  *\r
26  * The OverlayBundle solves this problem by layering another\r
27  * hierarchy, e.g, "com.acme.resources.LocaleElements", on top of a\r
28  * base hierarchy.  When a resource is requested, it is first sought\r
29  * in the overlay hierarchy, and if not found there, it is sought in\r
30  * the base hierarchy.  Multiple overlays are supported, but in\r
31  * practice one is usually sufficient.\r
32  * \r
33  * The OverlayBundle also addresses the problem of country-oriented\r
34  * data.  To specify the default data for a language, one just sets\r
35  * the language resource bundle data.  However, specifying the default\r
36  * data for a country using the standard ResourceBundle mechanism is\r
37  * impossible.  The OverlayBundle recognizes "wildcard" locales with\r
38  * the special language code "xx".  When looking up data for a locale\r
39  * with a non-empty country, if an exact locale match cannot be found,\r
40  * the OverlayBundle looks for data in the locale xx_YY, where YY is\r
41  * the country being sought.  This effectively adds another entry in\r
42  * the fallback sequence for a locale aa_BB: aa_BB, xx_BB, aa, root.\r
43  * Wildcard locales are not implemented for the base hierarchy, only\r
44  * for overlays.\r
45  *\r
46  * The OverlayBundle is implemented as an array of n ResourceBundle\r
47  * base names.  The base names are searched from 0 to n-1.  Base name\r
48  * n-1 is special; it is the base hierarchy.  This should be a\r
49  * well-populated hierarchy with most of the default data, typically,\r
50  * the icu or sun core hierarchies.  The base hierarchy is\r
51  * treated differently from the overlays above it.  It does not get\r
52  * wildcard resolution, and the getKeys() framework method is\r
53  * delegated to the base hierarchy bundle.\r
54  *\r
55  * Usage: Instantiate an OverlayBundle directly (not via a factory\r
56  * method as in ResourceBundle).  Instead of specifying a single base\r
57  * name, pass it an array of 2 or more base names.  After that, use it\r
58  * exactly as you would use ResourceBundle.\r
59  *\r
60  * @see java.util.ResourceBundle\r
61  * @author Alan Liu\r
62  * @internal\r
63  * @deprecated ICU 2.4. This class may be removed or modified.\r
64  */\r
65 // prepare to deprecate in next release\r
66 ///CLOVER:OFF\r
67 public class OverlayBundle extends ResourceBundle {\r
68 \r
69     /**\r
70      * The array of base names, with the length-1 entry being the base\r
71      * hierarchy, typically "sun.text.resources.LocaleElements".\r
72      */\r
73     private String[] baseNames;\r
74 \r
75     /**\r
76      * The requested locale.\r
77      */\r
78     private Locale locale;\r
79 \r
80     /**\r
81      * Loaded bundles.  These will be null until they are loaded on\r
82      * demand.\r
83      */\r
84     private ResourceBundle[] bundles;\r
85 \r
86     /**\r
87      * Construct an overlay bundle given a sequence of base names and\r
88      * a locale.\r
89      * @internal\r
90      * @deprecated ICU 2.4. This class may be removed or modified.\r
91      */\r
92     public OverlayBundle(String[] baseNames,\r
93                          Locale locale) {\r
94         this.baseNames = baseNames;\r
95         this.locale = locale;\r
96         bundles = new ResourceBundle[baseNames.length];\r
97     }\r
98 \r
99     /**\r
100      * ResourceBundle framework method.  Delegates to\r
101      * bundles[i].getObject().\r
102      * @internal\r
103      * @deprecated ICU 2.4. This class may be removed or modified.\r
104      */ \r
105    protected Object handleGetObject(String key) \r
106         throws MissingResourceException {\r
107 \r
108         Object o = null;\r
109 \r
110         for (int i=0; i<bundles.length; ++i) {\r
111             load(i);\r
112             try {\r
113                 o = bundles[i].getObject(key);\r
114             } catch (MissingResourceException e) {\r
115                 if (i == bundles.length-1) {\r
116                     throw e;\r
117                 }\r
118             }\r
119             if (o != null) {\r
120                 break;\r
121             }\r
122         }\r
123 \r
124         return o;\r
125     }\r
126 \r
127     /**\r
128      * ResourceBundle framework method.  Delegates to\r
129      * bundles[bundles.length-1].getKeys().\r
130      * @internal\r
131      * @deprecated ICU 2.4. This class may be removed or modified.\r
132      */\r
133     public Enumeration<String> getKeys() {\r
134         // Return the enumeration of the last bundle, which is the base\r
135         // of our hierarchy stack.\r
136         int i = bundles.length - 1;\r
137         load(i);\r
138         return bundles[i].getKeys();\r
139     }\r
140 \r
141     /**\r
142      * Load the i-th bundle and implement wildcard resolution.\r
143      */\r
144     private void load(int i)\r
145         throws MissingResourceException {\r
146 \r
147         if (bundles[i] == null) {\r
148             boolean tryWildcard = false;\r
149             try {\r
150                 bundles[i] = ResourceBundle.getBundle(baseNames[i], locale);\r
151                 if (bundles[i].getLocale().equals(locale)) {\r
152                     return;\r
153                 }\r
154                 if (locale.getCountry().length() != 0 && i != bundles.length-1) {\r
155                     tryWildcard = true;\r
156                 }\r
157             } catch (MissingResourceException e) {\r
158                 if (i == bundles.length-1) {\r
159                     throw e;\r
160                 }\r
161                 tryWildcard = true;\r
162             }\r
163             if (tryWildcard) {\r
164                 Locale wildcard = new Locale("xx", locale.getCountry(),\r
165                                              locale.getVariant());\r
166                 try {\r
167                     bundles[i] = ResourceBundle.getBundle(baseNames[i], wildcard);\r
168                 } catch (MissingResourceException e) {\r
169                     if (bundles[i] == null) {\r
170                         throw e;\r
171                     }\r
172                 }\r
173             }\r
174         }\r
175     }\r
176 }\r