make/src/classes/build/tools/cldrconverter/LDMLParseHandler.java
Print this page
*** 1,7 ****
/*
! * Copyright (c) 2012, 2013, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
--- 1,7 ----
/*
! * Copyright (c) 2012, 2015, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
*** 27,39 ****
--- 27,41 ----
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
+ import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
+ import java.util.Set;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
/**
*** 45,54 ****
--- 47,58 ----
private String currentNumberingSystem = "";
private CalendarType currentCalendarType;
private String zoneNameStyle; // "long" or "short" for time zone names
private String zonePrefix;
private final String id;
+ private String currentContext = ""; // "format"/"stand-alone"
+ private String currentWidth = ""; // "wide"/"narrow"/"abbreviated"
LDMLParseHandler(String id) {
this.id = id;
}
*** 110,122 ****
break;
// Calendar or currency
case "displayName":
{
! if (currentCalendarType != null) {
pushStringEntry(qName, attributes,
! currentCalendarType.keyElementName() + "field." + getContainerKey());
} else {
// for CurrencyNames
// need to get the key from the containing <currency> element
// ignore if is has "count" attribute
String containerKey = getContainerKey();
--- 114,127 ----
break;
// Calendar or currency
case "displayName":
{
! if (currentContainer.getqName().equals("field")) {
pushStringEntry(qName, attributes,
! (currentCalendarType != null ? currentCalendarType.keyElementName() : "")
! + "field." + getContainerKey());
} else {
// for CurrencyNames
// need to get the key from the containing <currency> element
// ignore if is has "count" attribute
String containerKey = getContainerKey();
*** 147,160 ****
pushIgnoredContainer(qName);
}
}
break;
case "fields":
! if (currentCalendarType != null) {
pushContainer(qName, attributes);
- } else {
- pushIgnoredContainer(qName);
}
break;
case "field":
{
String type = attributes.getValue("type");
--- 152,163 ----
pushIgnoredContainer(qName);
}
}
break;
case "fields":
! {
pushContainer(qName, attributes);
}
break;
case "field":
{
String type = attributes.getValue("type");
*** 181,190 ****
--- 184,194 ----
{
// for FormatData
// need to keep stand-alone and format, to allow for inheritance in CLDR
String type = attributes.getValue("type");
if ("stand-alone".equals(type) || "format".equals(type)) {
+ currentContext = type;
pushKeyContainer(qName, attributes, type);
} else {
pushIgnoredContainer(qName);
}
}
*** 192,203 ****
case "monthWidth":
{
// for FormatData
// create string array for the two types that the JRE knows
// keep info about the context type so we can sort out inheritance later
String prefix = (currentCalendarType == null) ? "" : currentCalendarType.keyElementName();
! switch (attributes.getValue("type")) {
case "wide":
pushStringArrayEntry(qName, attributes, prefix + "MonthNames/" + getContainerKey(), 13);
break;
case "abbreviated":
pushStringArrayEntry(qName, attributes, prefix + "MonthAbbreviations/" + getContainerKey(), 13);
--- 196,212 ----
case "monthWidth":
{
// for FormatData
// create string array for the two types that the JRE knows
// keep info about the context type so we can sort out inheritance later
+ if (currentCalendarType == null) {
+ pushIgnoredContainer(qName);
+ break;
+ }
String prefix = (currentCalendarType == null) ? "" : currentCalendarType.keyElementName();
! currentWidth = attributes.getValue("type");
! switch (currentWidth) {
case "wide":
pushStringArrayEntry(qName, attributes, prefix + "MonthNames/" + getContainerKey(), 13);
break;
case "abbreviated":
pushStringArrayEntry(qName, attributes, prefix + "MonthAbbreviations/" + getContainerKey(), 13);
*** 220,229 ****
--- 229,239 ----
{
// for FormatData
// need to keep stand-alone and format, to allow for multiple inheritance in CLDR
String type = attributes.getValue("type");
if ("stand-alone".equals(type) || "format".equals(type)) {
+ currentContext = type;
pushKeyContainer(qName, attributes, type);
} else {
pushIgnoredContainer(qName);
}
}
*** 232,242 ****
{
// for FormatData
// create string array for the two types that the JRE knows
// keep info about the context type so we can sort out inheritance later
String prefix = (currentCalendarType == null) ? "" : currentCalendarType.keyElementName();
! switch (attributes.getValue("type")) {
case "wide":
pushStringArrayEntry(qName, attributes, prefix + "DayNames/" + getContainerKey(), 7);
break;
case "abbreviated":
pushStringArrayEntry(qName, attributes, prefix + "DayAbbreviations/" + getContainerKey(), 7);
--- 242,253 ----
{
// for FormatData
// create string array for the two types that the JRE knows
// keep info about the context type so we can sort out inheritance later
String prefix = (currentCalendarType == null) ? "" : currentCalendarType.keyElementName();
! currentWidth = attributes.getValue("type");
! switch (currentWidth) {
case "wide":
pushStringArrayEntry(qName, attributes, prefix + "DayNames/" + getContainerKey(), 7);
break;
case "abbreviated":
pushStringArrayEntry(qName, attributes, prefix + "DayAbbreviations/" + getContainerKey(), 7);
*** 261,280 ****
// for FormatData
// need to keep stand-alone and format, to allow for multiple inheritance in CLDR
{
String type = attributes.getValue("type");
if ("stand-alone".equals(type) || "format".equals(type)) {
pushKeyContainer(qName, attributes, type);
} else {
pushIgnoredContainer(qName);
}
}
break;
case "dayPeriodWidth":
// for FormatData
// create string array entry for am/pm. only keeping wide
! switch (attributes.getValue("type")) {
case "wide":
pushStringArrayEntry(qName, attributes, "AmPmMarkers/" + getContainerKey(), 2);
break;
case "narrow":
pushStringArrayEntry(qName, attributes, "narrow.AmPmMarkers/" + getContainerKey(), 2);
--- 272,293 ----
// for FormatData
// need to keep stand-alone and format, to allow for multiple inheritance in CLDR
{
String type = attributes.getValue("type");
if ("stand-alone".equals(type) || "format".equals(type)) {
+ currentContext = type;
pushKeyContainer(qName, attributes, type);
} else {
pushIgnoredContainer(qName);
}
}
break;
case "dayPeriodWidth":
// for FormatData
// create string array entry for am/pm. only keeping wide
! currentWidth = attributes.getValue("type");
! switch (currentWidth) {
case "wide":
pushStringArrayEntry(qName, attributes, "AmPmMarkers/" + getContainerKey(), 2);
break;
case "narrow":
pushStringArrayEntry(qName, attributes, "narrow.AmPmMarkers/" + getContainerKey(), 2);
*** 360,369 ****
--- 373,383 ----
{
// for FormatData
// need to keep stand-alone and format, to allow for inheritance in CLDR
String type = attributes.getValue("type");
if ("stand-alone".equals(type) || "format".equals(type)) {
+ currentContext = type;
pushKeyContainer(qName, attributes, type);
} else {
pushIgnoredContainer(qName);
}
}
*** 371,381 ****
case "quarterWidth":
{
// for FormatData
// keep info about the context type so we can sort out inheritance later
String prefix = (currentCalendarType == null) ? "" : currentCalendarType.keyElementName();
! switch (attributes.getValue("type")) {
case "wide":
pushStringArrayEntry(qName, attributes, prefix + "QuarterNames/" + getContainerKey(), 4);
break;
case "abbreviated":
pushStringArrayEntry(qName, attributes, prefix + "QuarterAbbreviations/" + getContainerKey(), 4);
--- 385,396 ----
case "quarterWidth":
{
// for FormatData
// keep info about the context type so we can sort out inheritance later
String prefix = (currentCalendarType == null) ? "" : currentCalendarType.keyElementName();
! currentWidth = attributes.getValue("type");
! switch (currentWidth) {
case "wide":
pushStringArrayEntry(qName, attributes, prefix + "QuarterNames/" + getContainerKey(), 4);
break;
case "abbreviated":
pushStringArrayEntry(qName, attributes, prefix + "QuarterAbbreviations/" + getContainerKey(), 4);
*** 448,463 ****
--- 463,486 ----
}
break;
case "currencyFormat":
// for FormatData
// copy string for later assembly into NumberPatterns
+ if (attributes.getValue("type").equals("standard")) {
pushStringEntry(qName, attributes, "NumberPatterns/currency");
+ } else {
+ pushIgnoredContainer(qName);
+ }
break;
case "percentFormat":
// for FormatData
// copy string for later assembly into NumberPatterns
+ if (attributes.getValue("type").equals("standard")) {
pushStringEntry(qName, attributes, "NumberPatterns/percent");
+ } else {
+ pushIgnoredContainer(qName);
+ }
break;
case "defaultNumberingSystem":
// default numbering system if multiple numbering systems are used.
pushStringEntry(qName, attributes, "DefaultNumberingSystem");
break;
*** 580,595 ****
// copy string for later assembly into DateTimePatterns
String prefix = (currentCalendarType == null) ? "" : currentCalendarType.keyElementName();
pushStringEntry(qName, attributes, prefix + "DateTimePatterns/" + attributes.getValue("type") + "-date");
}
break;
! case "dateTimeFormat":
{
// for FormatData
// copy string for later assembly into DateTimePatterns
String prefix = (currentCalendarType == null) ? "" : currentCalendarType.keyElementName();
! pushStringEntry(qName, attributes, prefix + "DateTimePatterns/date-time");
}
break;
case "localizedPatternChars":
{
// for FormatData
--- 603,618 ----
// copy string for later assembly into DateTimePatterns
String prefix = (currentCalendarType == null) ? "" : currentCalendarType.keyElementName();
pushStringEntry(qName, attributes, prefix + "DateTimePatterns/" + attributes.getValue("type") + "-date");
}
break;
! case "dateTimeFormatLength":
{
// for FormatData
// copy string for later assembly into DateTimePatterns
String prefix = (currentCalendarType == null) ? "" : currentCalendarType.keyElementName();
! pushStringEntry(qName, attributes, prefix + "DateTimePatterns/" + attributes.getValue("type") + "-dateTime");
}
break;
case "localizedPatternChars":
{
// for FormatData
*** 597,613 ****
--- 620,828 ----
String prefix = (currentCalendarType == null) ? "" : currentCalendarType.keyElementName();
pushStringEntry(qName, attributes, prefix + "DateTimePatternChars");
}
break;
+ // "alias" for root
+ case "alias":
+ {
+ if (id.equals("root") &&
+ !isIgnored(attributes) &&
+ currentCalendarType != null &&
+ !currentCalendarType.lname().startsWith("islamic-")) { // ignore Islamic variants
+ pushAliasEntry(qName, attributes, attributes.getValue("path"));
+ } else {
+ pushIgnoredContainer(qName);
+ }
+ }
+ break;
+
default:
// treat anything else as a container
pushContainer(qName, attributes);
break;
}
}
+ private static final String[] CONTEXTS = {"stand-alone", "format"};
+ private static final String[] WIDTHS = {"wide", "narrow", "abbreviated"};
+ private static final String[] LENGTHS = {"full", "long", "medium", "short"};
+
+ private void populateWidthAlias(String type, Set<String> keys) {
+ for (String context : CONTEXTS) {
+ for (String width : WIDTHS) {
+ String keyName = toJDKKey(type+"Width", context, width);
+ if (keyName.length() > 0) {
+ keys.add(keyName + "," + context + "," + width);
+ }
+ }
+ }
+ }
+
+ private void populateFormatLengthAlias(String type, Set<String> keys) {
+ for (String length: LENGTHS) {
+ String keyName = toJDKKey(type+"FormatLength", currentContext, length);
+ if (keyName.length() > 0) {
+ keys.add(keyName + "," + currentContext + "," + length);
+ }
+ }
+ }
+
+ private Set<String> populateAliasKeys(String qName, String context, String width) {
+ HashSet<String> ret = new HashSet<>();
+ String keyName = qName;
+
+ switch (qName) {
+ case "monthWidth":
+ case "dayWidth":
+ case "quarterWidth":
+ case "dayPeriodWidth":
+ case "dateFormatLength":
+ case "timeFormatLength":
+ case "dateTimeFormatLength":
+ case "eraNames":
+ case "eraAbbr":
+ case "eraNarrow":
+ ret.add(toJDKKey(qName, context, width) + "," + context + "," + width);
+ break;
+ case "days":
+ populateWidthAlias("day", ret);
+ break;
+ case "months":
+ populateWidthAlias("month", ret);
+ break;
+ case "quarters":
+ populateWidthAlias("quarter", ret);
+ break;
+ case "dayPeriods":
+ populateWidthAlias("dayPeriod", ret);
+ break;
+ case "eras":
+ ret.add(toJDKKey("eraNames", context, width) + "," + context + "," + width);
+ ret.add(toJDKKey("eraAbbr", context, width) + "," + context + "," + width);
+ ret.add(toJDKKey("eraNarrow", context, width) + "," + context + "," + width);
+ break;
+ case "dateFormats":
+ populateFormatLengthAlias("date", ret);
+ break;
+ case "timeFormats":
+ populateFormatLengthAlias("time", ret);
+ break;
+ default:
+ break;
+ }
+ return ret;
+ }
+
+ private String translateWidthAlias(String qName, String context, String width) {
+ String keyName = qName;
+ String type = Character.toUpperCase(qName.charAt(0)) + qName.substring(1, qName.indexOf("Width"));
+
+ switch (width) {
+ case "wide":
+ keyName = type + "Names/" + context;
+ break;
+ case "abbreviated":
+ keyName = type + "Abbreviations/" + context;
+ break;
+ case "narrow":
+ keyName = type + "Narrows/" + context;
+ break;
+ default:
+ assert false;
+ }
+
+ return keyName;
+ }
+
+ private String toJDKKey(String containerqName, String context, String type) {
+ String keyName = containerqName;
+
+ switch (containerqName) {
+ case "monthWidth":
+ case "dayWidth":
+ case "quarterWidth":
+ keyName = translateWidthAlias(keyName, context, type);
+ break;
+ case "dayPeriodWidth":
+ switch (type) {
+ case "wide":
+ keyName = "AmPmMarkers/" + context;
+ break;
+ case "narrow":
+ keyName = "narrow.AmPmMarkers/" + context;
+ break;
+ case "abbreviated":
+ keyName = "";
+ break;
+ }
+ break;
+ case "dateFormatLength":
+ case "timeFormatLength":
+ case "dateTimeFormatLength":
+ keyName = "DateTimePatterns/" +
+ type + "-" +
+ keyName.substring(0, keyName.indexOf("FormatLength"));
+ break;
+ case "eraNames":
+ keyName = "long.Eras";
+ break;
+ case "eraAbbr":
+ keyName = "Eras";
+ break;
+ case "eraNarrow":
+ keyName = "narrow.Eras";
+ break;
+ case "dateFormats":
+ case "timeFormats":
+ case "days":
+ case "months":
+ case "quarters":
+ case "dayPeriods":
+ case "eras":
+ break;
+ default:
+ keyName = "";
+ break;
+ }
+
+ return keyName;
+ }
+
+ private String getTarget(String qName, String path, String calType, String context, String width) {
+ // qName
+ int lastSlash = path.lastIndexOf('/');
+ qName = path.substring(lastSlash+1);
+ int bracket = qName.indexOf('[');
+ if (bracket != -1) {
+ qName = qName.substring(0, bracket);
+ }
+
+ // calType
+ String typeKey = "/calendar[@type='";
+ int start = path.indexOf(typeKey);
+ if (start != -1) {
+ calType = path.substring(start+typeKey.length(), path.indexOf("']", start));
+ }
+
+ // context
+ typeKey = "Context[@type='";
+ start = path.indexOf(typeKey);
+ if (start != -1) {
+ context = (path.substring(start+typeKey.length(), path.indexOf("']", start)));
+ }
+
+ // width
+ typeKey = "Width[@type='";
+ start = path.indexOf(typeKey);
+ if (start != -1) {
+ width = path.substring(start+typeKey.length(), path.indexOf("']", start));
+ }
+
+ return calType + "." + toJDKKey(qName, context, width);
+ }
+
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
assert qName.equals(currentContainer.getqName()) : "current=" + currentContainer.getqName() + ", param=" + qName;
switch (qName) {
case "calendar":
*** 626,652 ****
break;
case "timeZoneNames":
zonePrefix = null;
break;
case "generic":
case "standard":
case "daylight":
if (zonePrefix != null && (currentContainer instanceof Entry)) {
@SuppressWarnings("unchecked")
Map<String, String> valmap = (Map<String, String>) get(zonePrefix + getContainerKey());
Entry<?> entry = (Entry<?>) currentContainer;
valmap.put(entry.getKey(), (String) entry.getValue());
}
break;
default:
! if (currentContainer instanceof Entry) {
Entry<?> entry = (Entry<?>) currentContainer;
Object value = entry.getValue();
if (value != null) {
put(entry.getKey(), value);
}
}
}
- currentContainer = currentContainer.getParent();
- }
}
--- 841,911 ----
break;
case "timeZoneNames":
zonePrefix = null;
break;
+
case "generic":
case "standard":
case "daylight":
if (zonePrefix != null && (currentContainer instanceof Entry)) {
@SuppressWarnings("unchecked")
Map<String, String> valmap = (Map<String, String>) get(zonePrefix + getContainerKey());
Entry<?> entry = (Entry<?>) currentContainer;
valmap.put(entry.getKey(), (String) entry.getValue());
}
break;
+
+ case "monthWidth":
+ case "dayWidth":
+ case "dayPeriodWidth":
+ case "quarterWidth":
+ currentWidth = "";
+ putIfEntry();
+ break;
+
+ case "monthContext":
+ case "dayContext":
+ case "dayPeriodContext":
+ case "quarterContext":
+ currentContext = "";
+ putIfEntry();
+ break;
+
default:
! putIfEntry();
! }
! currentContainer = currentContainer.getParent();
! }
!
! private void putIfEntry() {
! if (currentContainer instanceof AliasEntry) {
! Entry<?> entry = (Entry<?>) currentContainer;
! String containerqName = entry.getParent().getqName();
! Set<String> keyNames = populateAliasKeys(containerqName, currentContext, currentWidth);
! if (!keyNames.isEmpty()) {
! for (String keyName : keyNames) {
! String[] tmp = keyName.split(",", 3);
! String calType = currentCalendarType.lname();
! String src = calType+"."+tmp[0];
! String target = getTarget(containerqName,
! entry.getKey(),
! calType,
! tmp[1].length()>0 ? tmp[1] : currentContext,
! tmp[2].length()>0 ? tmp[2] : currentWidth);
! if (target.substring(target.lastIndexOf('.')+1).equals(containerqName)) {
! // may not always be correct
! target = target.substring(0, target.indexOf('.'))+"."+tmp[0];
! }
! CLDRConverter.aliases.put(src.replaceFirst("^gregorian.", ""),
! target.replaceFirst("^gregorian.", ""));
! }
! }
! } else if (currentContainer instanceof Entry) {
Entry<?> entry = (Entry<?>) currentContainer;
Object value = entry.getValue();
if (value != null) {
put(entry.getKey(), value);
}
}
}
}