jdk/src/share/classes/sun/util/locale/LocaleExtensions.java
changeset 9224 75c0420badef
parent 6501 684810d882b3
equal deleted inserted replaced
9223:d331b7996fc3 9224:75c0420badef
     1 /*
     1 /*
     2  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    34 import java.util.Collections;
    34 import java.util.Collections;
    35 import java.util.Map;
    35 import java.util.Map;
    36 import java.util.Map.Entry;
    36 import java.util.Map.Entry;
    37 import java.util.Set;
    37 import java.util.Set;
    38 import java.util.SortedMap;
    38 import java.util.SortedMap;
       
    39 import java.util.SortedSet;
    39 import java.util.TreeMap;
    40 import java.util.TreeMap;
    40 import java.util.TreeSet;
    41 import java.util.TreeSet;
    41 
    42 
    42 import sun.util.locale.InternalLocaleBuilder.CaseInsensitiveChar;
    43 import sun.util.locale.InternalLocaleBuilder.CaseInsensitiveChar;
    43 import sun.util.locale.InternalLocaleBuilder.CaseInsensitiveString;
    44 import sun.util.locale.InternalLocaleBuilder.CaseInsensitiveString;
    44 
    45 
    45 
    46 
    46 public class LocaleExtensions {
    47 public class LocaleExtensions {
    47 
    48 
    48     private SortedMap<Character, Extension> _map;
    49     private final Map<Character, Extension> extensionMap;
    49     private String _id;
    50     private final String id;
    50 
    51 
    51     private static final SortedMap<Character, Extension> EMPTY_MAP =
    52     public static final LocaleExtensions CALENDAR_JAPANESE
    52         Collections.unmodifiableSortedMap(new TreeMap<Character, Extension>());
    53         = new LocaleExtensions("u-ca-japanese",
    53 
    54                                UnicodeLocaleExtension.SINGLETON,
    54     public static final LocaleExtensions EMPTY_EXTENSIONS;
    55                                UnicodeLocaleExtension.CA_JAPANESE);
    55     public static final LocaleExtensions CALENDAR_JAPANESE;
    56 
    56     public static final LocaleExtensions NUMBER_THAI;
    57     public static final LocaleExtensions NUMBER_THAI
    57 
    58         = new LocaleExtensions("u-nu-thai",
    58     static {
    59                                UnicodeLocaleExtension.SINGLETON,
    59         EMPTY_EXTENSIONS = new LocaleExtensions();
    60                                UnicodeLocaleExtension.NU_THAI);
    60         EMPTY_EXTENSIONS._id = "";
    61 
    61         EMPTY_EXTENSIONS._map = EMPTY_MAP;
    62     private LocaleExtensions(String id, Character key, Extension value) {
    62 
    63         this.id = id;
    63         CALENDAR_JAPANESE = new LocaleExtensions();
    64         this.extensionMap = Collections.singletonMap(key, value);
    64         CALENDAR_JAPANESE._id = "u-ca-japanese";
       
    65         CALENDAR_JAPANESE._map = new TreeMap<Character, Extension>();
       
    66         CALENDAR_JAPANESE._map.put(Character.valueOf(UnicodeLocaleExtension.SINGLETON), UnicodeLocaleExtension.CA_JAPANESE);
       
    67 
       
    68         NUMBER_THAI = new LocaleExtensions();
       
    69         NUMBER_THAI._id = "u-nu-thai";
       
    70         NUMBER_THAI._map = new TreeMap<Character, Extension>();
       
    71         NUMBER_THAI._map.put(Character.valueOf(UnicodeLocaleExtension.SINGLETON), UnicodeLocaleExtension.NU_THAI);
       
    72     }
       
    73 
       
    74     private LocaleExtensions() {
       
    75     }
    65     }
    76 
    66 
    77     /*
    67     /*
    78      * Package local constructor, only used by InternalLocaleBuilder.
    68      * Package private constructor, only used by InternalLocaleBuilder.
    79      */
    69      */
    80     LocaleExtensions(Map<CaseInsensitiveChar, String> extensions,
    70     LocaleExtensions(Map<CaseInsensitiveChar, String> extensions,
    81             Set<CaseInsensitiveString> uattributes, Map<CaseInsensitiveString, String> ukeywords) {
    71                      Set<CaseInsensitiveString> uattributes,
    82         boolean hasExtension = (extensions != null && extensions.size() > 0);
    72                      Map<CaseInsensitiveString, String> ukeywords) {
    83         boolean hasUAttributes = (uattributes != null && uattributes.size() > 0);
    73         boolean hasExtension = !LocaleUtils.isEmpty(extensions);
    84         boolean hasUKeywords = (ukeywords != null && ukeywords.size() > 0);
    74         boolean hasUAttributes = !LocaleUtils.isEmpty(uattributes);
       
    75         boolean hasUKeywords = !LocaleUtils.isEmpty(ukeywords);
    85 
    76 
    86         if (!hasExtension && !hasUAttributes && !hasUKeywords) {
    77         if (!hasExtension && !hasUAttributes && !hasUKeywords) {
    87             _map = EMPTY_MAP;
    78             id = "";
    88             _id = "";
    79             extensionMap = Collections.emptyMap();
    89             return;
    80             return;
    90         }
    81         }
    91 
    82 
    92         // Build extension map
    83         // Build extension map
    93         _map = new TreeMap<Character, Extension>();
    84         SortedMap<Character, Extension> map = new TreeMap<>();
    94         if (hasExtension) {
    85         if (hasExtension) {
    95             for (Entry<CaseInsensitiveChar, String> ext : extensions.entrySet()) {
    86             for (Entry<CaseInsensitiveChar, String> ext : extensions.entrySet()) {
    96                 char key = AsciiUtil.toLower(ext.getKey().value());
    87                 char key = LocaleUtils.toLower(ext.getKey().value());
    97                 String value = ext.getValue();
    88                 String value = ext.getValue();
    98 
    89 
    99                 if (LanguageTag.isPrivateusePrefixChar(key)) {
    90                 if (LanguageTag.isPrivateusePrefixChar(key)) {
   100                     // we need to exclude special variant in privuateuse, e.g. "x-abc-lvariant-DEF"
    91                     // we need to exclude special variant in privuateuse, e.g. "x-abc-lvariant-DEF"
   101                     value = InternalLocaleBuilder.removePrivateuseVariant(value);
    92                     value = InternalLocaleBuilder.removePrivateuseVariant(value);
   102                     if (value == null) {
    93                     if (value == null) {
   103                         continue;
    94                         continue;
   104                     }
    95                     }
   105                 }
    96                 }
   106 
    97 
   107                 Extension e = new Extension(key, AsciiUtil.toLowerString(value));
    98                 map.put(key, new Extension(key, LocaleUtils.toLowerString(value)));
   108                 _map.put(Character.valueOf(key), e);
       
   109             }
    99             }
   110         }
   100         }
   111 
   101 
   112         if (hasUAttributes || hasUKeywords) {
   102         if (hasUAttributes || hasUKeywords) {
   113             TreeSet<String> uaset = null;
   103             SortedSet<String> uaset = null;
   114             TreeMap<String, String> ukmap = null;
   104             SortedMap<String, String> ukmap = null;
   115 
   105 
   116             if (hasUAttributes) {
   106             if (hasUAttributes) {
   117                 uaset = new TreeSet<String>();
   107                 uaset = new TreeSet<>();
   118                 for (CaseInsensitiveString cis : uattributes) {
   108                 for (CaseInsensitiveString cis : uattributes) {
   119                     uaset.add(AsciiUtil.toLowerString(cis.value()));
   109                     uaset.add(LocaleUtils.toLowerString(cis.value()));
   120                 }
   110                 }
   121             }
   111             }
   122 
   112 
   123             if (hasUKeywords) {
   113             if (hasUKeywords) {
   124                 ukmap = new TreeMap<String, String>();
   114                 ukmap = new TreeMap<>();
   125                 for (Entry<CaseInsensitiveString, String> kwd : ukeywords.entrySet()) {
   115                 for (Entry<CaseInsensitiveString, String> kwd : ukeywords.entrySet()) {
   126                     String key = AsciiUtil.toLowerString(kwd.getKey().value());
   116                     String key = LocaleUtils.toLowerString(kwd.getKey().value());
   127                     String type = AsciiUtil.toLowerString(kwd.getValue());
   117                     String type = LocaleUtils.toLowerString(kwd.getValue());
   128                     ukmap.put(key, type);
   118                     ukmap.put(key, type);
   129                 }
   119                 }
   130             }
   120             }
   131 
   121 
   132             UnicodeLocaleExtension ule = new UnicodeLocaleExtension(uaset, ukmap);
   122             UnicodeLocaleExtension ule = new UnicodeLocaleExtension(uaset, ukmap);
   133             _map.put(Character.valueOf(UnicodeLocaleExtension.SINGLETON), ule);
   123             map.put(UnicodeLocaleExtension.SINGLETON, ule);
   134         }
   124         }
   135 
   125 
   136         if (_map.size() == 0) {
   126         if (map.isEmpty()) {
   137             // this could happen when only privuateuse with special variant
   127             // this could happen when only privuateuse with special variant
   138             _map = EMPTY_MAP;
   128             id = "";
   139             _id = "";
   129             extensionMap = Collections.emptyMap();
   140         } else {
   130         } else {
   141             _id = toID(_map);
   131             id = toID(map);
       
   132             extensionMap = map;
   142         }
   133         }
   143     }
   134     }
   144 
   135 
   145     public Set<Character> getKeys() {
   136     public Set<Character> getKeys() {
   146         return Collections.unmodifiableSet(_map.keySet());
   137         if (extensionMap.isEmpty()) {
       
   138             return Collections.emptySet();
       
   139         }
       
   140         return Collections.unmodifiableSet(extensionMap.keySet());
   147     }
   141     }
   148 
   142 
   149     public Extension getExtension(Character key) {
   143     public Extension getExtension(Character key) {
   150         return _map.get(Character.valueOf(AsciiUtil.toLower(key.charValue())));
   144         return extensionMap.get(LocaleUtils.toLower(key));
   151     }
   145     }
   152 
   146 
   153     public String getExtensionValue(Character key) {
   147     public String getExtensionValue(Character key) {
   154         Extension ext = _map.get(Character.valueOf(AsciiUtil.toLower(key.charValue())));
   148         Extension ext = extensionMap.get(LocaleUtils.toLower(key));
   155         if (ext == null) {
   149         if (ext == null) {
   156             return null;
   150             return null;
   157         }
   151         }
   158         return ext.getValue();
   152         return ext.getValue();
   159     }
   153     }
   160 
   154 
   161     public Set<String> getUnicodeLocaleAttributes() {
   155     public Set<String> getUnicodeLocaleAttributes() {
   162         Extension ext = _map.get(Character.valueOf(UnicodeLocaleExtension.SINGLETON));
   156         Extension ext = extensionMap.get(UnicodeLocaleExtension.SINGLETON);
   163         if (ext == null) {
   157         if (ext == null) {
   164             return Collections.emptySet();
   158             return Collections.emptySet();
   165         }
   159         }
   166         assert (ext instanceof UnicodeLocaleExtension);
   160         assert (ext instanceof UnicodeLocaleExtension);
   167         return ((UnicodeLocaleExtension)ext).getUnicodeLocaleAttributes();
   161         return ((UnicodeLocaleExtension)ext).getUnicodeLocaleAttributes();
   168     }
   162     }
   169 
   163 
   170     public Set<String> getUnicodeLocaleKeys() {
   164     public Set<String> getUnicodeLocaleKeys() {
   171         Extension ext = _map.get(Character.valueOf(UnicodeLocaleExtension.SINGLETON));
   165         Extension ext = extensionMap.get(UnicodeLocaleExtension.SINGLETON);
   172         if (ext == null) {
   166         if (ext == null) {
   173             return Collections.emptySet();
   167             return Collections.emptySet();
   174         }
   168         }
   175         assert (ext instanceof UnicodeLocaleExtension);
   169         assert (ext instanceof UnicodeLocaleExtension);
   176         return ((UnicodeLocaleExtension)ext).getUnicodeLocaleKeys();
   170         return ((UnicodeLocaleExtension)ext).getUnicodeLocaleKeys();
   177     }
   171     }
   178 
   172 
   179     public String getUnicodeLocaleType(String unicodeLocaleKey) {
   173     public String getUnicodeLocaleType(String unicodeLocaleKey) {
   180         Extension ext = _map.get(Character.valueOf(UnicodeLocaleExtension.SINGLETON));
   174         Extension ext = extensionMap.get(UnicodeLocaleExtension.SINGLETON);
   181         if (ext == null) {
   175         if (ext == null) {
   182             return null;
   176             return null;
   183         }
   177         }
   184         assert (ext instanceof UnicodeLocaleExtension);
   178         assert (ext instanceof UnicodeLocaleExtension);
   185         return ((UnicodeLocaleExtension)ext).getUnicodeLocaleType(AsciiUtil.toLowerString(unicodeLocaleKey));
   179         return ((UnicodeLocaleExtension)ext).getUnicodeLocaleType(LocaleUtils.toLowerString(unicodeLocaleKey));
   186     }
   180     }
   187 
   181 
   188     public boolean isEmpty() {
   182     public boolean isEmpty() {
   189         return _map.isEmpty();
   183         return extensionMap.isEmpty();
   190     }
   184     }
   191 
   185 
   192     public static boolean isValidKey(char c) {
   186     public static boolean isValidKey(char c) {
   193         return LanguageTag.isExtensionSingletonChar(c) || LanguageTag.isPrivateusePrefixChar(c);
   187         return LanguageTag.isExtensionSingletonChar(c) || LanguageTag.isPrivateusePrefixChar(c);
   194     }
   188     }
   199 
   193 
   200     private static String toID(SortedMap<Character, Extension> map) {
   194     private static String toID(SortedMap<Character, Extension> map) {
   201         StringBuilder buf = new StringBuilder();
   195         StringBuilder buf = new StringBuilder();
   202         Extension privuse = null;
   196         Extension privuse = null;
   203         for (Entry<Character, Extension> entry : map.entrySet()) {
   197         for (Entry<Character, Extension> entry : map.entrySet()) {
   204             char singleton = entry.getKey().charValue();
   198             char singleton = entry.getKey();
   205             Extension extension = entry.getValue();
   199             Extension extension = entry.getValue();
   206             if (LanguageTag.isPrivateusePrefixChar(singleton)) {
   200             if (LanguageTag.isPrivateusePrefixChar(singleton)) {
   207                 privuse = extension;
   201                 privuse = extension;
   208             } else {
   202             } else {
   209                 if (buf.length() > 0) {
   203                 if (buf.length() > 0) {
   219             buf.append(privuse);
   213             buf.append(privuse);
   220         }
   214         }
   221         return buf.toString();
   215         return buf.toString();
   222     }
   216     }
   223 
   217 
   224 
   218     @Override
   225     public String toString() {
   219     public String toString() {
   226         return _id;
   220         return id;
   227     }
   221     }
   228 
   222 
   229     public String getID() {
   223     public String getID() {
   230         return _id;
   224         return id;
   231     }
   225     }
   232 
   226 
       
   227     @Override
   233     public int hashCode() {
   228     public int hashCode() {
   234         return _id.hashCode();
   229         return id.hashCode();
   235     }
   230     }
   236 
   231 
       
   232     @Override
   237     public boolean equals(Object other) {
   233     public boolean equals(Object other) {
   238         if (this == other) {
   234         if (this == other) {
   239             return true;
   235             return true;
   240         }
   236         }
   241         if (!(other instanceof LocaleExtensions)) {
   237         if (!(other instanceof LocaleExtensions)) {
   242             return false;
   238             return false;
   243         }
   239         }
   244         return this._id.equals(((LocaleExtensions)other)._id);
   240         return id.equals(((LocaleExtensions)other).id);
   245     }
   241     }
   246 }
   242 }