Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/share/classes/sun/util/locale/provider/TimeZoneNameUtility.java
41161 views
1
/*
2
* Copyright (c) 2005, 2018, 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
package sun.util.locale.provider;
27
28
import java.lang.ref.SoftReference;
29
import java.util.LinkedList;
30
import java.util.List;
31
import java.util.Locale;
32
import java.util.Map;
33
import java.util.Objects;
34
import java.util.Optional;
35
import java.util.Set;
36
import java.util.concurrent.ConcurrentHashMap;
37
import java.util.spi.TimeZoneNameProvider;
38
import sun.util.calendar.ZoneInfo;
39
import sun.util.cldr.CLDRLocaleProviderAdapter;
40
import static sun.util.locale.provider.LocaleProviderAdapter.Type;
41
42
/**
43
* Utility class that deals with the localized time zone names
44
*
45
* @author Naoto Sato
46
* @author Masayoshi Okutsu
47
*/
48
public final class TimeZoneNameUtility {
49
50
/**
51
* cache to hold time zone localized strings. Keyed by Locale
52
*/
53
private static final ConcurrentHashMap<Locale, SoftReference<String[][]>> cachedZoneData =
54
new ConcurrentHashMap<>();
55
56
/**
57
* Cache for managing display names per timezone per locale
58
* The structure is:
59
* Map(key=id, value=SoftReference(Map(key=locale, value=displaynames)))
60
*/
61
private static final Map<String, SoftReference<Map<Locale, String[]>>> cachedDisplayNames =
62
new ConcurrentHashMap<>();
63
64
/**
65
* get time zone localized strings. Enumerate all keys.
66
*/
67
public static String[][] getZoneStrings(Locale locale) {
68
String[][] zones;
69
SoftReference<String[][]> data = cachedZoneData.get(locale);
70
71
if (data == null || ((zones = data.get()) == null)) {
72
zones = loadZoneStrings(locale);
73
data = new SoftReference<>(zones);
74
cachedZoneData.put(locale, data);
75
}
76
77
return zones;
78
}
79
80
private static String[][] loadZoneStrings(Locale locale) {
81
// If the provider is a TimeZoneNameProviderImpl, call its getZoneStrings
82
// in order to avoid per-ID retrieval.
83
LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(TimeZoneNameProvider.class, locale);
84
TimeZoneNameProvider provider = adapter.getTimeZoneNameProvider();
85
if (provider instanceof TimeZoneNameProviderImpl) {
86
String[][] zoneStrings = ((TimeZoneNameProviderImpl)provider).getZoneStrings(locale);
87
88
if (zoneStrings.length == 0 && locale.equals(Locale.ROOT)) {
89
// Unlike other *Name provider, zoneStrings search won't do the fallback
90
// name search. If the ResourceBundle found for the root locale contains no
91
// zoneStrings, just use the one for English, assuming English bundle
92
// contains all the tzids and their names.
93
zoneStrings= getZoneStrings(Locale.ENGLISH);
94
}
95
96
return zoneStrings;
97
}
98
99
// Performs per-ID retrieval.
100
Set<String> zoneIDs = LocaleProviderAdapter.forJRE().getLocaleResources(locale).getZoneIDs();
101
List<String[]> zones = new LinkedList<>();
102
for (String key : zoneIDs) {
103
String[] names = retrieveDisplayNamesImpl(key, locale);
104
if (names != null) {
105
zones.add(names);
106
}
107
}
108
109
String[][] zonesArray = new String[zones.size()][];
110
return zones.toArray(zonesArray);
111
}
112
113
/**
114
* Retrieve display names for a time zone ID.
115
*/
116
public static String[] retrieveDisplayNames(String id, Locale locale) {
117
Objects.requireNonNull(id);
118
Objects.requireNonNull(locale);
119
120
return retrieveDisplayNamesImpl(id, locale);
121
}
122
123
/**
124
* Retrieves a generic time zone display name for a time zone ID.
125
*
126
* @param id time zone ID
127
* @param style TimeZone.LONG or TimeZone.SHORT
128
* @param locale desired Locale
129
* @return the requested generic time zone display name, or null if not found.
130
*/
131
public static String retrieveGenericDisplayName(String id, int style, Locale locale) {
132
String[] names = retrieveDisplayNamesImpl(id, locale);
133
if (Objects.nonNull(names)) {
134
return names[6 - style];
135
} else {
136
return null;
137
}
138
}
139
140
/**
141
* Retrieves a standard or daylight-saving time name for the given time zone ID.
142
*
143
* @param id time zone ID
144
* @param daylight true for a daylight saving time name, or false for a standard time name
145
* @param style TimeZone.LONG or TimeZone.SHORT
146
* @param locale desired Locale
147
* @return the requested time zone name, or null if not found.
148
*/
149
public static String retrieveDisplayName(String id, boolean daylight, int style, Locale locale) {
150
String[] names = retrieveDisplayNamesImpl(id, locale);
151
if (Objects.nonNull(names)) {
152
return names[(daylight ? 4 : 2) - style];
153
} else {
154
return null;
155
}
156
}
157
158
/**
159
* Converts the time zone id from LDML's 5-letter id to tzdb's id
160
*
161
* @param shortID time zone short ID defined in LDML
162
* @return the tzdb's time zone ID
163
*/
164
public static Optional<String> convertLDMLShortID(String shortID) {
165
return canonicalTZID(shortID);
166
}
167
168
/**
169
* Returns the canonical ID for the given ID
170
*/
171
public static Optional<String> canonicalTZID(String id) {
172
return ((CLDRLocaleProviderAdapter)LocaleProviderAdapter.forType(Type.CLDR))
173
.canonicalTZID(id);
174
}
175
176
private static String[] retrieveDisplayNamesImpl(String id, Locale locale) {
177
LocaleServiceProviderPool pool =
178
LocaleServiceProviderPool.getPool(TimeZoneNameProvider.class);
179
String[] names;
180
Map<Locale, String[]> perLocale = null;
181
182
SoftReference<Map<Locale, String[]>> ref = cachedDisplayNames.get(id);
183
if (Objects.nonNull(ref)) {
184
perLocale = ref.get();
185
if (Objects.nonNull(perLocale)) {
186
names = perLocale.get(locale);
187
if (Objects.nonNull(names)) {
188
return names;
189
}
190
}
191
}
192
193
// build names array
194
names = new String[7];
195
names[0] = id;
196
for (int i = 1; i <= 6; i ++) {
197
names[i] = pool.getLocalizedObject(TimeZoneNameGetter.INSTANCE, locale,
198
i<5 ? (i<3 ? "std" : "dst") : "generic", i%2, id);
199
}
200
201
if (Objects.isNull(perLocale)) {
202
perLocale = new ConcurrentHashMap<>();
203
}
204
perLocale.put(locale, names);
205
ref = new SoftReference<>(perLocale);
206
cachedDisplayNames.put(id, ref);
207
return names;
208
}
209
210
211
/**
212
* Obtains a localized time zone strings from a TimeZoneNameProvider
213
* implementation.
214
*/
215
private static class TimeZoneNameGetter
216
implements LocaleServiceProviderPool.LocalizedObjectGetter<TimeZoneNameProvider,
217
String> {
218
private static final TimeZoneNameGetter INSTANCE =
219
new TimeZoneNameGetter();
220
221
@Override
222
public String getObject(TimeZoneNameProvider timeZoneNameProvider,
223
Locale locale,
224
String requestID,
225
Object... params) {
226
assert params.length == 2;
227
int style = (int) params[0];
228
String tzid = (String) params[1];
229
String value = getName(timeZoneNameProvider, locale, requestID, style, tzid);
230
if (value == null) {
231
Map<String, String> aliases = ZoneInfo.getAliasTable();
232
if (aliases != null) {
233
String canonicalID = aliases.get(tzid);
234
if (canonicalID != null) {
235
value = getName(timeZoneNameProvider, locale, requestID, style, canonicalID);
236
}
237
if (value == null) {
238
value = examineAliases(timeZoneNameProvider, locale, requestID,
239
canonicalID != null ? canonicalID : tzid, style, aliases);
240
}
241
}
242
}
243
244
return value;
245
}
246
247
private static String examineAliases(TimeZoneNameProvider tznp, Locale locale,
248
String requestID, String tzid, int style,
249
Map<String, String> aliases) {
250
for (Map.Entry<String, String> entry : aliases.entrySet()) {
251
if (entry.getValue().equals(tzid)) {
252
String alias = entry.getKey();
253
String name = getName(tznp, locale, requestID, style, alias);
254
if (name != null) {
255
return name;
256
}
257
name = examineAliases(tznp, locale, requestID, alias, style, aliases);
258
if (name != null) {
259
return name;
260
}
261
}
262
}
263
return null;
264
}
265
266
private static String getName(TimeZoneNameProvider timeZoneNameProvider,
267
Locale locale, String requestID, int style, String tzid) {
268
String value = null;
269
switch (requestID) {
270
case "std":
271
value = timeZoneNameProvider.getDisplayName(tzid, false, style, locale);
272
break;
273
case "dst":
274
value = timeZoneNameProvider.getDisplayName(tzid, true, style, locale);
275
break;
276
case "generic":
277
value = timeZoneNameProvider.getGenericDisplayName(tzid, style, locale);
278
break;
279
}
280
return value;
281
}
282
}
283
284
// No instantiation
285
private TimeZoneNameUtility() {
286
}
287
}
288
289