< prev index next >

make/jdk/src/classes/build/tools/cldrconverter/LDMLParseHandler.java

Print this page
rev 56742 : [mq]: 8231273


  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 build.tools.cldrconverter;
  27 
  28 import java.io.File;
  29 import java.io.IOException;
  30 import java.text.DateFormatSymbols;
  31 import java.util.ArrayList;

  32 import java.util.HashMap;
  33 import java.util.HashSet;
  34 import java.util.List;
  35 import java.util.Locale;
  36 import java.util.Map;
  37 import java.util.Set;
  38 import org.xml.sax.Attributes;
  39 import org.xml.sax.InputSource;
  40 import org.xml.sax.SAXException;
  41 
  42 /**
  43  * Handles parsing of files in Locale Data Markup Language and produces a map
  44  * that uses the keys and values of JRE locale data.
  45  */
  46 class LDMLParseHandler extends AbstractLDMLHandler<Object> {
  47     private String defaultNumberingSystem;
  48     private String currentNumberingSystem = "";
  49     private CalendarType currentCalendarType;
  50     private String zoneNameStyle; // "long" or "short" for time zone names
  51     private String zonePrefix;


 515                 switch (type) {
 516                     case "short":
 517                     case "long":
 518                         // considering "short" and long for
 519                         // compact number formatting patterns
 520                         pushKeyContainer(qName, attributes, type);
 521                         currentStyle = type;
 522                         break;
 523                     default:
 524                         pushIgnoredContainer(qName);
 525                         break;
 526                 }
 527             }
 528             break;
 529         case "decimalFormat":
 530             if(currentStyle == null) {
 531                 pushContainer(qName, attributes);
 532             } else {
 533                 switch (currentStyle) {
 534                     case "short":
 535                         pushStringListEntry(qName, attributes,
 536                                 currentStyle+".CompactNumberPatterns");
 537                         break;
 538                     case "long":
 539                         pushStringListEntry(qName, attributes,
 540                                 currentStyle+".CompactNumberPatterns");
 541                         break;
 542                     default:
 543                         pushIgnoredContainer(qName);
 544                         break;
 545                 }
 546             }
 547             break;





 548         case "pattern":
 549             String containerName = currentContainer.getqName();
 550             if (containerName.equals("decimalFormat")) {























 551                 if (currentStyle == null) {
 552                     pushContainer(qName, attributes);
 553                 } else {
 554                     // The compact number patterns parsing assumes that the order
 555                     // of patterns are always in the increasing order of their
 556                     // type attribute i.e. type = 1000...
 557                     // Between the inflectional forms for a type (e.g.
 558                     // count = "one" and count = "other" for type = 1000), it is
 559                     // assumed that the count = "one" always appears before
 560                     // count = "other"
 561                     switch (currentStyle) {
 562                         case "short":
 563                         case "long":
 564                             String count = attributes.getValue("count");
 565                             // first pattern of count = "one" or count = "other"
 566                             if ((count.equals("one") || count.equals("other"))
 567                                     && compactCount.equals("")) {
 568                                 compactCount = count;
 569                                 pushStringListElement(qName, attributes,
 570                                         (int) Math.log10(Double.parseDouble(attributes.getValue("type"))));
 571                             } else if ((count.equals("one") || count.equals("other"))
 572                                     && compactCount.equals(count)) {
 573                                 // extract patterns with similar "count"
 574                                 // attribute value
 575                                 pushStringListElement(qName, attributes,
 576                                         (int) Math.log10(Double.parseDouble(attributes.getValue("type"))));
 577                             } else {
 578                                 pushIgnoredContainer(qName);
 579                             }
 580                             break;
 581                         default:
 582                             pushIgnoredContainer(qName);
 583                             break;
 584                     }
 585                 }
 586             } else {

 587                 pushContainer(qName, attributes);

 588             }
 589             break;
 590         case "currencyFormats":
 591         case "decimalFormats":
 592         case "percentFormats":
 593             {
 594                 String script = attributes.getValue("numberSystem");
 595                 if (script != null) {
 596                     addNumberingScript(script);
 597                     currentNumberingSystem = script + ".";
 598                 }
 599                 pushContainer(qName, attributes);
 600             }
 601             break;
 602         case "currencyFormatLength":
 603             if (attributes.getValue("type") == null) {
 604                 // skipping type="short" data
 605                 // for FormatData
 606                 pushContainer(qName, attributes);
 607             } else {
 608                 pushIgnoredContainer(qName);
 609             }
 610             break;
 611         case "currencyFormat":
 612             {
 613                 // for FormatData
 614                 // copy string for later assembly into NumberPatterns
 615                 String cfStyle = attributes.getValue("type");
 616                 if (cfStyle.equals("standard")) {
 617                     pushStringEntry(qName, attributes,
 618                         currentNumberingSystem + "NumberPatterns/currency");
 619                 } else if (cfStyle.equals("accounting")) {
 620                     pushStringEntry(qName, attributes,
 621                         currentNumberingSystem + "NumberPatterns/accounting");
 622                 } else {
 623                     pushIgnoredContainer(qName);
 624                 }
 625             }
 626             break;
 627         case "percentFormat":
 628             // for FormatData
 629             // copy string for later assembly into NumberPatterns
 630             if (attributes.getValue("type").equals("standard")) {
 631                 pushStringEntry(qName, attributes,
 632                     currentNumberingSystem + "NumberPatterns/percent");
 633             } else {
 634                 pushIgnoredContainer(qName);
 635             }
 636             break;
 637         case "defaultNumberingSystem":
 638             // default numbering system if multiple numbering systems are used.
 639             pushStringEntry(qName, attributes, "DefaultNumberingSystem");
 640             break;
 641         case "symbols":
 642             // for FormatData
 643             // look up numberingSystems
 644             symbols: {
 645                 String script = attributes.getValue("numberSystem");
 646                 if (script == null) {
 647                     // Has no script. Just ignore.
 648                     pushIgnoredContainer(qName);
 649                     break;
 650                 }
 651 
 652                 // Use keys as <script>."NumberElements/<symbol>"
 653                 currentNumberingSystem = script + ".";
 654                 String digits = CLDRConverter.handlerNumbering.get(script);
 655                 if (digits == null) {
 656                     pushIgnoredContainer(qName);


 750                 // for FormatData
 751                 // copy string for later assembly into DateTimePatterns
 752                 String prefix = (currentCalendarType == null) ? "" : currentCalendarType.keyElementName();
 753                 pushStringEntry(qName, attributes, prefix + "DateTimePatterns/" + attributes.getValue("type") + "-dateTime");
 754             }
 755             break;
 756         case "localizedPatternChars":
 757             {
 758                 // for FormatData
 759                 // copy string for later adaptation to JRE use
 760                 String prefix = (currentCalendarType == null) ? "" : currentCalendarType.keyElementName();
 761                 pushStringEntry(qName, attributes, prefix + "DateTimePatternChars");
 762             }
 763             break;
 764 
 765         // "alias" for root
 766         case "alias":
 767             {
 768                 if (id.equals("root") && !isIgnored(attributes)
 769                         && ((currentContainer.getqName().equals("decimalFormatLength"))


 770                         || (currentCalendarType != null && !currentCalendarType.lname().startsWith("islamic-")))) { // ignore islamic variants
 771                     pushAliasEntry(qName, attributes, attributes.getValue("path"));
 772                 } else {
 773                     pushIgnoredContainer(qName);
 774                 }
 775             }
 776             break;
 777 
 778         default:
 779             // treat anything else as a container
 780             pushContainer(qName, attributes);
 781             break;
 782         }
 783     }
 784 
 785     private static final String[] CONTEXTS = {"stand-alone", "format"};
 786     private static final String[] WIDTHS = {"wide", "narrow", "abbreviated"};
 787     private static final String[] LENGTHS = {"full", "long", "medium", "short"};
 788 
 789     private void populateWidthAlias(String type, Set<String> keys) {


 905         case "eraNames":
 906             keyName = "long.Eras";
 907             break;
 908         case "eraAbbr":
 909             keyName = "Eras";
 910             break;
 911         case "eraNarrow":
 912             keyName = "narrow.Eras";
 913             break;
 914         case "dateFormats":
 915         case "timeFormats":
 916         case "days":
 917         case "months":
 918         case "quarters":
 919         case "dayPeriods":
 920         case "eras":
 921             break;
 922         case "decimalFormatLength": // used for compact number formatting patterns
 923             keyName = type + ".CompactNumberPatterns";
 924             break;






 925         default:
 926             keyName = "";
 927             break;
 928         }
 929 
 930         return keyName;
 931     }
 932 
 933     private String getTarget(String path, String calType, String context, String width) {
 934         // Target qName
 935         int lastSlash = path.lastIndexOf('/');
 936         String qName = path.substring(lastSlash+1);
 937         int bracket = qName.indexOf('[');
 938         if (bracket != -1) {
 939             qName = qName.substring(0, bracket);
 940         }
 941 
 942         // calType
 943         String typeKey = "/calendar[@type='";
 944         int start = path.indexOf(typeKey);


 951         start = path.indexOf(typeKey);
 952         if (start != -1) {
 953             context = (path.substring(start+typeKey.length(), path.indexOf("']", start)));
 954         }
 955 
 956         // width
 957         typeKey = "Width[@type='";
 958         start = path.indexOf(typeKey);
 959         if (start != -1) {
 960             width = path.substring(start+typeKey.length(), path.indexOf("']", start));
 961         }
 962 
 963         // used for compact number formatting patterns aliases
 964         typeKey = "decimalFormatLength[@type='";
 965         start = path.indexOf(typeKey);
 966         if (start != -1) {
 967             String style = path.substring(start + typeKey.length(), path.indexOf("']", start));
 968             return toJDKKey(qName, "", style);
 969         }
 970 
















 971         return calType + "." + toJDKKey(qName, context, width);
 972     }
 973 
 974     @Override
 975     public void endElement(String uri, String localName, String qName) throws SAXException {
 976         assert qName.equals(currentContainer.getqName()) : "current=" + currentContainer.getqName() + ", param=" + qName;
 977         switch (qName) {
 978         case "calendar":
 979             assert !(currentContainer instanceof Entry);
 980             currentCalendarType = null;
 981             break;
 982 
 983         case "defaultNumberingSystem":
 984             if (currentContainer instanceof StringEntry) {
 985                 defaultNumberingSystem = ((StringEntry) currentContainer).getValue();
 986                 assert defaultNumberingSystem != null;
 987                 put(((StringEntry) currentContainer).getKey(), defaultNumberingSystem);
 988             } else {
 989                 defaultNumberingSystem = null;
 990             }
 991             break;
 992 
 993         case "timeZoneNames":
 994             zonePrefix = null;
 995             break;
 996 
 997         case "generic":
 998         case "standard":
 999         case "daylight":
1000         case "exemplarCity":
1001             if (zonePrefix != null && (currentContainer instanceof Entry)) {
1002                 @SuppressWarnings("unchecked")
1003                 Map<String, String> valmap = (Map<String, String>) get(zonePrefix + getContainerKey());
1004                 Entry<?> entry = (Entry<?>) currentContainer;
1005                 if (qName.equals("exemplarCity")) {
1006                     put(CLDRConverter.EXEMPLAR_CITY_PREFIX + getContainerKey(), (String) entry.getValue());
1007                 } else {


1026             putIfEntry();
1027             break;
1028         case "decimalFormatLength":
1029             currentStyle = "";
1030             compactCount = "";
1031             putIfEntry();
1032             break;
1033         case "currencyFormats":
1034         case "decimalFormats":
1035         case "percentFormats":
1036         case "symbols":
1037             currentNumberingSystem = "";
1038             putIfEntry();
1039             break;
1040         default:
1041             putIfEntry();
1042         }
1043         currentContainer = currentContainer.getParent();
1044     }
1045 
1046     private void putIfEntry() {
1047         if (currentContainer instanceof AliasEntry) {
1048             Entry<?> entry = (Entry<?>) currentContainer;
1049             String containerqName = entry.getParent().getqName();
1050             if (containerqName.equals("decimalFormatLength")) {
1051                 String srcKey = toJDKKey(containerqName, "", currentStyle);
1052                 String targetKey = getTarget(entry.getKey(), "", "", "");
1053                 CLDRConverter.aliases.put(srcKey, targetKey);







1054             } else {
1055                 Set<String> keyNames = populateAliasKeys(containerqName, currentContext, currentWidth);
1056                 if (!keyNames.isEmpty()) {
1057                     for (String keyName : keyNames) {
1058                         String[] tmp = keyName.split(",", 3);
1059                         String calType = currentCalendarType.lname();
1060                         String src = calType+"."+tmp[0];
1061                         String target = getTarget(
1062                                     entry.getKey(),
1063                                     calType,
1064                                     tmp[1].length()>0 ? tmp[1] : currentContext,
1065                                     tmp[2].length()>0 ? tmp[2] : currentWidth);
1066                         if (target.substring(target.lastIndexOf('.')+1).equals(containerqName)) {
1067                             target = target.substring(0, target.indexOf('.'))+"."+tmp[0];
1068                         }
1069                         CLDRConverter.aliases.put(src.replaceFirst("^gregorian.", ""),
1070                                                   target.replaceFirst("^gregorian.", ""));
1071                     }
1072                 }
1073             }
1074         } else if (currentContainer instanceof Entry) {
1075             Entry<?> entry = (Entry<?>) currentContainer;
1076             Object value = entry.getValue();
1077             if (value != null) {
1078                 String key = entry.getKey();
1079                 // Tweak for MonthNames for the root locale, Needed for
1080                 // SimpleDateFormat.format()/parse() roundtrip.
1081                 if (id.equals("root") && key.startsWith("MonthNames")) {
1082                     value = new DateFormatSymbols(Locale.US).getShortMonths();
1083                 }
1084                 put(entry.getKey(), value);
1085             }
1086         }

1087     }
1088 
1089     public String convertOldKeyName(String key) {
1090         // Explicitly obtained from "alias" attribute in each "key" element.
1091         switch (key) {
1092             case "calendar":
1093                 return "ca";
1094             case "currency":
1095                 return "cu";
1096             case "collation":
1097                 return "co";
1098             case "numbers":
1099                 return "nu";
1100             case "timezone":
1101                 return "tz";
1102             default:
1103                 return key;
1104         }
1105     }
1106 


  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 build.tools.cldrconverter;
  27 
  28 import java.io.File;
  29 import java.io.IOException;
  30 import java.text.DateFormatSymbols;
  31 import java.util.ArrayList;
  32 import java.util.Arrays;
  33 import java.util.HashMap;
  34 import java.util.HashSet;
  35 import java.util.List;
  36 import java.util.Locale;
  37 import java.util.Map;
  38 import java.util.Set;
  39 import org.xml.sax.Attributes;
  40 import org.xml.sax.InputSource;
  41 import org.xml.sax.SAXException;
  42 
  43 /**
  44  * Handles parsing of files in Locale Data Markup Language and produces a map
  45  * that uses the keys and values of JRE locale data.
  46  */
  47 class LDMLParseHandler extends AbstractLDMLHandler<Object> {
  48     private String defaultNumberingSystem;
  49     private String currentNumberingSystem = "";
  50     private CalendarType currentCalendarType;
  51     private String zoneNameStyle; // "long" or "short" for time zone names
  52     private String zonePrefix;


 516                 switch (type) {
 517                     case "short":
 518                     case "long":
 519                         // considering "short" and long for
 520                         // compact number formatting patterns
 521                         pushKeyContainer(qName, attributes, type);
 522                         currentStyle = type;
 523                         break;
 524                     default:
 525                         pushIgnoredContainer(qName);
 526                         break;
 527                 }
 528             }
 529             break;
 530         case "decimalFormat":
 531             if(currentStyle == null) {
 532                 pushContainer(qName, attributes);
 533             } else {
 534                 switch (currentStyle) {
 535                     case "short":



 536                     case "long":
 537                         pushStringListEntry(qName, attributes,
 538                                 currentStyle+".CompactNumberPatterns");
 539                         break;
 540                     default:
 541                         pushIgnoredContainer(qName);
 542                         break;
 543                 }
 544             }
 545             break;
 546         case "currencyFormat":
 547         case "percentFormat":
 548             pushKeyContainer(qName, attributes, attributes.getValue("type"));
 549             break;
 550 
 551         case "pattern":
 552             String containerName = currentContainer.getqName();
 553             switch (containerName) {
 554                 case "currencyFormat":
 555                 case "percentFormat":
 556                 {
 557                     // for FormatData
 558                     // copy string for later assembly into NumberPatterns
 559                     if (currentContainer instanceof KeyContainer) {
 560                         String fStyle = ((KeyContainer)currentContainer).getKey();
 561                         if (fStyle.equals("standard")) {
 562                             pushStringEntry(qName, attributes,
 563                                     currentNumberingSystem + "NumberPatterns/" + containerName.replaceFirst("Format", ""));
 564                         } else if (fStyle.equals("accounting") && containerName.equals("currencyFormat")) {
 565                             pushStringEntry(qName, attributes,
 566                                     currentNumberingSystem + "NumberPatterns/accounting");
 567                         } else {
 568                             pushIgnoredContainer(qName);
 569                         }
 570                     } else {
 571                         pushIgnoredContainer(qName);
 572                     }
 573                 }
 574                 break;
 575 
 576                 case "decimalFormat":
 577                     if (currentStyle == null) {
 578                         pushContainer(qName, attributes);
 579                     } else {
 580                         // The compact number patterns parsing assumes that the order
 581                         // of patterns are always in the increasing order of their
 582                         // type attribute i.e. type = 1000...
 583                         // Between the inflectional forms for a type (e.g.
 584                         // count = "one" and count = "other" for type = 1000), it is
 585                         // assumed that the count = "one" always appears before
 586                         // count = "other"
 587                         switch (currentStyle) {
 588                             case "short":
 589                             case "long":
 590                                 String count = attributes.getValue("count");
 591                                 // first pattern of count = "one" or count = "other"
 592                                 if ((count.equals("one") || count.equals("other"))
 593                                         && compactCount.equals("")) {
 594                                     compactCount = count;
 595                                     pushStringListElement(qName, attributes,
 596                                             (int) Math.log10(Double.parseDouble(attributes.getValue("type"))));
 597                                 } else if ((count.equals("one") || count.equals("other"))
 598                                         && compactCount.equals(count)) {
 599                                     // extract patterns with similar "count"
 600                                     // attribute value
 601                                     pushStringListElement(qName, attributes,
 602                                             (int) Math.log10(Double.parseDouble(attributes.getValue("type"))));
 603                                 } else {
 604                                     pushIgnoredContainer(qName);
 605                                 }
 606                                 break;
 607                             default:
 608                                 pushIgnoredContainer(qName);
 609                                 break;
 610                         }
 611                     }
 612                     break;
 613                 default:
 614                     pushContainer(qName, attributes);
 615                     break;
 616             }
 617             break;
 618         case "currencyFormats":
 619         case "decimalFormats":
 620         case "percentFormats":
 621             {
 622                 String script = attributes.getValue("numberSystem");
 623                 if (script != null) {
 624                     addNumberingScript(script);
 625                     currentNumberingSystem = script + ".";
 626                 }
 627                 pushContainer(qName, attributes);
 628             }
 629             break;
 630         case "currencyFormatLength":
 631             if (attributes.getValue("type") == null) {
 632                 // skipping type="short" data
 633                 // for FormatData
 634                 pushContainer(qName, attributes);
 635             } else {
 636                 pushIgnoredContainer(qName);
 637             }
 638             break;


























 639         case "defaultNumberingSystem":
 640             // default numbering system if multiple numbering systems are used.
 641             pushStringEntry(qName, attributes, "DefaultNumberingSystem");
 642             break;
 643         case "symbols":
 644             // for FormatData
 645             // look up numberingSystems
 646             symbols: {
 647                 String script = attributes.getValue("numberSystem");
 648                 if (script == null) {
 649                     // Has no script. Just ignore.
 650                     pushIgnoredContainer(qName);
 651                     break;
 652                 }
 653 
 654                 // Use keys as <script>."NumberElements/<symbol>"
 655                 currentNumberingSystem = script + ".";
 656                 String digits = CLDRConverter.handlerNumbering.get(script);
 657                 if (digits == null) {
 658                     pushIgnoredContainer(qName);


 752                 // for FormatData
 753                 // copy string for later assembly into DateTimePatterns
 754                 String prefix = (currentCalendarType == null) ? "" : currentCalendarType.keyElementName();
 755                 pushStringEntry(qName, attributes, prefix + "DateTimePatterns/" + attributes.getValue("type") + "-dateTime");
 756             }
 757             break;
 758         case "localizedPatternChars":
 759             {
 760                 // for FormatData
 761                 // copy string for later adaptation to JRE use
 762                 String prefix = (currentCalendarType == null) ? "" : currentCalendarType.keyElementName();
 763                 pushStringEntry(qName, attributes, prefix + "DateTimePatternChars");
 764             }
 765             break;
 766 
 767         // "alias" for root
 768         case "alias":
 769             {
 770                 if (id.equals("root") && !isIgnored(attributes)
 771                         && ((currentContainer.getqName().equals("decimalFormatLength"))
 772                         || (currentContainer.getqName().equals("currencyFormat"))
 773                         || (currentContainer.getqName().equals("percentFormat"))
 774                         || (currentCalendarType != null && !currentCalendarType.lname().startsWith("islamic-")))) { // ignore islamic variants
 775                     pushAliasEntry(qName, attributes, attributes.getValue("path"));
 776                 } else {
 777                     pushIgnoredContainer(qName);
 778                 }
 779             }
 780             break;
 781 
 782         default:
 783             // treat anything else as a container
 784             pushContainer(qName, attributes);
 785             break;
 786         }
 787     }
 788 
 789     private static final String[] CONTEXTS = {"stand-alone", "format"};
 790     private static final String[] WIDTHS = {"wide", "narrow", "abbreviated"};
 791     private static final String[] LENGTHS = {"full", "long", "medium", "short"};
 792 
 793     private void populateWidthAlias(String type, Set<String> keys) {


 909         case "eraNames":
 910             keyName = "long.Eras";
 911             break;
 912         case "eraAbbr":
 913             keyName = "Eras";
 914             break;
 915         case "eraNarrow":
 916             keyName = "narrow.Eras";
 917             break;
 918         case "dateFormats":
 919         case "timeFormats":
 920         case "days":
 921         case "months":
 922         case "quarters":
 923         case "dayPeriods":
 924         case "eras":
 925             break;
 926         case "decimalFormatLength": // used for compact number formatting patterns
 927             keyName = type + ".CompactNumberPatterns";
 928             break;
 929         case "currencyFormat":
 930         case "percentFormat":
 931             keyName = currentNumberingSystem +
 932                     "NumberPatterns/" +
 933                     (type.equals("standard") ? containerqName.replaceFirst("Format", "") : type);
 934             break;
 935         default:
 936             keyName = "";
 937             break;
 938         }
 939 
 940         return keyName;
 941     }
 942 
 943     private String getTarget(String path, String calType, String context, String width) {
 944         // Target qName
 945         int lastSlash = path.lastIndexOf('/');
 946         String qName = path.substring(lastSlash+1);
 947         int bracket = qName.indexOf('[');
 948         if (bracket != -1) {
 949             qName = qName.substring(0, bracket);
 950         }
 951 
 952         // calType
 953         String typeKey = "/calendar[@type='";
 954         int start = path.indexOf(typeKey);


 961         start = path.indexOf(typeKey);
 962         if (start != -1) {
 963             context = (path.substring(start+typeKey.length(), path.indexOf("']", start)));
 964         }
 965 
 966         // width
 967         typeKey = "Width[@type='";
 968         start = path.indexOf(typeKey);
 969         if (start != -1) {
 970             width = path.substring(start+typeKey.length(), path.indexOf("']", start));
 971         }
 972 
 973         // used for compact number formatting patterns aliases
 974         typeKey = "decimalFormatLength[@type='";
 975         start = path.indexOf(typeKey);
 976         if (start != -1) {
 977             String style = path.substring(start + typeKey.length(), path.indexOf("']", start));
 978             return toJDKKey(qName, "", style);
 979         }
 980 
 981         // currencyFormat
 982         typeKey = "currencyFormat[@type='";
 983         start = path.indexOf(typeKey);
 984         if (start != -1) {
 985             String style = path.substring(start + typeKey.length(), path.indexOf("']", start));
 986             return toJDKKey(qName, "", style);
 987         }
 988 
 989         // percentFormat
 990         typeKey = "percentFormat[@type='";
 991         start = path.indexOf(typeKey);
 992         if (start != -1) {
 993             String style = path.substring(start + typeKey.length(), path.indexOf("']", start));
 994             return toJDKKey(qName, "", style);
 995         }
 996 
 997         return calType + "." + toJDKKey(qName, context, width);
 998     }
 999 
