1 /*
2  * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 /*
27  * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
28  * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
29  *
30  * The original version of this source code and documentation
31  * is copyrighted and owned by Taligent, Inc., a wholly-owned
32  * subsidiary of IBM. These materials are provided under terms
33  * of a License Agreement between Taligent and Sun. This technology
34  * is protected by multiple US and International patents.
35  *
36  * This notice and attribution to Taligent may not be removed.
37  * Taligent is a registered trademark of Taligent, Inc.
38  *
39  */
40 
41 package java.util;
42 
43 import sun.util.ResourceBundleEnumeration;
44 
45 /**
46  * <code>ListResourceBundle</code> is an abstract subclass of
47  * <code>ResourceBundle</code> that manages resources for a locale
48  * in a convenient and easy to use list. See <code>ResourceBundle</code> for
49  * more information about resource bundles in general.
50  *
51  * <P>
52  * Subclasses must override <code>getContents</code> and provide an array,
53  * where each item in the array is a pair of objects.
54  * The first element of each pair is the key, which must be a
55  * <code>String</code>, and the second element is the value associated with
56  * that key.
57  *
58  * <p>
59  * The following <a name="sample">example</a> shows two members of a resource
60  * bundle family with the base name "MyResources".
61  * "MyResources" is the default member of the bundle family, and
62  * "MyResources_fr" is the French member.
63  * These members are based on <code>ListResourceBundle</code>
64  * (a related <a href="PropertyResourceBundle.html#sample">example</a> shows
65  * how you can add a bundle to this family that's based on a properties file).
66  * The keys in this example are of the form "s1" etc. The actual
67  * keys are entirely up to your choice, so long as they are the same as
68  * the keys you use in your program to retrieve the objects from the bundle.
69  * Keys are case-sensitive.
70  * <blockquote>
71  * <pre>
72  *
73  * public class MyResources extends ListResourceBundle {
74  *     protected Object[][] getContents() {
75  *         return new Object[][] {
76  *         // LOCALIZE THIS
77  *             {"s1", "The disk \"{1}\" contains {0}."},  // MessageFormat pattern
78  *             {"s2", "1"},                               // location of {0} in pattern
79  *             {"s3", "My Disk"},                         // sample disk name
80  *             {"s4", "no files"},                        // first ChoiceFormat choice
81  *             {"s5", "one file"},                        // second ChoiceFormat choice
82  *             {"s6", "{0,number} files"},                // third ChoiceFormat choice
83  *             {"s7", "3 Mar 96"},                        // sample date
84  *             {"s8", new Dimension(1,5)}                 // real object, not just string
85  *         // END OF MATERIAL TO LOCALIZE
86  *         };
87  *     }
88  * }
89  *
90  * public class MyResources_fr extends ListResourceBundle {
91  *     protected Object[][] getContents() {
92  *         return new Object[][] {
93  *         // LOCALIZE THIS
94  *             {"s1", "Le disque \"{1}\" {0}."},          // MessageFormat pattern
95  *             {"s2", "1"},                               // location of {0} in pattern
96  *             {"s3", "Mon disque"},                      // sample disk name
97  *             {"s4", "ne contient pas de fichiers"},     // first ChoiceFormat choice
98  *             {"s5", "contient un fichier"},             // second ChoiceFormat choice
99  *             {"s6", "contient {0,number} fichiers"},    // third ChoiceFormat choice
100  *             {"s7", "3 mars 1996"},                     // sample date
101  *             {"s8", new Dimension(1,3)}                 // real object, not just string
102  *         // END OF MATERIAL TO LOCALIZE
103  *         };
104  *     }
105  * }
106  * </pre>
107  * </blockquote>
108  *
109  * <p>
110  * The implementation of a {@code ListResourceBundle} subclass must be thread-safe
111  * if it's simultaneously used by multiple threads. The default implementations
112  * of the methods in this class are thread-safe.
113  *
114  * @see ResourceBundle
115  * @see PropertyResourceBundle
116  * @since JDK1.1
117  */
118 public abstract class ListResourceBundle extends ResourceBundle {
119     /**
120      * Sole constructor.  (For invocation by subclass constructors, typically
121      * implicit.)
122      */
ListResourceBundle()123     public ListResourceBundle() {
124     }
125 
126     // Implements java.util.ResourceBundle.handleGetObject; inherits javadoc specification.
handleGetObject(String key)127     public final Object handleGetObject(String key) {
128         // lazily load the lookup hashtable.
129         if (lookup == null) {
130             loadLookup();
131         }
132         if (key == null) {
133             throw new NullPointerException();
134         }
135         return lookup.get(key); // this class ignores locales
136     }
137 
138     /**
139      * Returns an <code>Enumeration</code> of the keys contained in
140      * this <code>ResourceBundle</code> and its parent bundles.
141      *
142      * @return an <code>Enumeration</code> of the keys contained in
143      *         this <code>ResourceBundle</code> and its parent bundles.
144      * @see #keySet()
145      */
getKeys()146     public Enumeration<String> getKeys() {
147         // lazily load the lookup hashtable.
148         if (lookup == null) {
149             loadLookup();
150         }
151 
152         ResourceBundle parent = this.parent;
153         return new ResourceBundleEnumeration(lookup.keySet(),
154                 (parent != null) ? parent.getKeys() : null);
155     }
156 
157     /**
158      * Returns a <code>Set</code> of the keys contained
159      * <em>only</em> in this <code>ResourceBundle</code>.
160      *
161      * @return a <code>Set</code> of the keys contained only in this
162      *         <code>ResourceBundle</code>
163      * @since 1.6
164      * @see #keySet()
165      */
handleKeySet()166     protected Set<String> handleKeySet() {
167         if (lookup == null) {
168             loadLookup();
169         }
170         return lookup.keySet();
171     }
172 
173     /**
174      * Returns an array in which each item is a pair of objects in an
175      * <code>Object</code> array. The first element of each pair is
176      * the key, which must be a <code>String</code>, and the second
177      * element is the value associated with that key.  See the class
178      * description for details.
179      *
180      * @return an array of an <code>Object</code> array representing a
181      * key-value pair.
182      */
getContents()183     abstract protected Object[][] getContents();
184 
185     // ==================privates====================
186 
187     /**
188      * We lazily load the lookup hashtable.  This function does the
189      * loading.
190      */
loadLookup()191     private synchronized void loadLookup() {
192         if (lookup != null)
193             return;
194 
195         Object[][] contents = getContents();
196         HashMap<String,Object> temp = new HashMap<>(contents.length);
197         for (int i = 0; i < contents.length; ++i) {
198             // key must be non-null String, value must be non-null
199             String key = (String) contents[i][0];
200             Object value = contents[i][1];
201             if (key == null || value == null) {
202                 throw new NullPointerException();
203             }
204             temp.put(key, value);
205         }
206         lookup = temp;
207     }
208 
209     private Map<String,Object> lookup = null;
210 }
211