2 *******************************************************************************
\r
3 * Copyright (C) 2001-2009, International Business Machines Corporation and *
\r
4 * others. All Rights Reserved. *
\r
5 *******************************************************************************
\r
7 package com.ibm.icu.util;
\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
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
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
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
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
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
60 * @see java.util.ResourceBundle
\r
63 * @deprecated ICU 2.4. This class may be removed or modified.
\r
65 // prepare to deprecate in next release
\r
67 public class OverlayBundle extends ResourceBundle {
\r
70 * The array of base names, with the length-1 entry being the base
\r
71 * hierarchy, typically "sun.text.resources.LocaleElements".
\r
73 private String[] baseNames;
\r
76 * The requested locale.
\r
78 private Locale locale;
\r
81 * Loaded bundles. These will be null until they are loaded on
\r
84 private ResourceBundle[] bundles;
\r
87 * Construct an overlay bundle given a sequence of base names and
\r
90 * @deprecated ICU 2.4. This class may be removed or modified.
\r
92 public OverlayBundle(String[] baseNames,
\r
94 this.baseNames = baseNames;
\r
95 this.locale = locale;
\r
96 bundles = new ResourceBundle[baseNames.length];
\r
100 * ResourceBundle framework method. Delegates to
\r
101 * bundles[i].getObject().
\r
103 * @deprecated ICU 2.4. This class may be removed or modified.
\r
105 protected Object handleGetObject(String key)
\r
106 throws MissingResourceException {
\r
110 for (int i=0; i<bundles.length; ++i) {
\r
113 o = bundles[i].getObject(key);
\r
114 } catch (MissingResourceException e) {
\r
115 if (i == bundles.length-1) {
\r
128 * ResourceBundle framework method. Delegates to
\r
129 * bundles[bundles.length-1].getKeys().
\r
131 * @deprecated ICU 2.4. This class may be removed or modified.
\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
138 return bundles[i].getKeys();
\r
142 * Load the i-th bundle and implement wildcard resolution.
\r
144 private void load(int i)
\r
145 throws MissingResourceException {
\r
147 if (bundles[i] == null) {
\r
148 boolean tryWildcard = false;
\r
150 bundles[i] = ResourceBundle.getBundle(baseNames[i], locale);
\r
151 if (bundles[i].getLocale().equals(locale)) {
\r
154 if (locale.getCountry().length() != 0 && i != bundles.length-1) {
\r
155 tryWildcard = true;
\r
157 } catch (MissingResourceException e) {
\r
158 if (i == bundles.length-1) {
\r
161 tryWildcard = true;
\r
164 Locale wildcard = new Locale("xx", locale.getCountry(),
\r
165 locale.getVariant());
\r
167 bundles[i] = ResourceBundle.getBundle(baseNames[i], wildcard);
\r
168 } catch (MissingResourceException e) {
\r
169 if (bundles[i] == null) {
\r