1000     @Override
1001     public void endElement(String uri, String localName, String qName) throws SAXException {
1002         assert qName.equals(currentContainer.getqName()) : "current=" + currentContainer.getqName() + ", param=" + qName;
1003         switch (qName) {
1004         case "calendar":
1005             assert !(currentContainer instanceof Entry);
1006             currentCalendarType = null;
1007             break;
1008 
1009         case "defaultNumberingSystem":
1010             if (currentContainer instanceof StringEntry) {
1011                 defaultNumberingSystem = (String) putIfEntry();


1012             } else {
1013                 defaultNumberingSystem = null;
1014             }
1015             break;
1016 
1017         case "timeZoneNames":
1018             zonePrefix = null;
1019             break;
1020 
1021         case "generic":
1022         case "standard":
1023         case "daylight":
1024         case "exemplarCity":
1025             if (zonePrefix != null && (currentContainer instanceof Entry)) {
1026                 @SuppressWarnings("unchecked")
1027                 Map<String, String> valmap = (Map<String, String>) get(zonePrefix + getContainerKey());
1028                 Entry<?> entry = (Entry<?>) currentContainer;
1029                 if (qName.equals("exemplarCity")) {
1030                     put(CLDRConverter.EXEMPLAR_CITY_PREFIX + getContainerKey(), (String) entry.getValue());
1031                 } else {


1050             putIfEntry();
1051             break;
1052         case "decimalFormatLength":
1053             currentStyle = "";
1054             compactCount = "";
1055             putIfEntry();
1056             break;
1057         case "currencyFormats":
1058         case "decimalFormats":
1059         case "percentFormats":
1060         case "symbols":
1061             currentNumberingSystem = "";
1062             putIfEntry();
1063             break;
1064         default:
1065             putIfEntry();
1066         }
1067         currentContainer = currentContainer.getParent();
1068     }
1069 
1070     private Object putIfEntry() {
1071         if (currentContainer instanceof AliasEntry) {
1072             Entry<?> entry = (Entry<?>) currentContainer;
1073             String containerqName = entry.getParent().getqName();
1074             if (containerqName.equals("decimalFormatLength")) {
1075                 String srcKey = toJDKKey(containerqName, "", currentStyle);
1076                 String targetKey = getTarget(entry.getKey(), "", "", "");
1077                 CLDRConverter.aliases.put(srcKey, targetKey);
1078             } else if (containerqName.equals("currencyFormat") ||
1079                         containerqName.equals("percentFormat")) {
1080                 KeyContainer kc = (KeyContainer)entry.getParent();
1081                 CLDRConverter.aliases.put(
1082                         toJDKKey(containerqName, "", kc.getKey()),
1083                         getTarget(entry.getKey(), "", "", "")
1084                 );
1085             } else {
1086                 Set<String> keyNames = populateAliasKeys(containerqName, currentContext, currentWidth);
1087                 if (!keyNames.isEmpty()) {
1088                     for (String keyName : keyNames) {
1089                         String[] tmp = keyName.split(",", 3);
1090                         String calType = currentCalendarType.lname();
1091                         String src = calType+"."+tmp[0];
1092                         String target = getTarget(
1093                                     entry.getKey(),
1094                                     calType,
1095                                     tmp[1].length()>0 ? tmp[1] : currentContext,
1096                                     tmp[2].length()>0 ? tmp[2] : currentWidth);
1097                         if (target.substring(target.lastIndexOf('.')+1).equals(containerqName)) {
1098                             target = target.substring(0, target.indexOf('.'))+"."+tmp[0];
1099                         }
1100                         CLDRConverter.aliases.put(src.replaceFirst("^gregorian.", ""),
1101                                                   target.replaceFirst("^gregorian.", ""));
1102                     }
1103                 }
1104             }
1105         } else if (currentContainer instanceof Entry) {
1106             Entry<?> entry = (Entry<?>) currentContainer;
1107             Object value = entry.getValue();
1108             if (value != null) {
1109                 String key = entry.getKey();
1110                 // Tweak for MonthNames for the root locale, Needed for
1111                 // SimpleDateFormat.format()/parse() roundtrip.
1112                 if (id.equals("root") && key.startsWith("MonthNames")) {
1113                     value = new DateFormatSymbols(Locale.US).getShortMonths();
1114                 }
1115                 return put(entry.getKey(), value);
1116             }
1117         }
1118         return null;
1119     }
1120 
1121     public String convertOldKeyName(String key) {
1122         // Explicitly obtained from "alias" attribute in each "key" element.
1123         switch (key) {
1124             case "calendar":
1125                 return "ca";
1126             case "currency":
1127                 return "cu";
1128             case "collation":
1129                 return "co";
1130             case "numbers":
1131                 return "nu";
1132             case "timezone":
1133                 return "tz";
1134             default:
1135                 return key;
1136         }
1137     }
1138 
< prev index next >