jdk/src/share/classes/sun/util/locale/InternalLocaleBuilder.java
changeset 9224 75c0420badef
parent 6501 684810d882b3
--- a/jdk/src/share/classes/sun/util/locale/InternalLocaleBuilder.java	Wed Apr 13 21:08:08 2011 +0400
+++ b/jdk/src/share/classes/sun/util/locale/InternalLocaleBuilder.java	Thu Apr 14 15:59:47 2011 +0900
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2011, 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
@@ -35,64 +35,66 @@
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 public final class InternalLocaleBuilder {
 
-    private String _language = "";
-    private String _script = "";
-    private String _region = "";
-    private String _variant = "";
+    private static final CaseInsensitiveChar PRIVATEUSE_KEY
+        = new CaseInsensitiveChar(LanguageTag.PRIVATEUSE);
 
-    private static final CaseInsensitiveChar PRIVUSE_KEY = new CaseInsensitiveChar(LanguageTag.PRIVATEUSE.charAt(0));
+    private String language = "";
+    private String script = "";
+    private String region = "";
+    private String variant = "";
 
-    private HashMap<CaseInsensitiveChar, String> _extensions;
-    private HashSet<CaseInsensitiveString> _uattributes;
-    private HashMap<CaseInsensitiveString, String> _ukeywords;
+    private Map<CaseInsensitiveChar, String> extensions;
+    private Set<CaseInsensitiveString> uattributes;
+    private Map<CaseInsensitiveString, String> ukeywords;
 
 
     public InternalLocaleBuilder() {
     }
 
     public InternalLocaleBuilder setLanguage(String language) throws LocaleSyntaxException {
-        if (language == null || language.length() == 0) {
-            _language = "";
+        if (LocaleUtils.isEmpty(language)) {
+            this.language = "";
         } else {
             if (!LanguageTag.isLanguage(language)) {
                 throw new LocaleSyntaxException("Ill-formed language: " + language, 0);
             }
-            _language = language;
+            this.language = language;
         }
         return this;
     }
 
     public InternalLocaleBuilder setScript(String script) throws LocaleSyntaxException {
-        if (script == null || script.length() == 0) {
-            _script = "";
+        if (LocaleUtils.isEmpty(script)) {
+            this.script = "";
         } else {
             if (!LanguageTag.isScript(script)) {
                 throw new LocaleSyntaxException("Ill-formed script: " + script, 0);
             }
-            _script = script;
+            this.script = script;
         }
         return this;
     }
 
     public InternalLocaleBuilder setRegion(String region) throws LocaleSyntaxException {
-        if (region == null || region.length() == 0) {
-            _region = "";
+        if (LocaleUtils.isEmpty(region)) {
+            this.region = "";
         } else {
             if (!LanguageTag.isRegion(region)) {
                 throw new LocaleSyntaxException("Ill-formed region: " + region, 0);
             }
-            _region = region;
+            this.region = region;
         }
         return this;
     }
 
     public InternalLocaleBuilder setVariant(String variant) throws LocaleSyntaxException {
-        if (variant == null || variant.length() == 0) {
-            _variant = "";
+        if (LocaleUtils.isEmpty(variant)) {
+            this.variant = "";
         } else {
             // normalize separators to "_"
             String var = variant.replaceAll(LanguageTag.SEP, BaseLocale.SEP);
@@ -100,7 +102,7 @@
             if (errIdx != -1) {
                 throw new LocaleSyntaxException("Ill-formed variant: " + variant, errIdx);
             }
-            _variant = var;
+            this.variant = var;
         }
         return this;
     }
@@ -110,10 +112,10 @@
             throw new LocaleSyntaxException("Ill-formed Unicode locale attribute: " + attribute);
         }
         // Use case insensitive string to prevent duplication
-        if (_uattributes == null) {
-            _uattributes = new HashSet<CaseInsensitiveString>(4);
+        if (uattributes == null) {
+            uattributes = new HashSet<>(4);
         }
-        _uattributes.add(new CaseInsensitiveString(attribute));
+        uattributes.add(new CaseInsensitiveString(attribute));
         return this;
     }
 
@@ -121,8 +123,8 @@
         if (attribute == null || !UnicodeLocaleExtension.isAttribute(attribute)) {
             throw new LocaleSyntaxException("Ill-formed Unicode locale attribute: " + attribute);
         }
-        if (_uattributes != null) {
-            _uattributes.remove(new CaseInsensitiveString(attribute));
+        if (uattributes != null) {
+            uattributes.remove(new CaseInsensitiveString(attribute));
         }
         return this;
     }
@@ -134,9 +136,9 @@
 
         CaseInsensitiveString cikey = new CaseInsensitiveString(key);
         if (type == null) {
-            if (_ukeywords != null) {
+            if (ukeywords != null) {
                 // null type is used for remove the key
-                _ukeywords.remove(cikey);
+                ukeywords.remove(cikey);
             }
         } else {
             if (type.length() != 0) {
@@ -147,15 +149,17 @@
                 while (!itr.isDone()) {
                     String s = itr.current();
                     if (!UnicodeLocaleExtension.isTypeSubtag(s)) {
-                        throw new LocaleSyntaxException("Ill-formed Unicode locale keyword type: " + type, itr.currentStart());
+                        throw new LocaleSyntaxException("Ill-formed Unicode locale keyword type: "
+                                                        + type,
+                                                        itr.currentStart());
                     }
                     itr.next();
                 }
             }
-            if (_ukeywords == null) {
-                _ukeywords = new HashMap<CaseInsensitiveString, String>(4);
+            if (ukeywords == null) {
+                ukeywords = new HashMap<>(4);
             }
-            _ukeywords.put(cikey, type);
+            ukeywords.put(cikey, type);
         }
         return this;
     }
@@ -167,21 +171,21 @@
             throw new LocaleSyntaxException("Ill-formed extension key: " + singleton);
         }
 
-        boolean remove = (value == null || value.length() == 0);
+        boolean remove = LocaleUtils.isEmpty(value);
         CaseInsensitiveChar key = new CaseInsensitiveChar(singleton);
 
         if (remove) {
             if (UnicodeLocaleExtension.isSingletonChar(key.value())) {
                 // clear entire Unicode locale extension
-                if (_uattributes != null) {
-                    _uattributes.clear();
+                if (uattributes != null) {
+                    uattributes.clear();
                 }
-                if (_ukeywords != null) {
-                    _ukeywords.clear();
+                if (ukeywords != null) {
+                    ukeywords.clear();
                 }
             } else {
-                if (_extensions != null && _extensions.containsKey(key)) {
-                    _extensions.remove(key);
+                if (extensions != null && extensions.containsKey(key)) {
+                    extensions.remove(key);
                 }
             }
         } else {
@@ -197,7 +201,8 @@
                     validSubtag = LanguageTag.isExtensionSubtag(s);
                 }
                 if (!validSubtag) {
-                    throw new LocaleSyntaxException("Ill-formed extension value: " + s, itr.currentStart());
+                    throw new LocaleSyntaxException("Ill-formed extension value: " + s,
+                                                    itr.currentStart());
                 }
                 itr.next();
             }
@@ -205,10 +210,10 @@
             if (UnicodeLocaleExtension.isSingletonChar(key.value())) {
                 setUnicodeLocaleExtension(val);
             } else {
-                if (_extensions == null) {
-                    _extensions = new HashMap<CaseInsensitiveChar, String>(4);
+                if (extensions == null) {
+                    extensions = new HashMap<>(4);
                 }
-                _extensions.put(key, val);
+                extensions.put(key, val);
             }
         }
         return this;
@@ -218,7 +223,7 @@
      * Set extension/private subtags in a single string representation
      */
     public InternalLocaleBuilder setExtensions(String subtags) throws LocaleSyntaxException {
-        if (subtags == null || subtags.length() == 0) {
+        if (LocaleUtils.isEmpty(subtags)) {
             clearExtensions();
             return this;
         }
@@ -252,11 +257,12 @@
                 }
 
                 if (parsed < start) {
-                    throw new LocaleSyntaxException("Incomplete extension '" + singleton + "'", start);
+                    throw new LocaleSyntaxException("Incomplete extension '" + singleton + "'",
+                                                    start);
                 }
 
                 if (extensions == null) {
-                    extensions = new ArrayList<String>(4);
+                    extensions = new ArrayList<>(4);
                 }
                 extensions.add(sb.toString());
             } else {
@@ -281,7 +287,9 @@
                     itr.next();
                 }
                 if (parsed <= start) {
-                    throw new LocaleSyntaxException("Incomplete privateuse:" + subtags.substring(start), start);
+                    throw new LocaleSyntaxException("Incomplete privateuse:"
+                                                    + subtags.substring(start),
+                                                    start);
                 } else {
                     privateuse = sb.toString();
                 }
@@ -289,7 +297,9 @@
         }
 
         if (!itr.isDone()) {
-            throw new LocaleSyntaxException("Ill-formed extension subtags:" + subtags.substring(itr.currentStart()), itr.currentStart());
+            throw new LocaleSyntaxException("Ill-formed extension subtags:"
+                                            + subtags.substring(itr.currentStart()),
+                                            itr.currentStart());
         }
 
         return setExtensions(extensions, privateuse);
@@ -302,30 +312,31 @@
     private InternalLocaleBuilder setExtensions(List<String> bcpExtensions, String privateuse) {
         clearExtensions();
 
-        if (bcpExtensions != null && bcpExtensions.size() > 0) {
-            HashSet<CaseInsensitiveChar> processedExntensions = new HashSet<CaseInsensitiveChar>(bcpExtensions.size());
+        if (!LocaleUtils.isEmpty(bcpExtensions)) {
+            Set<CaseInsensitiveChar> done = new HashSet<>(bcpExtensions.size());
             for (String bcpExt : bcpExtensions) {
-                CaseInsensitiveChar key = new CaseInsensitiveChar(bcpExt.charAt(0));
+                CaseInsensitiveChar key = new CaseInsensitiveChar(bcpExt);
                 // ignore duplicates
-                if (!processedExntensions.contains(key)) {
+                if (!done.contains(key)) {
                     // each extension string contains singleton, e.g. "a-abc-def"
                     if (UnicodeLocaleExtension.isSingletonChar(key.value())) {
                         setUnicodeLocaleExtension(bcpExt.substring(2));
                     } else {
-                        if (_extensions == null) {
-                            _extensions = new HashMap<CaseInsensitiveChar, String>(4);
+                        if (extensions == null) {
+                            extensions = new HashMap<>(4);
                         }
-                        _extensions.put(key, bcpExt.substring(2));
+                        extensions.put(key, bcpExt.substring(2));
                     }
                 }
+                done.add(key);
             }
         }
         if (privateuse != null && privateuse.length() > 0) {
             // privateuse string contains prefix, e.g. "x-abc-def"
-            if (_extensions == null) {
-                _extensions = new HashMap<CaseInsensitiveChar, String>(1);
+            if (extensions == null) {
+                extensions = new HashMap<>(1);
             }
-            _extensions.put(new CaseInsensitiveChar(privateuse.charAt(0)), privateuse.substring(2));
+            extensions.put(new CaseInsensitiveChar(privateuse), privateuse.substring(2));
         }
 
         return this;
@@ -336,24 +347,25 @@
      */
     public InternalLocaleBuilder setLanguageTag(LanguageTag langtag) {
         clear();
-        if (langtag.getExtlangs().size() > 0) {
-            _language = langtag.getExtlangs().get(0);
+        if (!langtag.getExtlangs().isEmpty()) {
+            language = langtag.getExtlangs().get(0);
         } else {
-            String language = langtag.getLanguage();
-            if (!language.equals(LanguageTag.UNDETERMINED)) {
-                _language = language;
+            String lang = langtag.getLanguage();
+            if (!lang.equals(LanguageTag.UNDETERMINED)) {
+                language = lang;
             }
         }
-        _script = langtag.getScript();
-        _region = langtag.getRegion();
+        script = langtag.getScript();
+        region = langtag.getRegion();
 
         List<String> bcpVariants = langtag.getVariants();
-        if (bcpVariants.size() > 0) {
+        if (!bcpVariants.isEmpty()) {
             StringBuilder var = new StringBuilder(bcpVariants.get(0));
-            for (int i = 1; i < bcpVariants.size(); i++) {
+            int size = bcpVariants.size();
+            for (int i = 1; i < size; i++) {
                 var.append(BaseLocale.SEP).append(bcpVariants.get(i));
             }
-            _variant = var.toString();
+            variant = var.toString();
         }
 
         setExtensions(langtag.getExtensions(), langtag.getPrivateuse());
@@ -361,7 +373,7 @@
         return this;
     }
 
-    public InternalLocaleBuilder setLocale(BaseLocale base, LocaleExtensions extensions) throws LocaleSyntaxException {
+    public InternalLocaleBuilder setLocale(BaseLocale base, LocaleExtensions localeExtensions) throws LocaleSyntaxException {
         String language = base.getLanguage();
         String script = base.getScript();
         String region = base.getRegion();
@@ -373,14 +385,14 @@
         if (language.equals("ja") && region.equals("JP") && variant.equals("JP")) {
             // When locale ja_JP_JP is created, ca-japanese is always there.
             // The builder ignores the variant "JP"
-            assert("japanese".equals(extensions.getUnicodeLocaleType("ca")));
+            assert("japanese".equals(localeExtensions.getUnicodeLocaleType("ca")));
             variant = "";
         }
         // Exception 2 - th_TH_TH
         else if (language.equals("th") && region.equals("TH") && variant.equals("TH")) {
             // When locale th_TH_TH is created, nu-thai is always there.
             // The builder ignores the variant "TH"
-            assert("thai".equals(extensions.getUnicodeLocaleType("nu")));
+            assert("thai".equals(localeExtensions.getUnicodeLocaleType("nu")));
             variant = "";
         }
         // Exception 3 - no_NO_NY
@@ -415,36 +427,36 @@
 
         // The input locale is validated at this point.
         // Now, updating builder's internal fields.
-        _language = language;
-        _script = script;
-        _region = region;
-        _variant = variant;
+        this.language = language;
+        this.script = script;
+        this.region = region;
+        this.variant = variant;
         clearExtensions();
 
-        Set<Character> extKeys = (extensions == null) ? null : extensions.getKeys();
+        Set<Character> extKeys = (localeExtensions == null) ? null : localeExtensions.getKeys();
         if (extKeys != null) {
-            // map extensions back to builder's internal format
+            // map localeExtensions back to builder's internal format
             for (Character key : extKeys) {
-                Extension e = extensions.getExtension(key);
+                Extension e = localeExtensions.getExtension(key);
                 if (e instanceof UnicodeLocaleExtension) {
                     UnicodeLocaleExtension ue = (UnicodeLocaleExtension)e;
                     for (String uatr : ue.getUnicodeLocaleAttributes()) {
-                        if (_uattributes == null) {
-                            _uattributes = new HashSet<CaseInsensitiveString>(4);
+                        if (uattributes == null) {
+                            uattributes = new HashSet<>(4);
                         }
-                        _uattributes.add(new CaseInsensitiveString(uatr));
+                        uattributes.add(new CaseInsensitiveString(uatr));
                     }
                     for (String ukey : ue.getUnicodeLocaleKeys()) {
-                        if (_ukeywords == null) {
-                            _ukeywords = new HashMap<CaseInsensitiveString, String>(4);
+                        if (ukeywords == null) {
+                            ukeywords = new HashMap<>(4);
                         }
-                        _ukeywords.put(new CaseInsensitiveString(ukey), ue.getUnicodeLocaleType(ukey));
+                        ukeywords.put(new CaseInsensitiveString(ukey), ue.getUnicodeLocaleType(ukey));
                     }
                 } else {
-                    if (_extensions == null) {
-                        _extensions = new HashMap<CaseInsensitiveChar, String>(4);
+                    if (extensions == null) {
+                        extensions = new HashMap<>(4);
                     }
-                    _extensions.put(new CaseInsensitiveChar(key.charValue()), e.getValue());
+                    extensions.put(new CaseInsensitiveChar(key), e.getValue());
                 }
             }
         }
@@ -452,37 +464,37 @@
     }
 
     public InternalLocaleBuilder clear() {
-        _language = "";
-        _script = "";
-        _region = "";
-        _variant = "";
+        language = "";
+        script = "";
+        region = "";
+        variant = "";
         clearExtensions();
         return this;
     }
 
     public InternalLocaleBuilder clearExtensions() {
-        if (_extensions != null) {
-            _extensions.clear();
+        if (extensions != null) {
+            extensions.clear();
         }
-        if (_uattributes != null) {
-            _uattributes.clear();
+        if (uattributes != null) {
+            uattributes.clear();
         }
-        if (_ukeywords != null) {
-            _ukeywords.clear();
+        if (ukeywords != null) {
+            ukeywords.clear();
         }
         return this;
     }
 
     public BaseLocale getBaseLocale() {
-        String language = _language;
-        String script = _script;
-        String region = _region;
-        String variant = _variant;
+        String language = this.language;
+        String script = this.script;
+        String region = this.region;
+        String variant = this.variant;
 
         // Special private use subtag sequence identified by "lvariant" will be
         // interpreted as Java variant.
-        if (_extensions != null) {
-            String privuse = _extensions.get(PRIVUSE_KEY);
+        if (extensions != null) {
+            String privuse = extensions.get(PRIVATEUSE_KEY);
             if (privuse != null) {
                 StringTokenIterator itr = new StringTokenIterator(privuse, LanguageTag.SEP);
                 boolean sawPrefix = false;
@@ -492,7 +504,7 @@
                         privVarStart = itr.currentStart();
                         break;
                     }
-                    if (AsciiUtil.caseIgnoreMatch(itr.current(), LanguageTag.PRIVUSE_VARIANT_PREFIX)) {
+                    if (LocaleUtils.caseIgnoreMatch(itr.current(), LanguageTag.PRIVUSE_VARIANT_PREFIX)) {
                         sawPrefix = true;
                     }
                     itr.next();
@@ -502,7 +514,8 @@
                     if (sb.length() != 0) {
                         sb.append(BaseLocale.SEP);
                     }
-                    sb.append(privuse.substring(privVarStart).replaceAll(LanguageTag.SEP, BaseLocale.SEP));
+                    sb.append(privuse.substring(privVarStart).replaceAll(LanguageTag.SEP,
+                                                                         BaseLocale.SEP));
                     variant = sb.toString();
                 }
             }
@@ -512,13 +525,13 @@
     }
 
     public LocaleExtensions getLocaleExtensions() {
-        if ((_extensions == null || _extensions.size() == 0)
-                && (_uattributes == null || _uattributes.size() == 0)
-                && (_ukeywords == null || _ukeywords.size() == 0)) {
-            return LocaleExtensions.EMPTY_EXTENSIONS;
+        if (LocaleUtils.isEmpty(extensions) && LocaleUtils.isEmpty(uattributes)
+            && LocaleUtils.isEmpty(ukeywords)) {
+            return null;
         }
 
-        return new LocaleExtensions(_extensions, _uattributes, _ukeywords);
+        LocaleExtensions lext = new LocaleExtensions(extensions, uattributes, ukeywords);
+        return lext.isEmpty() ? null : lext;
     }
 
     /*
@@ -540,7 +553,7 @@
                 sawPrivuseVar = true;
                 break;
             }
-            if (AsciiUtil.caseIgnoreMatch(itr.current(), LanguageTag.PRIVUSE_VARIANT_PREFIX)) {
+            if (LocaleUtils.caseIgnoreMatch(itr.current(), LanguageTag.PRIVUSE_VARIANT_PREFIX)) {
                 prefixStart = itr.currentStart();
             }
             itr.next();
@@ -576,11 +589,11 @@
      */
     private void setUnicodeLocaleExtension(String subtags) {
         // wipe out existing attributes/keywords
-        if (_uattributes != null) {
-            _uattributes.clear();
+        if (uattributes != null) {
+            uattributes.clear();
         }
-        if (_ukeywords != null) {
-            _ukeywords.clear();
+        if (ukeywords != null) {
+            ukeywords.clear();
         }
 
         StringTokenIterator itr = new StringTokenIterator(subtags, LanguageTag.SEP);
@@ -590,10 +603,10 @@
             if (!UnicodeLocaleExtension.isAttribute(itr.current())) {
                 break;
             }
-            if (_uattributes == null) {
-                _uattributes = new HashSet<CaseInsensitiveString>(4);
+            if (uattributes == null) {
+                uattributes = new HashSet<>(4);
             }
-            _uattributes.add(new CaseInsensitiveString(itr.current()));
+            uattributes.add(new CaseInsensitiveString(itr.current()));
             itr.next();
         }
 
@@ -608,14 +621,14 @@
                     // next keyword - emit previous one
                     assert(typeStart == -1 || typeEnd != -1);
                     type = (typeStart == -1) ? "" : subtags.substring(typeStart, typeEnd);
-                    if (_ukeywords == null) {
-                        _ukeywords = new HashMap<CaseInsensitiveString, String>(4);
+                    if (ukeywords == null) {
+                        ukeywords = new HashMap<>(4);
                     }
-                    _ukeywords.put(key, type);
+                    ukeywords.put(key, type);
 
                     // reset keyword info
                     CaseInsensitiveString tmpKey = new CaseInsensitiveString(itr.current());
-                    key = _ukeywords.containsKey(tmpKey) ? null : tmpKey;
+                    key = ukeywords.containsKey(tmpKey) ? null : tmpKey;
                     typeStart = typeEnd = -1;
                 } else {
                     if (typeStart == -1) {
@@ -627,7 +640,7 @@
                 // 1. first keyword or
                 // 2. next keyword, but previous one was duplicate
                 key = new CaseInsensitiveString(itr.current());
-                if (_ukeywords != null && _ukeywords.containsKey(key)) {
+                if (ukeywords != null && ukeywords.containsKey(key)) {
                     // duplicate
                     key = null;
                 }
@@ -638,10 +651,10 @@
                     // last keyword
                     assert(typeStart == -1 || typeEnd != -1);
                     type = (typeStart == -1) ? "" : subtags.substring(typeStart, typeEnd);
-                    if (_ukeywords == null) {
-                        _ukeywords = new HashMap<CaseInsensitiveString, String>(4);
+                    if (ukeywords == null) {
+                        ukeywords = new HashMap<>(4);
                     }
-                    _ukeywords.put(key, type);
+                    ukeywords.put(key, type);
                 }
                 break;
             }
@@ -650,21 +663,24 @@
         }
     }
 
-    static class CaseInsensitiveString {
-        private String _s;
+    static final class CaseInsensitiveString {
+        private final String str, lowerStr;
 
         CaseInsensitiveString(String s) {
-            _s = s;
+            str = s;
+            lowerStr = LocaleUtils.toLowerString(s);
         }
 
         public String value() {
-            return _s;
+            return str;
         }
 
+        @Override
         public int hashCode() {
-            return AsciiUtil.toLowerString(_s).hashCode();
+            return lowerStr.hashCode();
         }
 
+        @Override
         public boolean equals(Object obj) {
             if (this == obj) {
                 return true;
@@ -672,25 +688,36 @@
             if (!(obj instanceof CaseInsensitiveString)) {
                 return false;
             }
-            return AsciiUtil.caseIgnoreMatch(_s, ((CaseInsensitiveString)obj).value());
+            return lowerStr.equals(((CaseInsensitiveString)obj).lowerStr);
         }
     }
 
-    static class CaseInsensitiveChar {
-        private char _c;
+    static final class CaseInsensitiveChar {
+        private final char ch, lowerCh;
+
+        /**
+         * Constructs a CaseInsensitiveChar with the first char of the
+         * given s.
+         */
+        private CaseInsensitiveChar(String s) {
+            this(s.charAt(0));
+        }
 
         CaseInsensitiveChar(char c) {
-            _c = c;
+            ch = c;
+            lowerCh = LocaleUtils.toLower(ch);
         }
 
         public char value() {
-            return _c;
+            return ch;
         }
 
+        @Override
         public int hashCode() {
-            return AsciiUtil.toLower(_c);
+            return lowerCh;
         }
 
+        @Override
         public boolean equals(Object obj) {
             if (this == obj) {
                 return true;
@@ -698,8 +725,7 @@
             if (!(obj instanceof CaseInsensitiveChar)) {
                 return false;
             }
-            return _c ==  AsciiUtil.toLower(((CaseInsensitiveChar)obj).value());
+            return lowerCh == ((CaseInsensitiveChar)obj).lowerCh;
         }
-
     }
 }