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
|