Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/macosx/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java
38918 views
1
/*
2
* Copyright (c) 2012, 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
package sun.util.locale.provider;
27
28
import java.lang.ref.SoftReference;
29
import java.text.*;
30
import java.text.spi.DateFormatProvider;
31
import java.text.spi.DateFormatSymbolsProvider;
32
import java.text.spi.DecimalFormatSymbolsProvider;
33
import java.text.spi.NumberFormatProvider;
34
import java.util.Collections;
35
import java.util.Calendar;
36
import java.util.HashSet;
37
import java.util.Locale;
38
import java.util.Map;
39
import java.util.ResourceBundle.Control;
40
import java.util.Set;
41
import java.util.TimeZone;
42
import java.util.concurrent.ConcurrentHashMap;
43
import java.util.concurrent.ConcurrentMap;
44
import java.util.concurrent.atomic.AtomicReferenceArray;
45
import java.util.spi.CalendarDataProvider;
46
import java.util.spi.CalendarNameProvider;
47
import java.util.spi.CurrencyNameProvider;
48
import java.util.spi.LocaleNameProvider;
49
import java.util.spi.TimeZoneNameProvider;
50
import sun.util.spi.CalendarProvider;
51
52
/**
53
* LocaleProviderAdapter implementation for the Mac OS X locale data
54
*
55
* @author Naoto Sato
56
*/
57
public class HostLocaleProviderAdapterImpl {
58
59
// per supported locale instances
60
private static ConcurrentMap<Locale, SoftReference<AtomicReferenceArray<String>>> dateFormatPatternsMap =
61
new ConcurrentHashMap<>(2);
62
private static ConcurrentMap<Locale, SoftReference<AtomicReferenceArray<String>>> numberFormatPatternsMap =
63
new ConcurrentHashMap<>(2);
64
private static ConcurrentMap<Locale, SoftReference<DateFormatSymbols>> dateFormatSymbolsMap =
65
new ConcurrentHashMap<>(2);
66
private static ConcurrentMap<Locale, SoftReference<DecimalFormatSymbols>> decimalFormatSymbolsMap =
67
new ConcurrentHashMap<>(2);
68
69
// locale categories
70
private static final int CAT_DISPLAY = 0;
71
private static final int CAT_FORMAT = 1;
72
73
// NumberFormat styles
74
private static final int NF_NUMBER = 0;
75
private static final int NF_CURRENCY = 1;
76
private static final int NF_PERCENT = 2;
77
private static final int NF_INTEGER = 3;
78
private static final int NF_MAX = NF_INTEGER;
79
80
// CalendarData value types
81
private static final int CD_FIRSTDAYOFWEEK = 0;
82
private static final int CD_MINIMALDAYSINFIRSTWEEK = 1;
83
84
// Locale/Currency display name types
85
private static final int DN_LOCALE_LANGUAGE = 0;
86
private static final int DN_LOCALE_SCRIPT = 1;
87
private static final int DN_LOCALE_REGION = 2;
88
private static final int DN_LOCALE_VARIANT = 3;
89
private static final int DN_CURRENCY_CODE = 4;
90
private static final int DN_CURRENCY_SYMBOL = 5;
91
92
// TimeZone display name types
93
private static final int DN_TZ_SHORT_STANDARD = 0;
94
private static final int DN_TZ_SHORT_DST = 1;
95
private static final int DN_TZ_LONG_STANDARD = 2;
96
private static final int DN_TZ_LONG_DST = 3;
97
98
private static final Set<Locale> supportedLocaleSet;
99
static {
100
Set<Locale> tmpSet = new HashSet<>();
101
// Assuming the default locales do not include any extensions, so
102
// no stripping is needed here.
103
Locale l = convertMacOSXLocaleToJavaLocale(getDefaultLocale(CAT_FORMAT));
104
tmpSet.addAll(Control.getNoFallbackControl(Control.FORMAT_DEFAULT).getCandidateLocales("", l));
105
l = convertMacOSXLocaleToJavaLocale(getDefaultLocale(CAT_DISPLAY));
106
tmpSet.addAll(Control.getNoFallbackControl(Control.FORMAT_DEFAULT).getCandidateLocales("", l));
107
supportedLocaleSet = Collections.unmodifiableSet(tmpSet);
108
}
109
private final static Locale[] supportedLocale = supportedLocaleSet.toArray(new Locale[0]);
110
111
@SuppressWarnings("fallthrough")
112
private static Locale convertMacOSXLocaleToJavaLocale(String macosxloc) {
113
// MacOSX may return ICU notation, here is the quote from CFLocale doc:
114
// "The corresponding value is a CFString containing the POSIX locale
115
// identifier as used by ICU, such as "ja_JP". If you have a variant
116
// locale or a different currency or calendar, it can be as complex as
117
// "en_US_POSIX@calendar=japanese;currency=EUR" or
118
// "az_Cyrl_AZ@calendar=buddhist;currency=JPY".
119
String[] tmp = macosxloc.split("@");
120
String langTag = tmp[0].replace('_', '-');
121
if (tmp.length > 1) {
122
String[] ext = tmp[1].split(";");
123
for (String keyval : ext) {
124
// We are only interested in "calendar" value for now.
125
if (keyval.startsWith("calendar=")) {
126
String calid = keyval.substring(keyval.indexOf('=')+1);
127
switch (calid) {
128
case "gregorian":
129
langTag += "-u-ca-gregory";
130
break;
131
case "japanese":
132
// Tweak for ja_JP_JP
133
if (tmp[0].equals("ja_JP")) {
134
return JRELocaleConstants.JA_JP_JP;
135
}
136
137
// fall through
138
139
default:
140
langTag += "-u-ca-" + calid;
141
break;
142
}
143
}
144
}
145
}
146
147
return Locale.forLanguageTag(langTag);
148
}
149
150
public static DateFormatProvider getDateFormatProvider() {
151
return new DateFormatProvider() {
152
153
@Override
154
public Locale[] getAvailableLocales() {
155
return getSupportedCalendarLocales();
156
}
157
158
@Override
159
public boolean isSupportedLocale(Locale locale) {
160
return isSupportedCalendarLocale(locale);
161
}
162
163
@Override
164
public DateFormat getDateInstance(int style, Locale locale) {
165
return new SimpleDateFormat(getDateTimePattern(style, -1, locale),
166
getCalendarLocale(locale));
167
}
168
169
@Override
170
public DateFormat getTimeInstance(int style, Locale locale) {
171
return new SimpleDateFormat(getDateTimePattern(-1, style, locale),
172
getCalendarLocale(locale));
173
}
174
175
@Override
176
public DateFormat getDateTimeInstance(int dateStyle,
177
int timeStyle, Locale locale) {
178
return new SimpleDateFormat(getDateTimePattern(dateStyle, timeStyle, locale),
179
getCalendarLocale(locale));
180
}
181
182
private String getDateTimePattern(int dateStyle, int timeStyle, Locale locale) {
183
AtomicReferenceArray<String> dateFormatPatterns;
184
SoftReference<AtomicReferenceArray<String>> ref = dateFormatPatternsMap.get(locale);
185
186
if (ref == null || (dateFormatPatterns = ref.get()) == null) {
187
dateFormatPatterns = new AtomicReferenceArray<>(5 * 5);
188
ref = new SoftReference<>(dateFormatPatterns);
189
dateFormatPatternsMap.put(locale, ref);
190
}
191
192
int index = (dateStyle + 1) * 5 + timeStyle + 1;
193
String pattern = dateFormatPatterns.get(index);
194
if (pattern == null) {
195
String langTag = locale.toLanguageTag();
196
pattern = translateDateFormatLetters(getCalendarID(langTag),
197
getDateTimePatternNative(dateStyle, timeStyle, langTag));
198
if (!dateFormatPatterns.compareAndSet(index, null, pattern)) {
199
pattern = dateFormatPatterns.get(index);
200
}
201
}
202
203
return pattern;
204
}
205
};
206
}
207
208
public static DateFormatSymbolsProvider getDateFormatSymbolsProvider() {
209
return new DateFormatSymbolsProvider() {
210
@Override
211
public Locale[] getAvailableLocales() {
212
if (isSupportedLocale(Locale.getDefault(Locale.Category.FORMAT))) {
213
return supportedLocale;
214
}
215
return new Locale[0];
216
}
217
218
@Override
219
public boolean isSupportedLocale(Locale locale) {
220
// Only supports the locale with Gregorian calendar
221
Locale base = locale.stripExtensions();
222
if (supportedLocaleSet.contains(base)) {
223
return getCalendarID(locale.toLanguageTag()).equals("gregorian");
224
}
225
return false;
226
}
227
228
@Override
229
public DateFormatSymbols getInstance(Locale locale) {
230
DateFormatSymbols dateFormatSymbols;
231
SoftReference<DateFormatSymbols> ref = dateFormatSymbolsMap.get(locale);
232
233
if (ref == null || (dateFormatSymbols = ref.get()) == null) {
234
dateFormatSymbols = new DateFormatSymbols(locale);
235
String langTag = locale.toLanguageTag();
236
dateFormatSymbols.setAmPmStrings(getAmPmStrings(langTag, dateFormatSymbols.getAmPmStrings()));
237
dateFormatSymbols.setEras(getEras(langTag, dateFormatSymbols.getEras()));
238
dateFormatSymbols.setMonths(getMonths(langTag, dateFormatSymbols.getMonths()));
239
dateFormatSymbols.setShortMonths(getShortMonths(langTag, dateFormatSymbols.getShortMonths()));
240
dateFormatSymbols.setWeekdays(getWeekdays(langTag, dateFormatSymbols.getWeekdays()));
241
dateFormatSymbols.setShortWeekdays(getShortWeekdays(langTag, dateFormatSymbols.getShortWeekdays()));
242
ref = new SoftReference<>(dateFormatSymbols);
243
dateFormatSymbolsMap.put(locale, ref);
244
}
245
return (DateFormatSymbols)dateFormatSymbols.clone();
246
}
247
};
248
}
249
250
public static NumberFormatProvider getNumberFormatProvider() {
251
return new NumberFormatProvider() {
252
@Override
253
public Locale[] getAvailableLocales() {
254
return supportedLocale;
255
}
256
257
@Override
258
public boolean isSupportedLocale(Locale locale) {
259
// Ignore the extensions for now
260
return supportedLocaleSet.contains(locale.stripExtensions());
261
}
262
263
@Override
264
public NumberFormat getCurrencyInstance(Locale locale) {
265
return new DecimalFormat(getNumberPattern(NF_CURRENCY, locale),
266
DecimalFormatSymbols.getInstance(locale));
267
}
268
269
@Override
270
public NumberFormat getIntegerInstance(Locale locale) {
271
return new DecimalFormat(getNumberPattern(NF_INTEGER, locale),
272
DecimalFormatSymbols.getInstance(locale));
273
}
274
275
@Override
276
public NumberFormat getNumberInstance(Locale locale) {
277
return new DecimalFormat(getNumberPattern(NF_NUMBER, locale),
278
DecimalFormatSymbols.getInstance(locale));
279
}
280
281
@Override
282
public NumberFormat getPercentInstance(Locale locale) {
283
return new DecimalFormat(getNumberPattern(NF_PERCENT, locale),
284
DecimalFormatSymbols.getInstance(locale));
285
}
286
287
private String getNumberPattern(int style, Locale locale) {
288
AtomicReferenceArray<String> numberFormatPatterns;
289
SoftReference<AtomicReferenceArray<String>> ref = numberFormatPatternsMap.get(locale);
290
291
if (ref == null || (numberFormatPatterns = ref.get()) == null) {
292
numberFormatPatterns = new AtomicReferenceArray<>(4);
293
ref = new SoftReference<>(numberFormatPatterns);
294
numberFormatPatternsMap.put(locale, ref);
295
}
296
297
String pattern = numberFormatPatterns.get(style);
298
if (pattern == null) {
299
pattern = getNumberPatternNative(style, locale.toLanguageTag());
300
if (!numberFormatPatterns.compareAndSet(style, null, pattern)) {
301
pattern = numberFormatPatterns.get(style);
302
}
303
}
304
305
return pattern;
306
}
307
};
308
}
309
310
public static DecimalFormatSymbolsProvider getDecimalFormatSymbolsProvider() {
311
return new DecimalFormatSymbolsProvider() {
312
313
@Override
314
public Locale[] getAvailableLocales() {
315
return supportedLocale;
316
}
317
318
@Override
319
public boolean isSupportedLocale(Locale locale) {
320
// Ignore the extensions for now
321
return supportedLocaleSet.contains(locale.stripExtensions());
322
}
323
324
@Override
325
public DecimalFormatSymbols getInstance(Locale locale) {
326
DecimalFormatSymbols decimalFormatSymbols;
327
SoftReference<DecimalFormatSymbols> ref = decimalFormatSymbolsMap.get(locale);
328
329
if (ref == null || (decimalFormatSymbols = ref.get()) == null) {
330
decimalFormatSymbols = new DecimalFormatSymbols(locale);
331
String langTag = locale.toLanguageTag();
332
333
// DecimalFormatSymbols.setInternationalCurrencySymbol() has
334
// a side effect of setting the currency symbol as well. So
335
// the calling order is relevant here.
336
decimalFormatSymbols.setInternationalCurrencySymbol(getInternationalCurrencySymbol(langTag, decimalFormatSymbols.getInternationalCurrencySymbol()));
337
decimalFormatSymbols.setCurrencySymbol(getCurrencySymbol(langTag, decimalFormatSymbols.getCurrencySymbol()));
338
decimalFormatSymbols.setDecimalSeparator(getDecimalSeparator(langTag, decimalFormatSymbols.getDecimalSeparator()));
339
decimalFormatSymbols.setGroupingSeparator(getGroupingSeparator(langTag, decimalFormatSymbols.getGroupingSeparator()));
340
decimalFormatSymbols.setInfinity(getInfinity(langTag, decimalFormatSymbols.getInfinity()));
341
decimalFormatSymbols.setMinusSign(getMinusSign(langTag, decimalFormatSymbols.getMinusSign()));
342
decimalFormatSymbols.setMonetaryDecimalSeparator(getMonetaryDecimalSeparator(langTag, decimalFormatSymbols.getMonetaryDecimalSeparator()));
343
decimalFormatSymbols.setNaN(getNaN(langTag, decimalFormatSymbols.getNaN()));
344
decimalFormatSymbols.setPercent(getPercent(langTag, decimalFormatSymbols.getPercent()));
345
decimalFormatSymbols.setPerMill(getPerMill(langTag, decimalFormatSymbols.getPerMill()));
346
decimalFormatSymbols.setZeroDigit(getZeroDigit(langTag, decimalFormatSymbols.getZeroDigit()));
347
decimalFormatSymbols.setExponentSeparator(getExponentSeparator(langTag, decimalFormatSymbols.getExponentSeparator()));
348
ref = new SoftReference<>(decimalFormatSymbols);
349
decimalFormatSymbolsMap.put(locale, ref);
350
}
351
return (DecimalFormatSymbols)decimalFormatSymbols.clone();
352
}
353
};
354
}
355
356
public static CalendarDataProvider getCalendarDataProvider() {
357
return new CalendarDataProvider() {
358
@Override
359
public Locale[] getAvailableLocales() {
360
return getSupportedCalendarLocales();
361
}
362
363
@Override
364
public boolean isSupportedLocale(Locale locale) {
365
return isSupportedCalendarLocale(locale);
366
}
367
368
@Override
369
public int getFirstDayOfWeek(Locale locale) {
370
return getCalendarInt(locale.toLanguageTag(), CD_FIRSTDAYOFWEEK);
371
}
372
373
@Override
374
public int getMinimalDaysInFirstWeek(Locale locale) {
375
return getCalendarInt(locale.toLanguageTag(), CD_MINIMALDAYSINFIRSTWEEK);
376
}
377
};
378
}
379
380
public static CalendarNameProvider getCalendarNameProvider() {
381
return new CalendarNameProvider() {
382
@Override
383
public Locale[] getAvailableLocales() {
384
return getSupportedCalendarLocales();
385
}
386
387
@Override
388
public boolean isSupportedLocale(Locale locale) {
389
return isSupportedCalendarLocale(locale);
390
}
391
392
@Override
393
public String getDisplayName(String calType, int field, int value,
394
int style, Locale locale) {
395
return null;
396
}
397
398
@Override
399
public Map<String, Integer> getDisplayNames(String calType,
400
int field, int style, Locale locale) {
401
return null;
402
}
403
};
404
}
405
406
public static CalendarProvider getCalendarProvider() {
407
return new CalendarProvider() {
408
@Override
409
public Locale[] getAvailableLocales() {
410
return getSupportedCalendarLocales();
411
}
412
413
@Override
414
public boolean isSupportedLocale(Locale locale) {
415
return isSupportedCalendarLocale(locale);
416
}
417
418
@Override
419
public Calendar getInstance(TimeZone zone, Locale locale) {
420
return new Calendar.Builder()
421
.setLocale(locale)
422
.setCalendarType(getCalendarID(locale.toLanguageTag()))
423
.setTimeZone(zone)
424
.setInstant(System.currentTimeMillis())
425
.build();
426
}
427
};
428
}
429
430
public static CurrencyNameProvider getCurrencyNameProvider() {
431
return new CurrencyNameProvider() {
432
@Override
433
public Locale[] getAvailableLocales() {
434
return supportedLocale;
435
}
436
437
@Override
438
public boolean isSupportedLocale(Locale locale) {
439
// Ignore the extensions for now
440
return supportedLocaleSet.contains(locale.stripExtensions());
441
}
442
443
@Override
444
public String getDisplayName(String code, Locale locale) {
445
return getDisplayString(locale.toLanguageTag(), DN_CURRENCY_CODE, code);
446
}
447
448
@Override
449
public String getSymbol(String code, Locale locale) {
450
return getDisplayString(locale.toLanguageTag(), DN_CURRENCY_SYMBOL, code);
451
}
452
};
453
}
454
455
public static LocaleNameProvider getLocaleNameProvider() {
456
return new LocaleNameProvider() {
457
@Override
458
public Locale[] getAvailableLocales() {
459
return supportedLocale;
460
}
461
462
@Override
463
public boolean isSupportedLocale(Locale locale) {
464
// Ignore the extensions for now
465
return supportedLocaleSet.contains(locale.stripExtensions());
466
}
467
468
@Override
469
public String getDisplayLanguage(String languageCode, Locale locale) {
470
return getDisplayString(locale.toLanguageTag(), DN_LOCALE_LANGUAGE, languageCode);
471
}
472
473
@Override
474
public String getDisplayCountry(String countryCode, Locale locale) {
475
return getDisplayString(locale.toLanguageTag(), DN_LOCALE_REGION, countryCode);
476
}
477
478
@Override
479
public String getDisplayScript(String scriptCode, Locale locale) {
480
return getDisplayString(locale.toLanguageTag(), DN_LOCALE_SCRIPT, scriptCode);
481
}
482
483
@Override
484
public String getDisplayVariant(String variantCode, Locale locale) {
485
return getDisplayString(locale.toLanguageTag(), DN_LOCALE_VARIANT, variantCode);
486
}
487
};
488
}
489
490
public static TimeZoneNameProvider getTimeZoneNameProvider() {
491
return new TimeZoneNameProvider() {
492
@Override
493
public Locale[] getAvailableLocales() {
494
return supportedLocale;
495
}
496
497
@Override
498
public boolean isSupportedLocale(Locale locale) {
499
// Ignore the extensions for now
500
return supportedLocaleSet.contains(locale.stripExtensions());
501
}
502
503
@Override
504
public String getDisplayName(String ID, boolean daylight, int style, Locale locale) {
505
return getTimeZoneDisplayString(locale.toLanguageTag(), style * 2 + (daylight ? 1 : 0), ID);
506
}
507
};
508
}
509
510
private static Locale[] getSupportedCalendarLocales() {
511
if (supportedLocale.length != 0 &&
512
supportedLocaleSet.contains(Locale.JAPAN) &&
513
isJapaneseCalendar()) {
514
Locale[] sup = new Locale[supportedLocale.length+1];
515
sup[0] = JRELocaleConstants.JA_JP_JP;
516
System.arraycopy(supportedLocale, 0, sup, 1, supportedLocale.length);
517
return sup;
518
}
519
return supportedLocale;
520
}
521
522
private static boolean isSupportedCalendarLocale(Locale locale) {
523
Locale base = locale;
524
525
if (base.hasExtensions() || base.getVariant() != "") {
526
base = new Locale.Builder()
527
.setLocale(locale)
528
.clearExtensions()
529
.build();
530
}
531
532
if (!supportedLocaleSet.contains(base)) {
533
return false;
534
}
535
536
String requestedCalType = locale.getUnicodeLocaleType("ca");
537
String nativeCalType =
538
getCalendarID(base.toLanguageTag()).replaceFirst("gregorian", "gregory");
539
540
if (requestedCalType == null) {
541
return Calendar.getAvailableCalendarTypes().contains(nativeCalType);
542
} else {
543
return requestedCalType.equals(nativeCalType);
544
}
545
}
546
547
private static boolean isJapaneseCalendar() {
548
return getCalendarID("ja-JP").equals("japanese");
549
}
550
551
private static Locale getCalendarLocale(Locale locale) {
552
String nativeCalType = getCalendarID(locale.toLanguageTag())
553
.replaceFirst("gregorian", "gregory");
554
if (Calendar.getAvailableCalendarTypes().contains(nativeCalType)) {
555
return new Locale.Builder()
556
.setLocale(locale)
557
.setUnicodeLocaleKeyword("ca", nativeCalType)
558
.build();
559
} else {
560
return locale;
561
}
562
}
563
564
// The following methods are copied from CLDRConverter build tool.
565
private static String translateDateFormatLetters(String calendarType, String cldrFormat) {
566
String pattern = cldrFormat;
567
int length = pattern.length();
568
boolean inQuote = false;
569
StringBuilder jrePattern = new StringBuilder(length);
570
int count = 0;
571
char lastLetter = 0;
572
573
for (int i = 0; i < length; i++) {
574
char c = pattern.charAt(i);
575
576
if (c == '\'') {
577
// '' is treated as a single quote regardless of being
578
// in a quoted section.
579
if ((i + 1) < length) {
580
char nextc = pattern.charAt(i + 1);
581
if (nextc == '\'') {
582
i++;
583
if (count != 0) {
584
convert(calendarType, lastLetter, count, jrePattern);
585
lastLetter = 0;
586
count = 0;
587
}
588
jrePattern.append("''");
589
continue;
590
}
591
}
592
if (!inQuote) {
593
if (count != 0) {
594
convert(calendarType, lastLetter, count, jrePattern);
595
lastLetter = 0;
596
count = 0;
597
}
598
inQuote = true;
599
} else {
600
inQuote = false;
601
}
602
jrePattern.append(c);
603
continue;
604
}
605
if (inQuote) {
606
jrePattern.append(c);
607
continue;
608
}
609
if (!(c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')) {
610
if (count != 0) {
611
convert(calendarType, lastLetter, count, jrePattern);
612
lastLetter = 0;
613
count = 0;
614
}
615
jrePattern.append(c);
616
continue;
617
}
618
619
if (lastLetter == 0 || lastLetter == c) {
620
lastLetter = c;
621
count++;
622
continue;
623
}
624
convert(calendarType, lastLetter, count, jrePattern);
625
lastLetter = c;
626
count = 1;
627
}
628
629
if (count != 0) {
630
convert(calendarType, lastLetter, count, jrePattern);
631
}
632
if (cldrFormat.contentEquals(jrePattern)) {
633
return cldrFormat;
634
}
635
return jrePattern.toString();
636
}
637
638
private static void convert(String calendarType, char cldrLetter, int count, StringBuilder sb) {
639
switch (cldrLetter) {
640
case 'G':
641
if (!calendarType.equals("gregorian")) {
642
// Adjust the number of 'G's for JRE SimpleDateFormat
643
if (count == 5) {
644
// CLDR narrow -> JRE short
645
count = 1;
646
} else if (count == 1) {
647
// CLDR abbr -> JRE long
648
count = 4;
649
}
650
}
651
appendN(cldrLetter, count, sb);
652
break;
653
654
// TODO: support 'c' and 'e' in JRE SimpleDateFormat
655
// Use 'u' and 'E' for now.
656
case 'c':
657
case 'e':
658
switch (count) {
659
case 1:
660
sb.append('u');
661
break;
662
case 3:
663
case 4:
664
appendN('E', count, sb);
665
break;
666
case 5:
667
appendN('E', 3, sb);
668
break;
669
}
670
break;
671
672
case 'v':
673
case 'V':
674
appendN('z', count, sb);
675
break;
676
677
case 'Z':
678
if (count == 4 || count == 5) {
679
sb.append("XXX");
680
}
681
break;
682
683
case 'u':
684
case 'U':
685
case 'q':
686
case 'Q':
687
case 'l':
688
case 'g':
689
case 'j':
690
case 'A':
691
// Unsupported letter. Just append it within quotes
692
sb.append('\'');
693
sb.append(cldrLetter);
694
sb.append('\'');
695
break;
696
697
default:
698
appendN(cldrLetter, count, sb);
699
break;
700
}
701
}
702
703
private static void appendN(char c, int n, StringBuilder sb) {
704
for (int i = 0; i < n; i++) {
705
sb.append(c);
706
}
707
}
708
709
// initialize
710
private static native String getDefaultLocale(int cat);
711
712
// For DateFormatProvider
713
private static native String getDateTimePatternNative(int dateStyle, int timeStyle, String langtag);
714
private static native String getCalendarID(String langTag);
715
716
// For NumberFormatProvider
717
private static native String getNumberPatternNative(int style, String langtag);
718
719
// For DateFormatSymbolsProvider
720
private static native String[] getAmPmStrings(String langTag, String[] ampm);
721
private static native String[] getEras(String langTag, String[] eras);
722
private static native String[] getMonths(String langTag, String[] months);
723
private static native String[] getShortMonths(String langTag, String[] smonths);
724
private static native String[] getWeekdays(String langTag, String[] wdays);
725
private static native String[] getShortWeekdays(String langTag, String[] swdays);
726
727
// For DecimalFormatSymbolsProvider
728
private static native String getCurrencySymbol(String langTag, String currencySymbol);
729
private static native char getDecimalSeparator(String langTag, char decimalSeparator);
730
private static native char getGroupingSeparator(String langTag, char groupingSeparator);
731
private static native String getInfinity(String langTag, String infinity);
732
private static native String getInternationalCurrencySymbol(String langTag, String internationalCurrencySymbol);
733
private static native char getMinusSign(String langTag, char minusSign);
734
private static native char getMonetaryDecimalSeparator(String langTag, char monetaryDecimalSeparator);
735
private static native String getNaN(String langTag, String nan);
736
private static native char getPercent(String langTag, char percent);
737
private static native char getPerMill(String langTag, char perMill);
738
private static native char getZeroDigit(String langTag, char zeroDigit);
739
private static native String getExponentSeparator(String langTag, String exponent);
740
741
// For CalendarDataProvider
742
private static native int getCalendarInt(String langTag, int type);
743
744
// For Locale/CurrencyNameProvider
745
private static native String getDisplayString(String langTag, int key, String value);
746
747
// For TimeZoneNameProvider
748
private static native String getTimeZoneDisplayString(String langTag, int style, String value);
749
}
750
751