Skip to content

Commit

Permalink
8176841: Additional Unicode Language-Tag Extensions
Browse files Browse the repository at this point in the history
8189134: New system properties for the default Locale extensions
8190918: Retrieve the region specific data regardless of language in locale
8191349: Add a new method in j.t.f.DateTimeFormatter to reflect Unicode extensions

Reviewed-by: scolebourne, lancea, rriggs, rgoel, nishjain
  • Loading branch information
naotoj committed Dec 12, 2017
1 parent a43f60b commit 64c7629
Show file tree
Hide file tree
Showing 55 changed files with 3,631 additions and 890 deletions.
269 changes: 101 additions & 168 deletions make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java

Large diffs are not rendered by default.

Expand Up @@ -76,12 +76,16 @@ public void startElement(String uri, String localName, String qName, Attributes
// ignore this element - it has language and territory elements that aren't locale data
pushIgnoredContainer(qName);
break;
case "type":
if ("calendar".equals(attributes.getValue("key"))) {
pushStringEntry(qName, attributes, CLDRConverter.CALENDAR_NAME_PREFIX + attributes.getValue("type"));
} else {
pushIgnoredContainer(qName);
}

// for LocaleNames
// copy string
case "localeSeparator":
pushStringEntry(qName, attributes,
CLDRConverter.LOCALE_SEPARATOR);
break;
case "localeKeyTypePattern":
pushStringEntry(qName, attributes,
CLDRConverter.LOCALE_KEYTYPE);
break;

case "language":
Expand All @@ -96,6 +100,24 @@ public void startElement(String uri, String localName, String qName, Attributes
attributes.getValue("type"));
break;

case "key":
// for LocaleNames
// copy string
pushStringEntry(qName, attributes,
CLDRConverter.LOCALE_KEY_PREFIX +
convertOldKeyName(attributes.getValue("type")));
break;

case "type":
// for LocaleNames/CalendarNames
// copy string
pushStringEntry(qName, attributes,
CLDRConverter.LOCALE_TYPE_PREFIX +
convertOldKeyName(attributes.getValue("key")) + "." +
attributes.getValue("type"));

break;

//
// Currency information
//
Expand Down Expand Up @@ -515,26 +537,10 @@ public void startElement(String uri, String localName, String qName, Attributes
currentNumberingSystem = script + ".";
String digits = CLDRConverter.handlerNumbering.get(script);
if (digits == null) {
throw new InternalError("null digits for " + script);
}
if (Character.isSurrogate(digits.charAt(0))) {
// DecimalFormatSymbols doesn't support supplementary characters as digit zero.
pushIgnoredContainer(qName);
break;
}
// in case digits are in the reversed order, reverse back the order.
if (digits.charAt(0) > digits.charAt(digits.length() - 1)) {
StringBuilder sb = new StringBuilder(digits);
digits = sb.reverse().toString();
}
// Check if the order is sequential.
char c0 = digits.charAt(0);
for (int i = 1; i < digits.length(); i++) {
if (digits.charAt(i) != c0 + i) {
pushIgnoredContainer(qName);
break symbols;
}
}

@SuppressWarnings("unchecked")
List<String> numberingScripts = (List<String>) get("numberingScripts");
if (numberingScripts == null) {
Expand Down Expand Up @@ -924,17 +930,35 @@ private void putIfEntry() {
}
}
} else if (currentContainer instanceof Entry) {
Entry<?> entry = (Entry<?>) currentContainer;
Object value = entry.getValue();
if (value != null) {
String key = entry.getKey();
// Tweak for MonthNames for the root locale, Needed for
// SimpleDateFormat.format()/parse() roundtrip.
if (id.equals("root") && key.startsWith("MonthNames")) {
value = new DateFormatSymbols(Locale.US).getShortMonths();
}
put(entry.getKey(), value);
Entry<?> entry = (Entry<?>) currentContainer;
Object value = entry.getValue();
if (value != null) {
String key = entry.getKey();
// Tweak for MonthNames for the root locale, Needed for
// SimpleDateFormat.format()/parse() roundtrip.
if (id.equals("root") && key.startsWith("MonthNames")) {
value = new DateFormatSymbols(Locale.US).getShortMonths();
}
put(entry.getKey(), value);
}
}
}

public String convertOldKeyName(String key) {
// Explicitly obtained from "alias" attribute in each "key" element.
switch (key) {
case "calendar":
return "ca";
case "currency":
return "cu";
case "collation":
return "co";
case "numbers":
return "nu";
case "timezone":
return "tz";
default:
return key;
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -54,9 +54,32 @@ public InputSource resolveEntity(String publicID, String systemID) throws IOExce
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
switch (qName) {
case "numberingSystem":
if ("numeric".equals(attributes.getValue("type"))) {
// eg, <numberingSystem id="latn" type="numeric" digits="0123456789"/>
put(attributes.getValue("id"), attributes.getValue("digits"));
numberingSystem: {
if ("numeric".equals(attributes.getValue("type"))) {
// eg, <numberingSystem id="latn" type="numeric" digits="0123456789"/>
String script = attributes.getValue("id");
String digits = attributes.getValue("digits");

if (Character.isSurrogate(digits.charAt(0))) {
// DecimalFormatSymbols doesn't support supplementary characters as digit zero.
break numberingSystem;
}
// in case digits are in the reversed order, reverse back the order.
if (digits.charAt(0) > digits.charAt(digits.length() - 1)) {
StringBuilder sb = new StringBuilder(digits);
digits = sb.reverse().toString();
}
// Check if the order is sequential.
char c0 = digits.charAt(0);
for (int i = 1; i < digits.length(); i++) {
if (digits.charAt(i) != c0 + i) {
break numberingSystem;
}
}

// script/digits are acceptable.
put(script, digits);
}
}
pushIgnoredContainer(qName);
break;
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -256,20 +256,21 @@ public void generateMetaInfo(Map<String, SortedSet<String>> metaInfo) throws IOE
CLDRConverter.info("Generating file " + file);

try (PrintWriter out = new PrintWriter(file, "us-ascii")) {
out.println(CopyrightHeaders.getOpenJDKCopyright());
out.printf(CopyrightHeaders.getOpenJDKCopyright());

out.println((CLDRConverter.isBaseModule ? "package sun.util.cldr;\n\n" :
out.printf((CLDRConverter.isBaseModule ? "package sun.util.cldr;\n\n" :
"package sun.util.resources.cldr.provider;\n\n")
+ "import java.util.HashMap;\n"
+ "import java.util.Locale;\n"
+ "import java.util.Map;\n"
+ "import sun.util.locale.provider.LocaleProviderAdapter;\n"
+ "import sun.util.locale.provider.LocaleDataMetaInfo;\n");
+ "import sun.util.locale.provider.LocaleDataMetaInfo;\n"
+ "import sun.util.locale.provider.LocaleProviderAdapter;\n\n");
out.printf("public class %s implements LocaleDataMetaInfo {\n", className);
out.println(" private static final Map<String, String> resourceNameToLocales = new HashMap<>();\n" +
(CLDRConverter.isBaseModule ?
" private static final Map<Locale, String[]> parentLocalesMap = new HashMap<>();\n\n" : "\n") +
" static {\n");
out.printf(" private static final Map<String, String> resourceNameToLocales = new HashMap<>();\n" +
(CLDRConverter.isBaseModule ?
" private static final Map<Locale, String[]> parentLocalesMap = new HashMap<>();\n\n" :
"\n") +
" static {\n");

for (String key : metaInfo.keySet()) {
if (key.startsWith(CLDRConverter.PARENT_LOCALE_PREFIX)) {
Expand All @@ -296,30 +297,50 @@ public void generateMetaInfo(Map<String, SortedSet<String>> metaInfo) throws IOE
}
out.printf("\n });\n");
} else {
out.printf(" resourceNameToLocales.put(\"%s\",\n", key);
out.printf(" \"%s\");\n",
toLocaleList(key.equals("FormatData") ? metaInfo.get("AvailableLocales") :
metaInfo.get(key), false));
if ("AvailableLocales".equals(key)) {
out.printf(" resourceNameToLocales.put(\"%s\",\n", key);
out.printf(" \"%s\");\n", toLocaleList(metaInfo.get(key), false));
}
}
}
out.println(" }\n\n");

out.println(" @Override\n" +
out.printf(" }\n\n");

// end of static initializer block.

// Short TZ names for delayed initialization
if (CLDRConverter.isBaseModule) {
out.printf(" private static class TZShortIDMapHolder {\n");
out.printf(" static final Map<String, String> tzShortIDMap = new HashMap<>();\n");
out.printf(" static {\n");
CLDRConverter.handlerTimeZone.getData().entrySet().stream()
.forEach(e -> {
out.printf(" tzShortIDMap.put(\"%s\", \"%s\");\n", e.getKey(),
((String)e.getValue()));
});
out.printf(" }\n }\n\n");
}

out.printf(" @Override\n" +
" public LocaleProviderAdapter.Type getType() {\n" +
" return LocaleProviderAdapter.Type.CLDR;\n" +
" }\n\n");

out.println(" @Override\n" +
out.printf(" @Override\n" +
" public String availableLanguageTags(String category) {\n" +
" return resourceNameToLocales.getOrDefault(category, \"\");\n" +
" }\n\n");

if (CLDRConverter.isBaseModule) {
out.printf(" @Override\n" +
" public Map<String, String> tzShortIDs() {\n" +
" return TZShortIDMapHolder.tzShortIDMap;\n" +
" }\n\n");
out.printf(" public Map<Locale, String[]> parentLocales() {\n" +
" return parentLocalesMap;\n" +
" }\n}");
} else {
out.println("}");
out.printf("}");
}
}
}
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -84,53 +84,18 @@ Map<String, Object> getData(String id) {
values.put(CLDRConverter.PARENT_LOCALE_PREFIX+key,
parentLocalesMap.get(key));
});
} else {
String countryData = getWeekData(id, JAVA_FIRSTDAY, firstDayMap);
if (countryData != null) {
values.put(JAVA_FIRSTDAY, countryData);
}
String minDaysData = getWeekData(id, JAVA_MINDAY, minDaysMap);
if (minDaysData != null) {
values.put(JAVA_MINDAY, minDaysData);
}
firstDayMap.keySet().forEach(key -> {
values.put(CLDRConverter.CALENDAR_FIRSTDAY_PREFIX+firstDayMap.get(key),
key);
});
minDaysMap.keySet().forEach(key -> {
values.put(CLDRConverter.CALENDAR_MINDAYS_PREFIX+minDaysMap.get(key),
key);
});
}
return values.isEmpty() ? null : values;
}

/**
* It returns either firstDay or minDays in the JRE format for the country.
*
* @param country territory code of the requested data
* @param jreDataName JAVA_FIRSTDAY or JAVA_MINDAY
* @param dataMap firstDayMap or minDaysMap
* @return the value for the given jreDataName, or null if requested value
* (firstDay/minDays) is not available although that is highly unlikely
* because of the default value for the world (001).
*/
String getWeekData(String country, final String jreDataName, final Map<String, Object> dataMap) {
String countryValue = null;
String defaultWorldValue = null;
for (String key : dataMap.keySet()) {
if (key.contains(country)) {
if (jreDataName.equals(JAVA_FIRSTDAY)) {
countryValue = DAY_OF_WEEK_MAP.get((String) dataMap.get(key));
} else if (jreDataName.equals(JAVA_MINDAY)) {
countryValue = (String) dataMap.get(key);
}
if (countryValue != null) {
return countryValue;
}
} else if (key.contains(WORLD)) {
if (jreDataName.equals(JAVA_FIRSTDAY)) {
defaultWorldValue = DAY_OF_WEEK_MAP.get((String) dataMap.get(key));
} else if (jreDataName.equals(JAVA_MINDAY)) {
defaultWorldValue = (String) dataMap.get(key);
}
}
}
return defaultWorldValue;
}

@Override
public InputSource resolveEntity(String publicID, String systemID) throws IOException, SAXException {
// avoid HTTP traffic to unicode.org
Expand All @@ -152,7 +117,33 @@ public void startElement(String uri, String localName, String qName, Attributes
switch (qName) {
case "firstDay":
if (!isIgnored(attributes)) {
firstDayMap.put(attributes.getValue("territories"), attributes.getValue("day"));
String fd;

switch (attributes.getValue("day")) {
case "sun":
fd = "1";
break;
default:
case "mon":
fd = "2";
break;
case "tue":
fd = "3";
break;
case "wed":
fd = "4";
break;
case "thu":
fd = "5";
break;
case "fri":
fd = "6";
break;
case "sat":
fd = "7";
break;
}
firstDayMap.put(attributes.getValue("territories"), fd);
}
break;
case "minDays":
Expand Down

0 comments on commit 64c7629

Please sign in to comment.