ICU-6646 Merge 4.0.1 changes and synchronize eclipse35 branch with maint-4-0 @ r25219.
X-SVN-Rev: 25226
diff --git a/.gitattributes b/.gitattributes
index 1934145..4f9e609 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -87,6 +87,7 @@
src/com/ibm/icu/dev/eclipse/features/com.ibm.icu/.project -text
src/com/ibm/icu/dev/eclipse/features/com.ibm.icu/build.properties -text
src/com/ibm/icu/dev/eclipse/features/com.ibm.icu/feature.xml -text
+src/com/ibm/icu/dev/eclipse/misc/ICUConfig.properties -text
src/com/ibm/icu/dev/eclipse/pdebuild/allElements.xml -text
src/com/ibm/icu/dev/eclipse/pdebuild/build.properties -text
src/com/ibm/icu/dev/eclipse/pdebuild/customTargets.xml -text
@@ -261,6 +262,7 @@
src/com/ibm/icu/dev/tool/docs/icu4j36.api.gz -text
src/com/ibm/icu/dev/tool/docs/icu4j38.api.gz -text
src/com/ibm/icu/dev/tool/docs/icu4j381.api.gz -text
+src/com/ibm/icu/dev/tool/docs/icu4j400.api.gz -text
src/com/ibm/icu/dev/tool/tzu/icu.gif -text
src/com/ibm/icu/dev/tool/tzu/runicutzu.bat -text
src/com/ibm/icu/dev/tool/tzu/runicutzu.cmd -text
diff --git a/APIChangeReport_401.html b/APIChangeReport_401.html
new file mode 100644
index 0000000..f507d0f
--- /dev/null
+++ b/APIChangeReport_401.html
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>ICU4J API Comparison: ICU4J 4.0 with ICU4J 4.0.1</title>
+<!-- Copyright 2009, IBM, All Rights Reserved. -->
+</head>
+<body>
+<h1>ICU4J API Comparison: ICU4J 4.0 with ICU4J 4.0.1</h1>
+
+<hr/>
+<h2>Removed from ICU4J 4.0</h2>
+<p>(no API removed)</p>
+
+<hr/>
+<h2>Withdrawn, Deprecated, or Obsoleted in ICU4J 4.0.1</h2>
+<p>(no API obsoleted)</p>
+
+<hr/>
+<h2>Changed in ICU4J 4.0.1 (old, new)</h2>
+<p>(no API changed)</p>
+
+<hr/>
+<h2>Promoted to stable in ICU4J 4.0.1</h2>
+<p>(no API promoted)</p>
+
+<hr/>
+<h2>Added in ICU4J 4.0.1</h2>
+<p>(no API added)</p>
+<hr/>
+<p><i><font size="-1">Contents generated by ReportAPI tool on Wed Jan 07 11:34:45 EST 2009<br/>Copyright (C) 2009, International Business Machines Corporation, All Rights Reserved.</font></i></p>
+</body>
+</html>
diff --git a/build.properties b/build.properties
index dc35618..7290ab2 100644
--- a/build.properties
+++ b/build.properties
@@ -1,6 +1,6 @@
#*
#*******************************************************************************
-#* Copyright (C) 2006-2008, International Business Machines Corporation and *
+#* Copyright (C) 2006-2009, International Business Machines Corporation and *
#* others. All Rights Reserved. *
#*******************************************************************************
#* This is the properties file for ICU4J builds.
@@ -11,22 +11,22 @@
# impl version will be updated for maintenance releases.
# It must be <icu4j.spec.version.string>[.<maint-version>]
-icu4j.impl.version.string=4.0
+icu4j.impl.version.string=4.0.1
# data version number won't be changed in a feature stream
icu4j.data.version.number=40
# these version numbers are used by API change report
-icu4j.version.number=400
-icu4j.previous.version.number=381
+icu4j.version.number=401
+icu4j.previous.version.number=400
-current.year=2008
+current.year=2009
api.report.out=${api.dir}/icu4j_compare_${icu4j.previous.version.number}_${icu4j.version.number}.html
-copyright=Copyright (c) 2000-2008, International Business Machines Corporation and others. All Rights Reserved.
+copyright=Copyright (c) 2000-2009, International Business Machines Corporation and others. All Rights Reserved.
corp=IBM Corporation
default.target.rt.version=J2SE15
-icu4j.plugin.impl.version.string=4.0.0
-copyright.eclipse=Licensed Materials - Property of IBM \n (C) Copyright IBM Corp. 2000, 2008. All Rights Reserved. \n IBM is a registered trademark of IBM Corp.
+icu4j.plugin.impl.version.string=4.0.1
+copyright.eclipse=Licensed Materials - Property of IBM \n (C) Copyright IBM Corp. 2000, 2009. All Rights Reserved. \n IBM is a registered trademark of IBM Corp.
-icu4j.eclipse.build.version.string=4.0.0.v20081201
\ No newline at end of file
+icu4j.eclipse.build.version.string=4.0.1.v20090109
diff --git a/build.xml b/build.xml
index c324e34..c66c2b2 100644
--- a/build.xml
+++ b/build.xml
@@ -1,7 +1,7 @@
<!--
/*
*******************************************************************************
-* Copyright (C) 1997-2008, International Business Machines Corporation and *
+* Copyright (C) 1997-2009, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
* This is the ant build file for ICU4J. See readme.html for more information.
@@ -1715,6 +1715,10 @@
includes="impl/**/*,lang/**/*,math/**/*,text/**/*,util/**/*"
excludes="**/.svn/**/*,**/*.jar,**/Transliterator_Han_Latin*.txt" />
</copy>
+ <!-- overwriting the ICU runtime configuration file for forcing ICU4J plugin to use JDK time zone rules -->
+ <copy file="${eclipse.dir}/misc/ICUConfig.properties"
+ toDir="${eclipse.projects.dir}/plugins/com.ibm.icu/src/com/ibm/icu"
+ overwrite="true"/>
<!-- icu data -->
<copy todir="${eclipse.projects.dir}/plugins/com.ibm.icu/src/com/ibm/icu/impl/data">
<fileset dir="${build.dir}/com/ibm/icu/impl/data"
diff --git a/license.html b/license.html
index cd07b36..ba2871a 100644
--- a/license.html
+++ b/license.html
@@ -11,7 +11,7 @@
<p>COPYRIGHT AND PERMISSION NOTICE</p>
<p>
-Copyright (c) 1995-2008 International Business Machines Corporation and others
+Copyright (c) 1995-2009 International Business Machines Corporation and others
</p>
<p>
All rights reserved.
diff --git a/readme.html b/readme.html
index 5b80456..8fd7e5d 100644
--- a/readme.html
+++ b/readme.html
@@ -4,25 +4,28 @@
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Content-Style-Type" content="text/css2">
<title>ReadMe for ICU4J</title>
- <meta name="COPYRIGHT" content="Copyright 2000-2008, International Business Machines Corporation and others. All Rights Reserved.">
+ <meta name="COPYRIGHT" content="Copyright 2000-2009, International Business Machines Corporation and others. All Rights Reserved.">
<style type="text/css">
h3.doc { background: #CCCCFF }
+h4.doc { text-decoration: underline }
</style>
</head>
<body style="background-color: rgb(255, 255, 255);" lang="EN-US"
link="#0000ff" vlink="#800080">
<h2>International Components for Unicode for Java (ICU4J)</h2>
-<h3>Read Me for ICU4J 4.0</h3>
+<h3>Read Me for ICU4J 4.0.1</h3>
<hr size="2" width="100%">
<p><b>Release Date</b><br>
-July 2, 2008<br>
+January 9, 2009<br>
</p>
<!-- <p><b>Note:</b> This is major release of ICU4J. It contains bug fixes
and adds implementations of inherited API and introduces new API
or functionality. -->
-<p><b>Note:</b> This is major release of ICU4J. It contains bug fixes and adds
-implementations of inherited API and introduces new API or functionality.
+<p><b>Note:</b> This is an update release of ICU4J 4.0. It contains bug fixes
+and adds implementations of inherited API, but does not introduce any new
+API or functionality. These changes will be rolled into the next major release
+of ICU4J.
</p>
<p>For the most recent release, see the <a
@@ -131,7 +134,7 @@
</blockquote>
<h3 class="doc"><a name="news"></a>What Is New In This Release?</h3>
-
+<h4 class="doc">4.0 (July 2, 2008)</h4>
<p><b>Status of ICU4J charset converter</b></p>
<p>The ICU4J implementation of java.nio.charset.Charset was included in ICU4J 3.8 as
a Technology Preview. In this release, all functionality from the java.nio.Charset
@@ -151,6 +154,28 @@
See the <a href="http://www.icu-project.org/download/">ICU 4.0 download page</a> about other
new features in this release.
</p>
+
+<h4 class="doc">4.0.1 (January 9, 2009)</h4>
+<p><b>Time zone data update</b></p>
+<p>ICU4J 4.0.1 updates the time zone data to version 2008i
+from the Olson tz database.</p>
+
+<p><b>Bug fixes</b></p>
+<p>This release contains following bug fixes (not a complete list)
+<ul>
+<li><a href="http://bugs.icu-project.org/trac/ticket/6361">#6361</a> Invalid behavor in MessageFormat for null values</li>
+<li><a href="http://bugs.icu-project.org/trac/ticket/6422">#6422</a> DurationFormat.getInstance(ULocale) throws MissingResourcesException</li>
+<li><a href="http://bugs.icu-project.org/trac/ticket/6459">#6459</a> ICU4J TimeZone#setDefault messes up historic time zone rules in JDK Calendar</li>
+<li><a href="http://bugs.icu-project.org/trac/ticket/6502">#6502</a> Holiday.getDisplayName(); doesn't work</li>
+<li><a href="http://bugs.icu-project.org/trac/ticket/6503">#6503</a> DateIntervalFormat creation is too slow</li>
+<li><a href="http://bugs.icu-project.org/trac/ticket/6612">#6612</a> ICU4J charset converter should not read source data beyond Buffer.limit()</li>
+<li><a href="http://bugs.icu-project.org/trac/ticket/6620">#6620</a> Default locale always taken for lenient parse of RuleBasedNumberFormat</li>
+<li><a href="http://bugs.icu-project.org/trac/ticket/6644">#6644</a> getDisplayName problem in ICU4J</li>
+<li><a href="http://bugs.icu-project.org/trac/ticket/6672">#6672</a> ULocale#getDefault() strips off keywords</li>
+<li><a href="http://bugs.icu-project.org/trac/ticket/6670">#6670</a> Test failure in format/TimeZoneTest/TestShortZoneIDs</li>
+</ul>
+</p>
+
<h3 class="doc"><a name="license"></a>License Information</h3>
<p>
The ICU projects (ICU4C and ICU4J) use the X license. The X
diff --git a/src/com/ibm/icu/charset/CharsetMBCS.java b/src/com/ibm/icu/charset/CharsetMBCS.java
index eec3e14..42c56fc 100644
--- a/src/com/ibm/icu/charset/CharsetMBCS.java
+++ b/src/com/ibm/icu/charset/CharsetMBCS.java
@@ -2516,7 +2516,7 @@
}
}
- if (!cr[0].isError() && sourceArrayIndex < source.capacity() && !target.hasRemaining()) {
+ if (!cr[0].isError() && sourceArrayIndex < source.limit() && !target.hasRemaining()) {
/* target is full */
cr[0] = CoderResult.OVERFLOW;
}
diff --git a/src/com/ibm/icu/dev/data/testdata.jar b/src/com/ibm/icu/dev/data/testdata.jar
index 75627bb..d1436ab 100644
--- a/src/com/ibm/icu/dev/data/testdata.jar
+++ b/src/com/ibm/icu/dev/data/testdata.jar
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:cb8928283d3b54908b633edf745e456f6eaa4127c7649f5a9e8cc6ab8b93c541
-size 764853
+oid sha256:eb85766f31d9d6a0c709a241d051c66cc70afb5825e662e5118841077c6e8710
+size 766031
diff --git a/src/com/ibm/icu/dev/eclipse/misc/ICUConfig.properties b/src/com/ibm/icu/dev/eclipse/misc/ICUConfig.properties
new file mode 100644
index 0000000..26dad40
--- /dev/null
+++ b/src/com/ibm/icu/dev/eclipse/misc/ICUConfig.properties
@@ -0,0 +1,12 @@
+#******************************************************************************
+# Copyright (C) 2008-2009, International Business Machines Corporation and *
+# others. All Rights Reserved. *
+#******************************************************************************
+# This is the properties contains ICU runtime configuration for eclispe plug-in
+#
+
+#
+# The default TimeZone implementation type used by the ICU TimeZone
+# factory method. [ ICU | JDK ]
+#
+com.ibm.icu.util.TimeZone.DefaultTimeZoneType = JDK
diff --git a/src/com/ibm/icu/dev/eclipse/misc/about_icu_base.html b/src/com/ibm/icu/dev/eclipse/misc/about_icu_base.html
index eb56ad1..d2703b8 100644
--- a/src/com/ibm/icu/dev/eclipse/misc/about_icu_base.html
+++ b/src/com/ibm/icu/dev/eclipse/misc/about_icu_base.html
@@ -8,7 +8,7 @@
<body lang="EN-US">
<h2>About This Content</h2>
-<p>July 2, 2008</p>
+<p>January 9, 2009</p>
<h3>License</h3>
<p>The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise
@@ -31,13 +31,13 @@
for informational purposes only, and you should look to the Redistributor's license for
terms and conditions of use.</p>
- <p><strong>ICU4J 4.0</strong> <br/><br/>
+ <p><strong>ICU4J 4.0.1</strong> <br/><br/>
The plug-in includes software ("ICU4J") developed by International Business Machines
Corporation and others.
<br/><br/>
ICU4J is:
<blockquote>
- Copyright (c) 1995-2008 International Business Machines Corporation and others<br/>
+ Copyright (c) 1995-2009 International Business Machines Corporation and others<br/>
All rights reserved.
</blockquote>
<p>
diff --git a/src/com/ibm/icu/dev/eclipse/plugins/com.ibm.icu.base.tests/META-INF/MANIFEST.MF b/src/com/ibm/icu/dev/eclipse/plugins/com.ibm.icu.base.tests/META-INF/MANIFEST.MF
index 50533a2..0bb57f0 100644
--- a/src/com/ibm/icu/dev/eclipse/plugins/com.ibm.icu.base.tests/META-INF/MANIFEST.MF
+++ b/src/com/ibm/icu/dev/eclipse/plugins/com.ibm.icu.base.tests/META-INF/MANIFEST.MF
@@ -5,7 +5,7 @@
Bundle-Version: 1.0.0
Bundle-Vendor: IBM
Bundle-Copyright: @COPYRIGHT@
-Fragment-Host: com.ibm.icu.base;bundle-version="[3.4.3,4.1.0)"
+Fragment-Host: com.ibm.icu.base;bundle-version="[4.0.0,4.2.0)"
Bundle-Localization: plugin
Bundle-RequiredExecutionEnvironment: J2SE-1.3,
CDC-1.0/Foundation-1.0
diff --git a/src/com/ibm/icu/dev/eclipse/plugins/com.ibm.icu.base/META-INF/MANIFEST.MF b/src/com/ibm/icu/dev/eclipse/plugins/com.ibm.icu.base/META-INF/MANIFEST.MF
index 573dfc2..891a87e 100644
--- a/src/com/ibm/icu/dev/eclipse/plugins/com.ibm.icu.base/META-INF/MANIFEST.MF
+++ b/src/com/ibm/icu/dev/eclipse/plugins/com.ibm.icu.base/META-INF/MANIFEST.MF
@@ -6,8 +6,8 @@
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Bundle-Copyright: @COPYRIGHT@
-Export-Package: com.ibm.icu.text;version="@IMPL_VERSION@",
- com.ibm.icu.util;version="@IMPL_VERSION@"
+Export-Package: com.ibm.icu.text;base=true;version="@IMPL_VERSION@",
+ com.ibm.icu.util;base=true;version="@IMPL_VERSION@"
Eclipse-LazyStart: true
Bundle-RequiredExecutionEnvironment: CDC-1.0/Foundation-1.0,
J2SE-1.3
diff --git a/src/com/ibm/icu/dev/eclipse/plugins/com.ibm.icu.base/src/com/ibm/icu/util/ULocale.java b/src/com/ibm/icu/dev/eclipse/plugins/com.ibm.icu.base/src/com/ibm/icu/util/ULocale.java
index 49de604..f255527 100644
--- a/src/com/ibm/icu/dev/eclipse/plugins/com.ibm.icu.base/src/com/ibm/icu/util/ULocale.java
+++ b/src/com/ibm/icu/dev/eclipse/plugins/com.ibm.icu.base/src/com/ibm/icu/util/ULocale.java
@@ -1,21 +1,27 @@
/*
- *******************************************************************************
- * Copyright (C) 2005-2008, International Business Machines Corporation and *
- * others. All Rights Reserved. *
- *******************************************************************************
- */
+******************************************************************************
+* Copyright (C) 2003-2008, International Business Machines Corporation and *
+* others. All Rights Reserved. *
+******************************************************************************
+*/
package com.ibm.icu.util;
import java.io.Serializable;
+import java.lang.ref.SoftReference;
+import java.text.ParseException;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
+import java.util.MissingResourceException;
import java.util.TreeMap;
+//import com.ibm.icu.impl.SimpleCache;
+//import com.ibm.icu.impl.ICUResourceBundle;
+//import com.ibm.icu.impl.LocaleUtility;
/**
* A class analogous to {@link java.util.Locale} that provides additional
@@ -81,7 +87,8 @@
* @stable ICU 2.8
*/
public final class ULocale implements Serializable {
- private static final long serialVersionUID = 1L;
+ // using serialver from jdk1.4.2_05
+ private static final long serialVersionUID = 3715177670352309217L;
/**
* Useful constant for language.
@@ -209,44 +216,26 @@
*/
public static final ULocale CANADA_FRENCH = new ULocale("fr_CA", Locale.CANADA_FRENCH);
- private static final HashMap CACHE = new HashMap(20);
- static {
- CACHE.put(Locale.ENGLISH, ENGLISH);
- CACHE.put(Locale.FRENCH, FRENCH);
- CACHE.put(Locale.GERMAN, GERMAN);
- CACHE.put(Locale.ITALIAN, ITALIAN);
- CACHE.put(Locale.JAPANESE, JAPANESE);
- CACHE.put(Locale.KOREAN, KOREAN);
- CACHE.put(Locale.CHINESE, CHINESE);
- CACHE.put(Locale.SIMPLIFIED_CHINESE, SIMPLIFIED_CHINESE);
- CACHE.put(Locale.TRADITIONAL_CHINESE, TRADITIONAL_CHINESE);
- CACHE.put(Locale.FRANCE, FRANCE);
- CACHE.put(Locale.GERMANY, GERMANY);
- CACHE.put(Locale.ITALY, ITALY);
- CACHE.put(Locale.JAPAN, JAPAN);
- CACHE.put(Locale.KOREA, KOREA);
- CACHE.put(Locale.CHINA, CHINA);
- CACHE.put(Locale.TAIWAN, TAIWAN);
- CACHE.put(Locale.UK, UK);
- CACHE.put(Locale.US, US);
- CACHE.put(Locale.CANADA, CANADA);
- CACHE.put(Locale.CANADA_FRENCH, CANADA_FRENCH);
- }
-
/**
* Handy constant.
*/
private static final String EMPTY_STRING = "";
// Used in both ULocale and IDParser, so moved up here.
- private static final char UNDERSCORE = '_';
+ private static final char UNDERSCORE = '_';
+
+ // default empty locale
+ private static final Locale EMPTY_LOCALE = new Locale("", "");
/**
* The root ULocale.
* @stable ICU 2.8
*/
- public static final ULocale ROOT = new ULocale(EMPTY_STRING, (Locale)null);
+ public static final ULocale ROOT = new ULocale("root", EMPTY_LOCALE);
+// private static final SimpleCache CACHE = new SimpleCache();
+ private static final HashMap CACHE = new HashMap(20);
+
/**
* Cache the locale.
*/
@@ -509,118 +498,118 @@
/* This list MUST be in sorted order, and MUST contain only two-letter codes! */
String[] tempCountries = {
"AD", "AE", "AF", "AG", "AI", "AL", "AM", "AN",
- "AO", "AQ", "AR", "AS", "AT", "AU", "AW", "AZ",
+ "AO", "AQ", "AR", "AS", "AT", "AU", "AW", "AX", "AZ",
"BA", "BB", "BD", "BE", "BF", "BG", "BH", "BI",
- "BJ", "BM", "BN", "BO", "BR", "BS", "BT", "BV",
+ "BJ", "BL", "BM", "BN", "BO", "BR", "BS", "BT", "BV",
"BW", "BY", "BZ", "CA", "CC", "CD", "CF", "CG",
"CH", "CI", "CK", "CL", "CM", "CN", "CO", "CR",
"CU", "CV", "CX", "CY", "CZ", "DE", "DJ", "DK",
"DM", "DO", "DZ", "EC", "EE", "EG", "EH", "ER",
"ES", "ET", "FI", "FJ", "FK", "FM", "FO", "FR",
- "GA", "GB", "GD", "GE", "GF", "GH", "GI", "GL",
+ "GA", "GB", "GD", "GE", "GF", "GG", "GH", "GI", "GL",
"GM", "GN", "GP", "GQ", "GR", "GS", "GT", "GU",
"GW", "GY", "HK", "HM", "HN", "HR", "HT", "HU",
- "ID", "IE", "IL", "IN", "IO", "IQ", "IR", "IS",
- "IT", "JM", "JO", "JP", "KE", "KG", "KH", "KI",
+ "ID", "IE", "IL", "IM", "IN", "IO", "IQ", "IR", "IS",
+ "IT", "JE", "JM", "JO", "JP", "KE", "KG", "KH", "KI",
"KM", "KN", "KP", "KR", "KW", "KY", "KZ", "LA",
"LB", "LC", "LI", "LK", "LR", "LS", "LT", "LU",
- "LV", "LY", "MA", "MC", "MD", "MG", "MH", "MK",
+ "LV", "LY", "MA", "MC", "MD", "ME", "MF", "MG", "MH", "MK",
"ML", "MM", "MN", "MO", "MP", "MQ", "MR", "MS",
"MT", "MU", "MV", "MW", "MX", "MY", "MZ", "NA",
"NC", "NE", "NF", "NG", "NI", "NL", "NO", "NP",
"NR", "NU", "NZ", "OM", "PA", "PE", "PF", "PG",
"PH", "PK", "PL", "PM", "PN", "PR", "PS", "PT",
- "PW", "PY", "QA", "RE", "RO", "RU", "RW", "SA",
+ "PW", "PY", "QA", "RE", "RO", "RS", "RU", "RW", "SA",
"SB", "SC", "SD", "SE", "SG", "SH", "SI", "SJ",
"SK", "SL", "SM", "SN", "SO", "SR", "ST", "SV",
"SY", "SZ", "TC", "TD", "TF", "TG", "TH", "TJ",
"TK", "TL", "TM", "TN", "TO", "TR", "TT", "TV",
"TW", "TZ", "UA", "UG", "UM", "US", "UY", "UZ",
"VA", "VC", "VE", "VG", "VI", "VN", "VU", "WF",
- "WS", "YE", "YT", "YU", "ZA", "ZM", "ZW",
- };
+ "WS", "YE", "YT", "ZA", "ZM", "ZW",
+ };
/* this table is used for 3 letter codes */
String[] tempObsoleteCountries = {
- "FX", "RO", "TP", "ZR", /* obsolete country codes */
+ "FX", "CS", "RO", "TP", "YU", "ZR", /* obsolete country codes */
};
String[] tempDeprecatedCountries = {
- "BU", "DY", "FX", "HV", "NH", "RH", "TP", "YU", "ZR" /* deprecated country list */
+ "BU", "CS", "DY", "FX", "HV", "NH", "RH", "TP", "YU", "ZR" /* deprecated country list */
};
String[] tempReplacementCountries = {
- /* "BU", "DY", "FX", "HV", "NH", "RH", "TP", "YU", "ZR" */
- "MM", "BJ", "FR", "BF", "VU", "ZW", "TL", "CS", "CD", /* replacement country codes */
+ /* "BU", "CS", "DY", "FX", "HV", "NH", "RH", "TP", "YU", "ZR" */
+ "MM", "RS", "BJ", "FR", "BF", "VU", "ZW", "TL", "RS", "CD", /* replacement country codes */
};
/* This list MUST contain a three-letter code for every two-letter code in
the above list, and they MUST be listed in the same order! */
String[] tempCountries3 = {
- /*"AD", "AE", "AF", "AG", "AI", "AL", "AM", "AN", */
- "AND", "ARE", "AFG", "ATG", "AIA", "ALB", "ARM", "ANT",
- /*"AO", "AQ", "AR", "AS", "AT", "AU", "AW", "AZ", */
- "AGO", "ATA", "ARG", "ASM", "AUT", "AUS", "ABW", "AZE",
- /*"BA", "BB", "BD", "BE", "BF", "BG", "BH", "BI", */
- "BIH", "BRB", "BGD", "BEL", "BFA", "BGR", "BHR", "BDI",
- /*"BJ", "BM", "BN", "BO", "BR", "BS", "BT", "BV", */
- "BEN", "BMU", "BRN", "BOL", "BRA", "BHS", "BTN", "BVT",
- /*"BW", "BY", "BZ", "CA", "CC", "CD", "CF", "CG", */
- "BWA", "BLR", "BLZ", "CAN", "CCK", "COD", "CAF", "COG",
- /*"CH", "CI", "CK", "CL", "CM", "CN", "CO", "CR", */
- "CHE", "CIV", "COK", "CHL", "CMR", "CHN", "COL", "CRI",
- /*"CU", "CV", "CX", "CY", "CZ", "DE", "DJ", "DK", */
- "CUB", "CPV", "CXR", "CYP", "CZE", "DEU", "DJI", "DNK",
- /*"DM", "DO", "DZ", "EC", "EE", "EG", "EH", "ER", */
- "DMA", "DOM", "DZA", "ECU", "EST", "EGY", "ESH", "ERI",
- /*"ES", "ET", "FI", "FJ", "FK", "FM", "FO", "FR", */
- "ESP", "ETH", "FIN", "FJI", "FLK", "FSM", "FRO", "FRA",
- /*"GA", "GB", "GD", "GE", "GF", "GH", "GI", "GL", */
- "GAB", "GBR", "GRD", "GEO", "GUF", "GHA", "GIB", "GRL",
- /*"GM", "GN", "GP", "GQ", "GR", "GS", "GT", "GU", */
- "GMB", "GIN", "GLP", "GNQ", "GRC", "SGS", "GTM", "GUM",
- /*"GW", "GY", "HK", "HM", "HN", "HR", "HT", "HU", */
- "GNB", "GUY", "HKG", "HMD", "HND", "HRV", "HTI", "HUN",
- /*"ID", "IE", "IL", "IN", "IO", "IQ", "IR", "IS", */
- "IDN", "IRL", "ISR", "IND", "IOT", "IRQ", "IRN", "ISL",
- /*"IT", "JM", "JO", "JP", "KE", "KG", "KH", "KI", */
- "ITA", "JAM", "JOR", "JPN", "KEN", "KGZ", "KHM", "KIR",
- /*"KM", "KN", "KP", "KR", "KW", "KY", "KZ", "LA", */
- "COM", "KNA", "PRK", "KOR", "KWT", "CYM", "KAZ", "LAO",
- /*"LB", "LC", "LI", "LK", "LR", "LS", "LT", "LU", */
- "LBN", "LCA", "LIE", "LKA", "LBR", "LSO", "LTU", "LUX",
- /*"LV", "LY", "MA", "MC", "MD", "MG", "MH", "MK", */
- "LVA", "LBY", "MAR", "MCO", "MDA", "MDG", "MHL", "MKD",
- /*"ML", "MM", "MN", "MO", "MP", "MQ", "MR", "MS", */
- "MLI", "MMR", "MNG", "MAC", "MNP", "MTQ", "MRT", "MSR",
- /*"MT", "MU", "MV", "MW", "MX", "MY", "MZ", "NA", */
- "MLT", "MUS", "MDV", "MWI", "MEX", "MYS", "MOZ", "NAM",
- /*"NC", "NE", "NF", "NG", "NI", "NL", "NO", "NP", */
- "NCL", "NER", "NFK", "NGA", "NIC", "NLD", "NOR", "NPL",
- /*"NR", "NU", "NZ", "OM", "PA", "PE", "PF", "PG", */
- "NRU", "NIU", "NZL", "OMN", "PAN", "PER", "PYF", "PNG",
- /*"PH", "PK", "PL", "PM", "PN", "PR", "PS", "PT", */
- "PHL", "PAK", "POL", "SPM", "PCN", "PRI", "PSE", "PRT",
- /*"PW", "PY", "QA", "RE", "RO", "RU", "RW", "SA", */
- "PLW", "PRY", "QAT", "REU", "ROU", "RUS", "RWA", "SAU",
- /*"SB", "SC", "SD", "SE", "SG", "SH", "SI", "SJ", */
- "SLB", "SYC", "SDN", "SWE", "SGP", "SHN", "SVN", "SJM",
- /*"SK", "SL", "SM", "SN", "SO", "SR", "ST", "SV", */
- "SVK", "SLE", "SMR", "SEN", "SOM", "SUR", "STP", "SLV",
- /*"SY", "SZ", "TC", "TD", "TF", "TG", "TH", "TJ", */
- "SYR", "SWZ", "TCA", "TCD", "ATF", "TGO", "THA", "TJK",
- /*"TK", "TL", "TM", "TN", "TO", "TR", "TT", "TV", */
- "TKL", "TLS", "TKM", "TUN", "TON", "TUR", "TTO", "TUV",
- /*"TW", "TZ", "UA", "UG", "UM", "US", "UY", "UZ", */
- "TWN", "TZA", "UKR", "UGA", "UMI", "USA", "URY", "UZB",
- /*"VA", "VC", "VE", "VG", "VI", "VN", "VU", "WF", */
- "VAT", "VCT", "VEN", "VGB", "VIR", "VNM", "VUT", "WLF",
- /*"WS", "YE", "YT", "YU", "ZA", "ZM", "ZW", */
- "WSM", "YEM", "MYT", "YUG", "ZAF", "ZMB", "ZWE",
+ /* "AD", "AE", "AF", "AG", "AI", "AL", "AM", "AN", */
+ "AND", "ARE", "AFG", "ATG", "AIA", "ALB", "ARM", "ANT",
+ /* "AO", "AQ", "AR", "AS", "AT", "AU", "AW", "AX", "AZ", */
+ "AGO", "ATA", "ARG", "ASM", "AUT", "AUS", "ABW", "ALA", "AZE",
+ /* "BA", "BB", "BD", "BE", "BF", "BG", "BH", "BI", */
+ "BIH", "BRB", "BGD", "BEL", "BFA", "BGR", "BHR", "BDI",
+ /* "BJ", "BL", "BM", "BN", "BO", "BR", "BS", "BT", "BV", */
+ "BEN", "BLM", "BMU", "BRN", "BOL", "BRA", "BHS", "BTN", "BVT",
+ /* "BW", "BY", "BZ", "CA", "CC", "CD", "CF", "CG", */
+ "BWA", "BLR", "BLZ", "CAN", "CCK", "COD", "CAF", "COG",
+ /* "CH", "CI", "CK", "CL", "CM", "CN", "CO", "CR", */
+ "CHE", "CIV", "COK", "CHL", "CMR", "CHN", "COL", "CRI",
+ /* "CU", "CV", "CX", "CY", "CZ", "DE", "DJ", "DK", */
+ "CUB", "CPV", "CXR", "CYP", "CZE", "DEU", "DJI", "DNK",
+ /* "DM", "DO", "DZ", "EC", "EE", "EG", "EH", "ER", */
+ "DMA", "DOM", "DZA", "ECU", "EST", "EGY", "ESH", "ERI",
+ /* "ES", "ET", "FI", "FJ", "FK", "FM", "FO", "FR", */
+ "ESP", "ETH", "FIN", "FJI", "FLK", "FSM", "FRO", "FRA",
+ /* "GA", "GB", "GD", "GE", "GF", "GG", "GH", "GI", "GL", */
+ "GAB", "GBR", "GRD", "GEO", "GUF", "GGY", "GHA", "GIB", "GRL",
+ /* "GM", "GN", "GP", "GQ", "GR", "GS", "GT", "GU", */
+ "GMB", "GIN", "GLP", "GNQ", "GRC", "SGS", "GTM", "GUM",
+ /* "GW", "GY", "HK", "HM", "HN", "HR", "HT", "HU", */
+ "GNB", "GUY", "HKG", "HMD", "HND", "HRV", "HTI", "HUN",
+ /* "ID", "IE", "IL", "IM", "IN", "IO", "IQ", "IR", "IS" */
+ "IDN", "IRL", "ISR", "IMN", "IND", "IOT", "IRQ", "IRN", "ISL",
+ /* "IT", "JE", "JM", "JO", "JP", "KE", "KG", "KH", "KI", */
+ "ITA", "JEY", "JAM", "JOR", "JPN", "KEN", "KGZ", "KHM", "KIR",
+ /* "KM", "KN", "KP", "KR", "KW", "KY", "KZ", "LA", */
+ "COM", "KNA", "PRK", "KOR", "KWT", "CYM", "KAZ", "LAO",
+ /* "LB", "LC", "LI", "LK", "LR", "LS", "LT", "LU", */
+ "LBN", "LCA", "LIE", "LKA", "LBR", "LSO", "LTU", "LUX",
+ /* "LV", "LY", "MA", "MC", "MD", "ME", "MF", "MG", "MH", "MK", */
+ "LVA", "LBY", "MAR", "MCO", "MDA", "MNE", "MAF", "MDG", "MHL", "MKD",
+ /* "ML", "MM", "MN", "MO", "MP", "MQ", "MR", "MS", */
+ "MLI", "MMR", "MNG", "MAC", "MNP", "MTQ", "MRT", "MSR",
+ /* "MT", "MU", "MV", "MW", "MX", "MY", "MZ", "NA", */
+ "MLT", "MUS", "MDV", "MWI", "MEX", "MYS", "MOZ", "NAM",
+ /* "NC", "NE", "NF", "NG", "NI", "NL", "NO", "NP", */
+ "NCL", "NER", "NFK", "NGA", "NIC", "NLD", "NOR", "NPL",
+ /* "NR", "NU", "NZ", "OM", "PA", "PE", "PF", "PG", */
+ "NRU", "NIU", "NZL", "OMN", "PAN", "PER", "PYF", "PNG",
+ /* "PH", "PK", "PL", "PM", "PN", "PR", "PS", "PT", */
+ "PHL", "PAK", "POL", "SPM", "PCN", "PRI", "PSE", "PRT",
+ /* "PW", "PY", "QA", "RE", "RO", "RS", "RU", "RW", "SA", */
+ "PLW", "PRY", "QAT", "REU", "ROU", "SRB", "RUS", "RWA", "SAU",
+ /* "SB", "SC", "SD", "SE", "SG", "SH", "SI", "SJ", */
+ "SLB", "SYC", "SDN", "SWE", "SGP", "SHN", "SVN", "SJM",
+ /* "SK", "SL", "SM", "SN", "SO", "SR", "ST", "SV", */
+ "SVK", "SLE", "SMR", "SEN", "SOM", "SUR", "STP", "SLV",
+ /* "SY", "SZ", "TC", "TD", "TF", "TG", "TH", "TJ", */
+ "SYR", "SWZ", "TCA", "TCD", "ATF", "TGO", "THA", "TJK",
+ /* "TK", "TL", "TM", "TN", "TO", "TR", "TT", "TV", */
+ "TKL", "TLS", "TKM", "TUN", "TON", "TUR", "TTO", "TUV",
+ /* "TW", "TZ", "UA", "UG", "UM", "US", "UY", "UZ", */
+ "TWN", "TZA", "UKR", "UGA", "UMI", "USA", "URY", "UZB",
+ /* "VA", "VC", "VE", "VG", "VI", "VN", "VU", "WF", */
+ "VAT", "VCT", "VEN", "VGB", "VIR", "VNM", "VUT", "WLF",
+ /* "WS", "YE", "YT", "ZA", "ZM", "ZW" */
+ "WSM", "YEM", "MYT", "ZAF", "ZMB", "ZWE",
};
String[] tempObsoleteCountries3 = {
- /*"FX", "RO", "TP", "ZR", */
- "FXX", "ROM", "TMP", "ZAR",
+ /*"FX", "CS", "RO", "TP", "YU", "ZR", */
+ "FXX", "SCG", "ROM", "TMP", "YUG", "ZAR",
};
synchronized (ULocale.class) {
@@ -636,16 +625,17 @@
}
}
- private static String[][] _variantsToKeywords;
+ private static String[][] CANONICALIZE_MAP;
+ private static String[][] variantsToKeywords;
- private static void initVariantsTable() {
- if (_variantsToKeywords == null) {
+ private static void initCANONICALIZE_MAP() {
+ if (CANONICALIZE_MAP == null) {
/**
* This table lists pairs of locale ids for canonicalization. The
- * The first item is the normalized id, the second item is the
- * canonicalized id.
+ * The 1st item is the normalized id. The 2nd item is the
+ * canonicalized id. The 3rd is the keyword. The 4th is the keyword value.
*/
- String[][] tempVariantsToKeywords = {
+ String[][] tempCANONICALIZE_MAP = {
// { EMPTY_STRING, "en_US_POSIX", null, null }, /* .NET name */
{ "C", "en_US_POSIX", null, null }, /* POSIX name */
{ "art_LOJBAN", "jbo", null, null }, /* registered name */
@@ -655,7 +645,7 @@
{ "cel_GAULISH", "cel__GAULISH", null, null }, /* registered name */
{ "de_1901", "de__1901", null, null }, /* registered name */
{ "de_1906", "de__1906", null, null }, /* registered name */
- { "de__PHONEBOOK", "de", "collation", "phonebook" },
+ { "de__PHONEBOOK", "de", "collation", "phonebook" }, /* Old ICU name */
{ "de_AT_PREEURO", "de_AT", "currency", "ATS" },
{ "de_DE_PREEURO", "de_DE", "currency", "DEM" },
{ "de_LU_PREEURO", "de_LU", "currency", "EUR" },
@@ -664,7 +654,7 @@
{ "en_SCOUSE", "en__SCOUSE", null, null }, /* registered name */
{ "en_BE_PREEURO", "en_BE", "currency", "BEF" },
{ "en_IE_PREEURO", "en_IE", "currency", "IEP" },
- { "es__TRADITIONAL", "es", "collation", "traditional" },
+ { "es__TRADITIONAL", "es", "collation", "traditional" }, /* Old ICU name */
{ "es_ES_PREEURO", "es_ES", "currency", "ESP" },
{ "eu_ES_PREEURO", "eu_ES", "currency", "ESP" },
{ "fi_FI_PREEURO", "fi_FI", "currency", "FIM" },
@@ -673,7 +663,7 @@
{ "fr_LU_PREEURO", "fr_LU", "currency", "LUF" },
{ "ga_IE_PREEURO", "ga_IE", "currency", "IEP" },
{ "gl_ES_PREEURO", "gl_ES", "currency", "ESP" },
- { "hi__DIRECT", "hi", "collation", "direct" },
+ { "hi__DIRECT", "hi", "collation", "direct" }, /* Old ICU name */
{ "it_IT_PREEURO", "it_IT", "currency", "ITL" },
{ "ja_JP_TRADITIONAL", "ja_JP", "calendar", "japanese" },
// { "nb_NO_NY", "nn_NO", null, null },
@@ -681,9 +671,11 @@
{ "nl_NL_PREEURO", "nl_NL", "currency", "NLG" },
{ "pt_PT_PREEURO", "pt_PT", "currency", "PTE" },
{ "sl_ROZAJ", "sl__ROZAJ", null, null }, /* registered name */
- { "sr_SP_CYRL", "sr_Cyrl_CS", null, null }, /* .NET name */
- { "sr_SP_LATN", "sr_Latn_CS", null, null }, /* .NET name */
- { "sr_YU_CYRILLIC", "sr_Cyrl_CS", null, null }, /* Linux name */
+ { "sr_SP_CYRL", "sr_Cyrl_RS", null, null }, /* .NET name */
+ { "sr_SP_LATN", "sr_Latn_RS", null, null }, /* .NET name */
+ { "sr_YU_CYRILLIC", "sr_Cyrl_RS", null, null }, /* Linux name */
+ { "th_TH_TRADITIONAL", "th_TH", "calendar", "buddhist" }, /* Old ICU name */
+ { "uz_UZ_CYRILLIC", "uz_Cyrl_UZ", null, null }, /* Linux name */
{ "uz_UZ_CYRL", "uz_Cyrl_UZ", null, null }, /* .NET name */
{ "uz_UZ_LATN", "uz_Latn_UZ", null, null }, /* .NET name */
{ "zh_CHS", "zh_Hans", null, null }, /* .NET name */
@@ -695,20 +687,49 @@
{ "zh_MIN_NAN", "zh__MINNAN", null, null }, /* registered name */
{ "zh_WUU", "zh__WUU", null, null }, /* registered name */
{ "zh_XIANG", "zh__XIANG", null, null }, /* registered name */
- { "zh_YUE", "zh__YUE", null, null }, /* registered name */
- { "th_TH_TRADITIONAL", "th_TH", "calendar", "buddhist" },
- { "zh_TW_STROKE", "zh_TW", "collation", "stroke" },
- { "zh__PINYIN", "zh", "collation", "pinyin" }
+ { "zh_YUE", "zh__YUE", null, null } /* registered name */
};
synchronized (ULocale.class) {
- if (_variantsToKeywords == null) {
- _variantsToKeywords = tempVariantsToKeywords;
+ if (CANONICALIZE_MAP == null) {
+ CANONICALIZE_MAP = tempCANONICALIZE_MAP;
+ }
+ }
+ }
+ if (variantsToKeywords == null) {
+ /**
+ * This table lists pairs of locale ids for canonicalization. The
+ * The first item is the normalized variant id.
+ */
+ String[][] tempVariantsToKeywords = {
+ { "EURO", "currency", "EUR" },
+ { "PINYIN", "collation", "pinyin" }, /* Solaris variant */
+ { "STROKE", "collation", "stroke" } /* Solaris variant */
+ };
+
+ synchronized (ULocale.class) {
+ if (variantsToKeywords == null) {
+ variantsToKeywords = tempVariantsToKeywords;
}
}
}
}
+ /*
+ * This table is used for mapping between ICU and special Java
+ * locales. When an ICU locale matches <minumum base> with
+ * <keyword>/<value>, the ICU locale is mapped to <Java> locale.
+ * For example, both ja_JP@calendar=japanese and ja@calendar=japanese
+ * are mapped to Java locale "ja_JP_JP". ICU locale "nn" is mapped
+ * to Java locale "no_NO_NY".
+ */
+ private static final String[][] _javaLocaleMap = {
+ // { <Java>, <ICU base>, <keyword>, <value>, <minimum base>
+ { "ja_JP_JP", "ja_JP", "calendar", "japanese", "ja"},
+ { "no_NO_NY", "nn_NO", null, null, "nn"},
+ // { "th_TH_TH", "th_TH", ??, ??, "th"} //TODO
+ };
+
/**
* Private constructor used by static initializers.
*/
@@ -724,7 +745,7 @@
* @internal
*/
private ULocale(Locale loc) {
- this.localeID = getName(loc.toString());
+ this.localeID = getName(forLocale(loc).toString());
this.locale = loc;
}
@@ -739,10 +760,26 @@
return null;
}
ULocale result = (ULocale)CACHE.get(loc);
- if (result == null && defaultULocale != null && loc == defaultULocale.locale) {
+ if (result == null) {
+ if (defaultULocale != null && loc == defaultULocale.locale) {
result = defaultULocale;
} else {
- result = new ULocale(loc.toString(), loc);
+ String locStr = loc.toString();
+ if (locStr.length() == 0) {
+ result = ROOT;
+ } else {
+ for (int i = 0; i < _javaLocaleMap.length; i++) {
+ if (_javaLocaleMap[i][0].equals(locStr)) {
+ IDParser p = new IDParser(_javaLocaleMap[i][1]);
+ p.setKeywordValue(_javaLocaleMap[i][2], _javaLocaleMap[i][3]);
+ locStr = p.getName();
+ break;
+ }
+ }
+ result = new ULocale(locStr, loc);
+ }
+ }
+ CACHE.put(loc, result);
}
return result;
}
@@ -754,13 +791,17 @@
* script, if present, is four characters long-- this distinguishes it
* from a country code, which is two characters long. Other fields
* are distinguished by position as indicated by the underscores. The
- * start of the keyword list is indicated by '@', and consists of one
- * or more keyword/value pairs separated by commas.
+ * start of the keyword list is indicated by '@', and consists of two
+ * or more keyword/value pairs separated by semicolons(';').
* <p>
- * This constructor does not canonicalize the localeID.
+ * This constructor does not canonicalize the localeID. So, for
+ * example, "zh__pinyin" remains unchanged instead of converting
+ * to "zh@collation=pinyin". By default ICU only recognizes the
+ * latter as specifying pinyin collation. Use {@link #createCanonical}
+ * or {@link #canonicalize} if you need to canonicalize the localeID.
*
* @param localeID string representation of the locale, e.g:
- * "en_US", "sy_Cyrl_YU", "zh__pinyin", "es_ES@currency=EUR,collation=traditional"
+ * "en_US", "sy_Cyrl_YU", "zh__pinyin", "es_ES@currency=EUR;collation=traditional"
* @stable ICU 2.8
*/
public ULocale(String localeID) {
@@ -843,20 +884,56 @@
*/
public Locale toLocale() {
if (locale == null) {
- locale = toLocale(localeID);
+ IDParser p = new IDParser(localeID);
+ String base = p.getBaseName();
+ for (int i = 0; i < _javaLocaleMap.length; i++) {
+ if (base.equals(_javaLocaleMap[i][1]) || base.equals(_javaLocaleMap[i][4])) {
+ if (_javaLocaleMap[i][2] != null) {
+ String val = p.getKeywordValue(_javaLocaleMap[i][2]);
+ if (val != null && val.equals(_javaLocaleMap[i][3])) {
+ p = new IDParser(_javaLocaleMap[i][0]);
+ break;
+ }
+ } else {
+ p = new IDParser(_javaLocaleMap[i][0]);
+ break;
+ }
+ }
+ }
+ String[] names = p.getLanguageScriptCountryVariant();
+ locale = new Locale(names[0], names[2], names[3]);
}
return locale;
}
-
+
private static Locale toLocale(String localeID) {
- String[] names = new IDParser(localeID).getLanguageScriptCountryVariant();
+ IDParser p = new IDParser(localeID);
+ String base = p.getBaseName();
+ for (int i = 0; i < _javaLocaleMap.length; i++) {
+ if (base.equals(_javaLocaleMap[i][1]) || base.equals(_javaLocaleMap[i][4])) {
+ if (_javaLocaleMap[i][2] != null) {
+ String val = p.getKeywordValue(_javaLocaleMap[i][2]);
+ if (val != null && val.equals(_javaLocaleMap[i][3])) {
+ p = new IDParser(_javaLocaleMap[i][0]);
+ break;
+ }
+ } else {
+ p = new IDParser(_javaLocaleMap[i][0]);
+ break;
+ }
+ }
+ }
+ String[] names = p.getLanguageScriptCountryVariant();
return new Locale(names[0], names[2], names[3]);
}
-
+
+
+ private static SoftReference nameCacheRef = new SoftReference(Collections.synchronizedMap(new HashMap()));
/**
* Keep our own default ULocale.
*/
- private static ULocale defaultULocale;
+ private static Locale defaultLocale = Locale.getDefault();
+ private static ULocale defaultULocale = new ULocale(defaultLocale);
/**
* Returns the current default ULocale.
@@ -864,8 +941,9 @@
*/
public static ULocale getDefault() {
synchronized (ULocale.class) {
- Locale defaultLocale = Locale.getDefault();
- if (defaultULocale == null || defaultULocale.toLocale() != defaultLocale) {
+ Locale currentDefault = Locale.getDefault();
+ if (defaultLocale != currentDefault) {
+ defaultLocale = currentDefault;
defaultULocale = new ULocale(defaultLocale);
}
return defaultULocale;
@@ -882,7 +960,7 @@
* if a security manager exists and its
* <code>checkPermission</code> method doesn't allow the operation.
* @throws NullPointerException if <code>newLocale</code> is null
- * @see SecurityManager#checkPermission
+ * @see SecurityManager#checkPermission(java.security.Permission)
* @see java.util.PropertyPermission
* @stable ICU 3.0
*/
@@ -929,23 +1007,25 @@
}
return false;
}
-
+
+ private static ULocale[] ulocales;
+
/**
* Returns a list of all installed locales.
* @stable ICU 3.0
*/
public static ULocale[] getAvailableLocales() {
+// return ICUResourceBundle.getAvailableULocales();
if (ulocales == null) {
- Locale[] locales = Locale.getAvailableLocales();
- ULocale[] ul = new ULocale[locales.length];
- for (int i = 0; i < locales.length; ++i) {
- ul[i] = ULocale.forLocale(locales[i]);
- }
- ulocales = ul;
+ Locale[] locales = Locale.getAvailableLocales();
+ ULocale[] ul = new ULocale[locales.length];
+ for (int i = 0; i < locales.length; ++i) {
+ ul[i] = ULocale.forLocale(locales[i]);
+ }
+ ulocales = ul;
}
return (ULocale[])ulocales.clone();
}
- private static ULocale[] ulocales;
/**
* Returns a list of all 2-letter country codes defined in ISO 3166.
@@ -973,7 +1053,8 @@
/**
* Returns the language code for this locale, which will either be the empty string
* or a lowercase ISO 639 code.
- * @see #getDisplayLanguage
+ * @see #getDisplayLanguage()
+ * @see #getDisplayLanguage(ULocale)
* @stable ICU 3.0
*/
public String getLanguage() {
@@ -984,7 +1065,8 @@
* Returns the language code for the locale ID,
* which will either be the empty string
* or a lowercase ISO 639 code.
- * @see #getDisplayLanguage
+ * @see #getDisplayLanguage()
+ * @see #getDisplayLanguage(ULocale)
* @stable ICU 3.0
*/
public static String getLanguage(String localeID) {
@@ -993,7 +1075,8 @@
/**
* Returns the script code for this locale, which might be the empty string.
- * @see #getDisplayScript
+ * @see #getDisplayScript()
+ * @see #getDisplayScript(ULocale)
* @stable ICU 3.0
*/
public String getScript() {
@@ -1002,7 +1085,8 @@
/**
* Returns the script code for the specified locale, which might be the empty string.
- * @see #getDisplayScript
+ * @see #getDisplayScript()
+ * @see #getDisplayScript(ULocale)
* @stable ICU 3.0
*/
public static String getScript(String localeID) {
@@ -1012,7 +1096,8 @@
/**
* Returns the country/region code for this locale, which will either be the empty string
* or an uppercase ISO 3166 2-letter code.
- * @see #getDisplayCountry
+ * @see #getDisplayCountry()
+ * @see #getDisplayCountry(ULocale)
* @stable ICU 3.0
*/
public String getCountry() {
@@ -1023,7 +1108,8 @@
* Returns the country/region code for this locale, which will either be the empty string
* or an uppercase ISO 3166 2-letter code.
* @param localeID
- * @see #getDisplayCountry
+ * @see #getDisplayCountry()
+ * @see #getDisplayCountry(ULocale)
* @stable ICU 3.0
*/
public static String getCountry(String localeID) {
@@ -1032,7 +1118,8 @@
/**
* Returns the variant code for this locale, which might be the empty string.
- * @see #getDisplayVariant
+ * @see #getDisplayVariant()
+ * @see #getDisplayVariant(ULocale)
* @stable ICU 3.0
*/
public String getVariant() {
@@ -1041,7 +1128,8 @@
/**
* Returns the variant code for the specified locale, which might be the empty string.
- * @see #getDisplayVariant
+ * @see #getDisplayVariant()
+ * @see #getDisplayVariant(ULocale)
* @stable ICU 3.0
*/
public static String getVariant(String localeID) {
@@ -1098,6 +1186,9 @@
* @stable ICU 3.0
*/
public static String getBaseName(String localeID){
+ if (localeID.indexOf('@') == -1) {
+ return localeID;
+ }
return new IDParser(localeID).getBaseName();
}
@@ -1119,7 +1210,17 @@
* @stable ICU 3.0
*/
public static String getName(String localeID){
- return new IDParser(localeID).getName();
+ Map cache = (Map)nameCacheRef.get();
+ if (cache == null) {
+ cache = Collections.synchronizedMap(new HashMap());
+ nameCacheRef = new SoftReference(cache);
+ }
+ String name = (String)cache.get(localeID);
+ if (name == null) {
+ name = new IDParser(localeID).getName();
+ cache.put(localeID, name);
+ }
+ return name;
}
/**
@@ -1304,6 +1405,13 @@
return index >= id.length || isTerminator(id[index]);
}
+ /*
+ * Returns true if the character is an id separator (underscore or hyphen).
+ */
+/* private boolean isIDSeparator(char c) {
+ return c == UNDERSCORE || c == HYPHEN;
+ }*/
+
/**
* Returns true if the character is a terminator (keyword separator, dot, or DONE).
* Dot is a terminator because of the POSIX form, where dot precedes the codepage.
@@ -1462,6 +1570,7 @@
*/
private int parseCountry() {
if (!atTerminator()) {
+ int oldIndex = index;
++index;
int oldBlen = blen;
@@ -1476,7 +1585,20 @@
}
--index; // unget
- if (blen - oldBlen == 3) {
+ int charsAppended = blen - oldBlen;
+
+ if (charsAppended == 0) {
+ // Do nothing.
+ }
+ else if (charsAppended < 2 || charsAppended > 3) {
+ // It's not a country, so return index and blen to
+ // their previous values.
+ index = oldIndex;
+ --oldBlen;
+ blen = oldBlen;
+ hadCountry = false;
+ }
+ else if (charsAppended == 3) {
initCountryTables();
/* convert 3 character code to 2 character code if possible *CWB*/
@@ -1495,7 +1617,7 @@
}
return blen;
- }
+ }
/**
* Advance index past country.
@@ -1505,7 +1627,17 @@
private void skipCountry() {
if (!atTerminator()) {
++index;
+ /*
+ * Save the index point after the separator, since the format
+ * requires two separators if the country is not present.
+ */
+ int oldIndex = index;
+
skipUntilTerminatorOrIDSeparator();
+ int charsSkipped = index - oldIndex;
+ if (charsSkipped < 2 || charsSkipped > 3) {
+ index = oldIndex;
+ }
}
}
@@ -1919,14 +2051,31 @@
// we have an ID in the form xx_Yyyy_ZZ_KKKKK
- initVariantsTable();
+ initCANONICALIZE_MAP();
- /* See if this is an already known locale */
- for (int i = 0; i < _variantsToKeywords.length; i++) {
- if (_variantsToKeywords[i][0].equals(baseName)) {
+ /* convert the variants to appropriate ID */
+ for (int i = 0; i < variantsToKeywords.length; i++) {
+ String[] vals = variantsToKeywords[i];
+ int idx = baseName.lastIndexOf("_" + vals[0]);
+ if (idx > -1) {
foundVariant = true;
- String[] vals = _variantsToKeywords[i];
+ baseName = baseName.substring(0, idx);
+ if (baseName.endsWith("_")) {
+ baseName = baseName.substring(0, --idx);
+ }
+ parser.setBaseName(baseName);
+ parser.defaultKeywordValue(vals[1], vals[2]);
+ break;
+ }
+ }
+
+ /* See if this is an already known locale */
+ for (int i = 0; i < CANONICALIZE_MAP.length; i++) {
+ if (CANONICALIZE_MAP[i][0].equals(baseName)) {
+ foundVariant = true;
+
+ String[] vals = CANONICALIZE_MAP[i];
parser.setBaseName(vals[1]);
if (vals[2] != null) {
parser.defaultKeywordValue(vals[2], vals[3]);
@@ -1935,15 +2084,6 @@
}
}
- /* convert the Euro variant to appropriate ID */
- if (!foundVariant) {
- int idx = baseName.indexOf("_EURO");
- if (idx > -1) {
- parser.setBaseName(baseName.substring(0, idx));
- parser.defaultKeywordValue("currency", "EUR");
- }
- }
-
/* total mondo hack for Norwegian, fortunately the main NY case is handled earlier */
if (!foundVariant) {
if (parser.getLanguage().equals("nb") && parser.getVariant().equals("NY")) {
@@ -1987,6 +2127,22 @@
return parser.getName();
}
+ /*
+ * Given a locale id, a keyword, and a value, return a new locale id with an updated
+ * keyword and value, if the keyword does not already have a value. The keyword and
+ * value must not be null or empty.
+ * @param localeID the locale id to modify
+ * @param keyword the keyword to add, if not already present
+ * @param value the value to add, if not already present
+ * @return the updated locale id
+ * @internal
+ */
+/* private static String defaultKeywordValue(String localeID, String keyword, String value) {
+ IDParser parser = new IDParser(localeID);
+ parser.defaultKeywordValue(keyword, value);
+ return parser.getName();
+ }*/
+
/**
* Returns a three-letter abbreviation for this locale's language. If the locale
* doesn't specify a language, returns the empty string. Otherwise, returns
@@ -2064,13 +2220,90 @@
// display names
+// /**
+// * Utility to fetch locale display data from resource bundle tables.
+// */
+// private static String getTableString(String tableName, String subtableName, String item, String displayLocaleID) {
+// if (item.length() > 0) {
+// try {
+// ICUResourceBundle bundle = (ICUResourceBundle)UResourceBundle.
+// getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, displayLocaleID);
+// return getTableString(tableName, subtableName, item, bundle);
+// } catch (Exception e) {
+//// System.out.println("gtsu: " + e.getMessage());
+// }
+// }
+// return item;
+// }
+//
+// /**
+// * Utility to fetch locale display data from resource bundle tables.
+// */
+// private static String getTableString(String tableName, String subtableName, String item, ICUResourceBundle bundle) {
+//// System.out.println("gts table: " + tableName +
+//// " subtable: " + subtableName +
+//// " item: " + item +
+//// " bundle: " + bundle.getULocale());
+// try {
+// for (;;) {
+// // special case currency
+// if ("currency".equals(subtableName)) {
+// ICUResourceBundle table = bundle.getWithFallback("Currencies");
+// table = table.getWithFallback(item);
+// return table.getString(1);
+// } else {
+// ICUResourceBundle table = bundle.getWithFallback(tableName);
+// try {
+// if (subtableName != null) {
+// table = table.getWithFallback(subtableName);
+// }
+// return table.getStringWithFallback(item);
+// }
+// catch (MissingResourceException e) {
+//
+// if(subtableName==null){
+// try{
+// // may be a deprecated code
+// String currentName = null;
+// if(tableName.equals("Countries")){
+// currentName = getCurrentCountryID(item);
+// }else if(tableName.equals("Languages")){
+// currentName = getCurrentLanguageID(item);
+// }
+// return table.getStringWithFallback(currentName);
+// }catch (MissingResourceException ex){/* fall through*/}
+// }
+//
+// // still can't figure out ?.. try the fallback mechanism
+// String fallbackLocale = table.getWithFallback("Fallback").getString();
+// if (fallbackLocale.length() == 0) {
+// fallbackLocale = "root";
+// }
+//// System.out.println("bundle: " + bundle.getULocale() + " fallback: " + fallbackLocale);
+// if(fallbackLocale.equals(table.getULocale().localeID)){
+// return item;
+// }
+// bundle = (ICUResourceBundle)UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME,
+// fallbackLocale);
+//// System.out.println("fallback from " + table.getULocale() + " to " + fallbackLocale +
+//// ", got bundle " + bundle.getULocale());
+// }
+// }
+// }
+// }
+// catch (Exception e) {
+//// System.out.println("gtsi: " + e.getMessage());
+// }
+// return item;
+// }
+
/**
* Returns this locale's language localized for display in the default locale.
* @return the localized language name.
* @stable ICU 3.0
*/
public String getDisplayLanguage() {
- return toLocale().getDisplayLanguage();
+ return getDisplayLanguageInternal(localeID, getDefault().localeID);
}
/**
@@ -2080,7 +2313,7 @@
* @stable ICU 3.0
*/
public String getDisplayLanguage(ULocale displayLocale) {
- return toLocale().getDisplayLanguage(displayLocale.toLocale());
+ return getDisplayLanguageInternal(localeID, displayLocale.localeID);
}
/**
@@ -2092,7 +2325,7 @@
* @stable ICU 3.0
*/
public static String getDisplayLanguage(String localeID, String displayLocaleID) {
- return toLocale(localeID).getDisplayLanguage(toLocale(displayLocaleID));
+ return getDisplayLanguageInternal(localeID, getName(displayLocaleID));
}
/**
@@ -2104,8 +2337,8 @@
* @stable ICU 3.0
*/
public static String getDisplayLanguage(String localeID, ULocale displayLocale) {
- return toLocale(localeID).getDisplayLanguage(displayLocale.toLocale());
- }
+ return getDisplayLanguageInternal(localeID, displayLocale.localeID);
+ }
static String getCurrentCountryID(String oldID){
initCountryTables();
@@ -2115,7 +2348,6 @@
}
return oldID;
}
-
static String getCurrentLanguageID(String oldID){
initLanguageTables();
int offset = findIndex(_obsoleteLanguages, oldID);
@@ -2124,15 +2356,21 @@
}
return oldID;
}
-
+
+ // displayLocaleID is canonical, localeID need not be since parsing will fix this.
+ private static String getDisplayLanguageInternal(String localeID, String displayLocaleID) {
+// return getTableString("Languages", null, new IDParser(localeID).getLanguage(), displayLocaleID);
+ return toLocale(localeID).getDisplayLanguage(toLocale(displayLocaleID));
+ }
+
/**
* Returns this locale's script localized for display in the default locale.
* @return the localized script name.
* @stable ICU 3.0
*/
public String getDisplayScript() {
- return new IDParser(localeID).getScript();
+ return getDisplayScriptInternal(localeID, getDefault().localeID);
}
/**
@@ -2142,7 +2380,7 @@
* @stable ICU 3.0
*/
public String getDisplayScript(ULocale displayLocale) {
- return new IDParser(localeID).getScript();
+ return getDisplayScriptInternal(localeID, displayLocale.localeID);
}
/**
@@ -2154,7 +2392,7 @@
* @stable ICU 3.0
*/
public static String getDisplayScript(String localeID, String displayLocaleID) {
- return new IDParser(localeID).getScript();
+ return getDisplayScriptInternal(localeID, getName(displayLocaleID));
}
/**
@@ -2165,6 +2403,12 @@
* @stable ICU 3.0
*/
public static String getDisplayScript(String localeID, ULocale displayLocale) {
+ return getDisplayScriptInternal(localeID, displayLocale.localeID);
+ }
+
+ // displayLocaleID is canonical, localeID need not be since parsing will fix this.
+ private static String getDisplayScriptInternal(String localeID, String displayLocaleID) {
+// return getTableString("Scripts", null, new IDParser(localeID).getScript(), displayLocaleID);
return new IDParser(localeID).getScript();
}
@@ -2174,7 +2418,7 @@
* @stable ICU 3.0
*/
public String getDisplayCountry() {
- return toLocale(localeID).getDisplayCountry();
+ return getDisplayCountryInternal(localeID, getDefault().localeID);
}
/**
@@ -2184,7 +2428,7 @@
* @stable ICU 3.0
*/
public String getDisplayCountry(ULocale displayLocale){
- return toLocale(localeID).getDisplayCountry(displayLocale.toLocale());
+ return getDisplayCountryInternal(localeID, displayLocale.localeID);
}
/**
@@ -2196,7 +2440,7 @@
* @stable ICU 3.0
*/
public static String getDisplayCountry(String localeID, String displayLocaleID) {
- return toLocale(localeID).getDisplayCountry(toLocale(displayLocaleID));
+ return getDisplayCountryInternal(localeID, getName(displayLocaleID));
}
/**
@@ -2208,16 +2452,22 @@
* @stable ICU 3.0
*/
public static String getDisplayCountry(String localeID, ULocale displayLocale) {
- return toLocale(localeID).getDisplayCountry(displayLocale.toLocale());
+ return getDisplayCountryInternal(localeID, displayLocale.localeID);
}
+ // displayLocaleID is canonical, localeID need not be since parsing will fix this.
+ private static String getDisplayCountryInternal(String localeID, String displayLocaleID) {
+// return getTableString("Countries", null, new IDParser(localeID).getCountry(), displayLocaleID);
+ return toLocale(localeID).getDisplayCountry(toLocale(displayLocaleID));
+ }
+
/**
* Returns this locale's variant localized for display in the default locale.
* @return the localized variant name.
* @stable ICU 3.0
*/
public String getDisplayVariant() {
- return toLocale().getDisplayVariant();
+ return getDisplayVariantInternal(localeID, getDefault().localeID);
}
/**
@@ -2227,7 +2477,7 @@
* @stable ICU 3.0
*/
public String getDisplayVariant(ULocale displayLocale) {
- return toLocale().getDisplayVariant(displayLocale.toLocale());
+ return getDisplayVariantInternal(localeID, displayLocale.localeID);
}
/**
@@ -2239,7 +2489,7 @@
* @stable ICU 3.0
*/
public static String getDisplayVariant(String localeID, String displayLocaleID){
- return toLocale(localeID).getDisplayVariant(toLocale(displayLocaleID));
+ return getDisplayVariantInternal(localeID, getName(displayLocaleID));
}
/**
@@ -2251,18 +2501,24 @@
* @stable ICU 3.0
*/
public static String getDisplayVariant(String localeID, ULocale displayLocale) {
- return toLocale(localeID).getDisplayVariant(displayLocale.toLocale());
+ return getDisplayVariantInternal(localeID, displayLocale.localeID);
+ }
+
+ // displayLocaleID is canonical, localeID need not be since parsing will fix this.
+ private static String getDisplayVariantInternal(String localeID, String displayLocaleID) {
+// return getTableString("Variants", null, new IDParser(localeID).getVariant(), displayLocaleID);
+ return toLocale(localeID).getDisplayVariant(toLocale(displayLocaleID));
}
/**
* Returns a keyword localized for display in the default locale.
* @param keyword the keyword to be displayed.
* @return the localized keyword name.
- * @see #getKeywords
+ * @see #getKeywords()
* @stable ICU 3.0
*/
public static String getDisplayKeyword(String keyword) {
- return keyword.trim().toLowerCase();
+ return getDisplayKeywordInternal(keyword, getDefault().localeID);
}
/**
@@ -2270,11 +2526,11 @@
* @param keyword the keyword to be displayed.
* @param displayLocaleID the id of the locale in which to display the keyword.
* @return the localized keyword name.
- * @see #getKeywords
+ * @see #getKeywords(String)
* @stable ICU 3.0
*/
public static String getDisplayKeyword(String keyword, String displayLocaleID) {
- return keyword.trim().toLowerCase();
+ return getDisplayKeywordInternal(keyword, getName(displayLocaleID));
}
/**
@@ -2282,11 +2538,17 @@
* @param keyword the keyword to be displayed.
* @param displayLocale the locale in which to display the keyword.
* @return the localized keyword name.
- * @see #getKeywords
+ * @see #getKeywords(String)
* @stable ICU 3.0
*/
public static String getDisplayKeyword(String keyword, ULocale displayLocale) {
- return keyword.trim().toLowerCase();
+ return getDisplayKeywordInternal(keyword, displayLocale.localeID);
+ }
+
+ // displayLocaleID is canonical, localeID need not be since parsing will fix this.
+ private static String getDisplayKeywordInternal(String keyword, String displayLocaleID) {
+// return getTableString("Keys", null, keyword.trim().toLowerCase(), displayLocaleID);
+ return keyword.trim().toLowerCase();
}
/**
@@ -2296,7 +2558,7 @@
* @stable ICU 3.0
*/
public String getDisplayKeywordValue(String keyword) {
- return new IDParser(localeID).getKeywordValue(keyword.trim().toLowerCase());
+ return getDisplayKeywordValueInternal(localeID, keyword, getDefault().localeID);
}
/**
@@ -2307,8 +2569,8 @@
* @stable ICU 3.0
*/
public String getDisplayKeywordValue(String keyword, ULocale displayLocale) {
- return new IDParser(localeID).getKeywordValue(keyword.trim().toLowerCase());
- }
+ return getDisplayKeywordValueInternal(localeID, keyword, displayLocale.localeID);
+ }
/**
* Returns a keyword value localized for display in the specified locale.
@@ -2320,7 +2582,7 @@
* @stable ICU 3.0
*/
public static String getDisplayKeywordValue(String localeID, String keyword, String displayLocaleID) {
- return new IDParser(localeID).getKeywordValue(keyword.trim().toLowerCase());
+ return getDisplayKeywordValueInternal(localeID, keyword, getName(displayLocaleID));
}
/**
@@ -2333,16 +2595,24 @@
* @stable ICU 3.0
*/
public static String getDisplayKeywordValue(String localeID, String keyword, ULocale displayLocale) {
- return new IDParser(localeID).getKeywordValue(keyword.trim().toLowerCase());
+ return getDisplayKeywordValueInternal(localeID, keyword, displayLocale.localeID);
}
+ // displayLocaleID is canonical, localeID need not be since parsing will fix this.
+ private static String getDisplayKeywordValueInternal(String localeID, String keyword, String displayLocaleID) {
+ keyword = keyword.trim().toLowerCase();
+ String value = new IDParser(localeID).getKeywordValue(keyword);
+// return getTableString("Types", keyword, value, displayLocaleID);
+ return value;
+ }
+
/**
* Returns this locale name localized for display in the default locale.
* @return the localized locale name.
* @stable ICU 3.0
*/
public String getDisplayName() {
- return getDisplayNameInternal(localeID, getDefault().toLocale());
+ return getDisplayNameInternal(localeID, getDefault().localeID);
}
/**
@@ -2352,7 +2622,7 @@
* @stable ICU 3.0
*/
public String getDisplayName(ULocale displayLocale) {
- return getDisplayNameInternal(localeID, displayLocale.toLocale());
+ return getDisplayNameInternal(localeID, displayLocale.localeID);
}
/**
@@ -2364,7 +2634,7 @@
* @stable ICU 3.0
*/
public static String getDisplayName(String localeID, String displayLocaleID) {
- return getDisplayNameInternal(localeID, toLocale(displayLocaleID));
+ return getDisplayNameInternal(localeID, getName(displayLocaleID));
}
/**
@@ -2376,34 +2646,42 @@
* @stable ICU 3.0
*/
public static String getDisplayName(String localeID, ULocale displayLocale) {
- return getDisplayNameInternal(localeID, displayLocale.toLocale());
+ return getDisplayNameInternal(localeID, displayLocale.localeID);
}
// displayLocaleID is canonical, localeID need not be since parsing will fix this.
- private static String getDisplayNameInternal(String localeID, Locale displayLocale) {
+ private static String getDisplayNameInternal(String localeID, String displayLocaleID) {
// lang
// lang (script, country, variant, keyword=value, ...)
// script, country, variant, keyword=value, ...
+// final String[] tableNames = { "Languages", "Scripts", "Countries", "Variants" };
+//
+// ICUResourceBundle bundle = (ICUResourceBundle)UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, displayLocaleID);
+
StringBuffer buf = new StringBuffer();
IDParser parser = new IDParser(localeID);
String[] names = parser.getLanguageScriptCountryVariant();
-
+
Locale locale = toLocale(localeID);
+ Locale dispLocale = toLocale(displayLocaleID);
boolean haveLanguage = names[0].length() > 0;
boolean openParen = false;
for (int i = 0; i < names.length; ++i) {
String name = names[i];
if (name.length() > 0) {
+// name = getTableString(tableNames[i], null, name, bundle);
+
switch (i) {
- case 0: name = locale.getDisplayLanguage(displayLocale); break;
+ case 0: name = locale.getDisplayLanguage(dispLocale); break;
case 1: break;
- case 2: name = locale.getDisplayCountry(displayLocale); break;
- case 3: name = locale.getDisplayVariant(displayLocale); break;
+ case 2: name = locale.getDisplayCountry(dispLocale); break;
+ case 3: name = locale.getDisplayVariant(dispLocale); break;
}
- if (buf.length() > 0) {
+
+ if (buf.length() > 0) { // need a separator
if (haveLanguage & !openParen) {
buf.append(" (");
openParen = true;
@@ -2430,6 +2708,9 @@
Map.Entry e = (Map.Entry)keys.next();
String key = (String)e.getKey();
String val = (String)e.getValue();
+// buf.append(getTableString("Keys", null, key, bundle));
+// buf.append("=");
+// buf.append(getTableString("Types", key, val, bundle));
buf.append(key);
buf.append("=");
buf.append(val);
@@ -2442,7 +2723,72 @@
return buf.toString();
}
-
+
+// /**
+// * Returns this locale's layout orientation for characters. The possible
+// * values are "left-to-right", "right-to-left", "top-to-bottom" or
+// * "bottom-to-top".
+// * @return The locale's layout orientation for characters.
+// * @draft ICU 4.0
+// * @provisional This API might change or be removed in a future release.
+// */
+// public String getCharacterOrientation() {
+// return getTableString("layout", null, "characters", getName());
+// }
+//
+// /**
+// * Returns this locale's layout orientation for lines. The possible
+// * values are "left-to-right", "right-to-left", "top-to-bottom" or
+// * "bottom-to-top".
+// * @return The locale's layout orientation for lines.
+// * @draft ICU 4.0
+// * @provisional This API might change or be removed in a future release.
+// */
+// public String getLineOrientation() {
+// return getTableString("layout", null, "lines", getName());
+// }
+
+ /**
+ * Selector for <tt>getLocale()</tt> indicating the locale of the
+ * resource containing the data. This is always at or above the
+ * valid locale. If the valid locale does not contain the
+ * specific data being requested, then the actual locale will be
+ * above the valid locale. If the object was not constructed from
+ * locale data, then the valid locale is <i>null</i>.
+ *
+ * @draft ICU 2.8 (retain)
+ * @provisional This API might change or be removed in a future release.
+ */
+ public static Type ACTUAL_LOCALE = new Type();
+
+ /**
+ * Selector for <tt>getLocale()</tt> indicating the most specific
+ * locale for which any data exists. This is always at or above
+ * the requested locale, and at or below the actual locale. If
+ * the requested locale does not correspond to any resource data,
+ * then the valid locale will be above the requested locale. If
+ * the object was not constructed from locale data, then the
+ * actual locale is <i>null</i>.
+ *
+ * <p>Note: The valid locale will be returned correctly in ICU
+ * 3.0 or later. In ICU 2.8, it is not returned correctly.
+ * @draft ICU 2.8 (retain)
+ * @provisional This API might change or be removed in a future release.
+ */
+ public static Type VALID_LOCALE = new Type();
+
+ /**
+ * Opaque selector enum for <tt>getLocale()</tt>.
+ * @see com.ibm.icu.util.ULocale
+ * @see com.ibm.icu.util.ULocale#ACTUAL_LOCALE
+ * @see com.ibm.icu.util.ULocale#VALID_LOCALE
+ * @draft ICU 2.8 (retainAll)
+ * @provisional This API might change or be removed in a future release.
+ */
+ public static final class Type {
+ private Type() {}
+ }
+
/**
* Based on a HTTP formatted list of acceptable locales, determine an available locale for the user.
* NullPointerException is thrown if acceptLanguageList or availableLocales is
@@ -2458,93 +2804,25 @@
* @return one of the locales from the availableLocales list, or null if none match
* @stable ICU 3.4
*/
- public static ULocale acceptLanguage(String acceptLanguageList,
- ULocale[] availableLocales, boolean[] fallback) {
- /**
- * @internal ICU 3.4
- */
- class ULocaleAcceptLanguageQ implements Comparable {
- private double q;
- private double serial;
- public ULocaleAcceptLanguageQ(double theq, int theserial) {
- q = theq;
- serial = theserial;
- }
- public int compareTo(Object o) {
- ULocaleAcceptLanguageQ other = (ULocaleAcceptLanguageQ) o;
- if(q > other.q) { // reverse - to sort in descending order
- return -1;
- } else if(q < other.q) {
- return 1;
- }
- if(serial < other.serial) {
- return -1;
- } else if(serial > other.serial) {
- return 1;
- } else {
- return 0; // same object
- }
- }
- }
- // 1st: parse out the acceptLanguageList into an array
-
- TreeMap map = new TreeMap();
-
- final int l = acceptLanguageList.length();
- int n;
- for(n=0;n<l;n++) {
- int itemEnd = acceptLanguageList.indexOf(',',n);
- if(itemEnd == -1) {
- itemEnd = l;
- }
- int paramEnd = acceptLanguageList.indexOf(';',n);
- double q = 1.0;
-
- if((paramEnd != -1) && (paramEnd < itemEnd)) {
- /* semicolon (;) is closer than end (,) */
- int t = paramEnd + 1;
- while(Character.isWhitespace(acceptLanguageList.charAt(t))) {
- t++;
- }
- if(acceptLanguageList.charAt(t)=='q') {
- t++;
- }
- while(Character.isWhitespace(acceptLanguageList.charAt(t))) {
- t++;
- }
- if(acceptLanguageList.charAt(t)=='=') {
- t++;
- }
- while(Character.isWhitespace(acceptLanguageList.charAt(t))) {
- t++;
- }
- try {
- String val = acceptLanguageList.substring(t,itemEnd).trim();
- q = Double.parseDouble(val);
- } catch (NumberFormatException nfe) {
- q = 1.0;
- }
- } else {
- q = 1.0; //default
- paramEnd = itemEnd;
- }
-
- String loc = acceptLanguageList.substring(n,paramEnd).trim();
- int serial = map.size();
- ULocaleAcceptLanguageQ entry = new ULocaleAcceptLanguageQ(q,serial);
- map.put(entry, new ULocale(canonicalize(loc))); // sort in reverse order.. 1.0, 0.9, 0.8 .. etc
- n = itemEnd; // get next item. (n++ will skip over delimiter)
+ public static ULocale acceptLanguage(String acceptLanguageList, ULocale[] availableLocales,
+ boolean[] fallback) {
+ if (acceptLanguageList == null) {
+ throw new NullPointerException();
}
-
- // 2. pull out the map
- ULocale acceptList[] = (ULocale[])map.values().toArray(new ULocale[map.size()]);
-
- // 3. call the real function
+ ULocale acceptList[] = null;
+ try {
+ acceptList = parseAcceptLanguage(acceptLanguageList, true);
+ } catch (ParseException pe) {
+ acceptList = null;
+ }
+ if (acceptList == null) {
+ return null;
+ }
return acceptLanguage(acceptList, availableLocales, fallback);
}
-
- /**
+
+ /**
* Based on a list of acceptable locales, determine an available locale for the user.
* NullPointerException is thrown if acceptLanguageList or availableLocales is
* null. If fallback is non-null, it will contain true if a fallback locale (one
@@ -2559,8 +2837,9 @@
* @return one of the locales from the availableLocales list, or null if none match
* @stable ICU 3.4
*/
- public static ULocale acceptLanguage(ULocale[] acceptLanguageList,
- ULocale[] availableLocales, boolean[] fallback) {
+
+ public static ULocale acceptLanguage(ULocale[] acceptLanguageList, ULocale[]
+ availableLocales, boolean[] fallback) {
// fallbacklist
int i,j;
if(fallback != null) {
@@ -2578,20 +2857,46 @@
return availableLocales[j];
}
}
- aLocale = aLocale.getFallback();
+ Locale loc = aLocale.toLocale();
+// Locale parent = LocaleUtility.fallback(loc);
+ Locale parent = fallback(loc);
+ if(parent != null) {
+ aLocale = new ULocale(parent);
+ } else {
+ aLocale = null;
+ }
setFallback = null; // Do not set fallback in later iterations
} while (aLocale != null);
}
return null;
}
- /**
+ // copied from com.ibm.icu.impl.LocaleUtility
+ private static Locale fallback(Locale loc) {
+
+ // Split the locale into parts and remove the rightmost part
+ String[] parts = new String[]
+ { loc.getLanguage(), loc.getCountry(), loc.getVariant() };
+ int i;
+ for (i=2; i>=0; --i) {
+ if (parts[i].length() != 0) {
+ parts[i] = "";
+ break;
+ }
+ }
+ if (i<0) {
+ return null; // All parts were empty
+ }
+ return new Locale(parts[0], parts[1], parts[2]);
+ }
+
+ /**
* Based on a HTTP formatted list of acceptable locales, determine an available locale for the user.
* NullPointerException is thrown if acceptLanguageList or availableLocales is
* null. If fallback is non-null, it will contain true if a fallback locale (one
* not in the acceptLanguageList) was returned. The value on entry is ignored.
* ULocale will be one of the locales in availableLocales, or the ROOT ULocale if
- * a ROOT locale was used as a fallback (because nothing else in
+ * if a ROOT locale was used as a fallback (because nothing else in
* availableLocales matched). No ULocale array element should be null; behavior
* is undefined if this is the case.
* This function will choose a locale from the ULocale.getAvailableLocales() list as available.
@@ -2600,8 +2905,10 @@
* @return one of the locales from the ULocale.getAvailableLocales() list, or null if none match
* @stable ICU 3.4
*/
+
public static ULocale acceptLanguage(String acceptLanguageList, boolean[] fallback) {
- return acceptLanguage(acceptLanguageList, ULocale.getAvailableLocales(), fallback);
+ return acceptLanguage(acceptLanguageList, ULocale.getAvailableLocales(),
+ fallback);
}
/**
@@ -2619,7 +2926,897 @@
* @return one of the locales from the ULocale.getAvailableLocales() list, or null if none match
* @stable ICU 3.4
*/
- public static ULocale acceptLanguage(ULocale[] acceptLanguageList, boolean[] fallback) {
- return acceptLanguage(acceptLanguageList, ULocale.getAvailableLocales(), fallback);
+
+ public static ULocale acceptLanguage(ULocale[] acceptLanguageList, boolean[]
+ fallback) {
+ return acceptLanguage(acceptLanguageList, ULocale.getAvailableLocales(),
+ fallback);
}
+
+ /**
+ * Package local method used for parsing Accept-Language string
+ * @internal ICU 3.8
+ */
+ static ULocale[] parseAcceptLanguage(String acceptLanguage, boolean isLenient) throws ParseException {
+ /**
+ * @internal ICU 3.4
+ */
+ class ULocaleAcceptLanguageQ implements Comparable {
+ private double q;
+ private double serial;
+ public ULocaleAcceptLanguageQ(double theq, int theserial) {
+ q = theq;
+ serial = theserial;
+ }
+ public int compareTo(Object o) {
+ ULocaleAcceptLanguageQ other = (ULocaleAcceptLanguageQ) o;
+ if (q > other.q) { // reverse - to sort in descending order
+ return -1;
+ } else if (q < other.q) {
+ return 1;
+ }
+ if (serial < other.serial) {
+ return -1;
+ } else if (serial > other.serial) {
+ return 1;
+ } else {
+ return 0; // same object
+ }
+ }
+ }
+
+ // parse out the acceptLanguage into an array
+ TreeMap map = new TreeMap();
+ StringBuffer languageRangeBuf = new StringBuffer();
+ StringBuffer qvalBuf = new StringBuffer();
+ int state = 0;
+ acceptLanguage += ","; // append comma to simplify the parsing code
+ int n;
+ boolean subTag = false;
+ boolean q1 = false;
+ for (n = 0; n < acceptLanguage.length(); n++) {
+ boolean gotLanguageQ = false;
+ char c = acceptLanguage.charAt(n);
+ switch (state) {
+ case 0: // before language-range start
+ if (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z')) {
+ // in language-range
+ languageRangeBuf.append(c);
+ state = 1;
+ subTag = false;
+ } else if (c == '*') {
+ languageRangeBuf.append(c);
+ state = 2;
+ } else if (c != ' ' && c != '\t') {
+ // invalid character
+ state = -1;
+ }
+ break;
+ case 1: // in language-range
+ if (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z')) {
+ languageRangeBuf.append(c);
+ } else if (c == '-') {
+ subTag = true;
+ languageRangeBuf.append(c);
+ } else if (c == '_') {
+ if (isLenient) {
+ subTag = true;
+ languageRangeBuf.append(c);
+ } else {
+ state = -1;
+ }
+ } else if ('0' <= c && c <= '9') {
+ if (subTag) {
+ languageRangeBuf.append(c);
+ } else {
+ // DIGIT is allowed only in language sub tag
+ state = -1;
+ }
+ } else if (c == ',') {
+ // language-q end
+ gotLanguageQ = true;
+ } else if (c == ' ' || c == '\t') {
+ // language-range end
+ state = 3;
+ } else if (c == ';') {
+ // before q
+ state = 4;
+ } else {
+ // invalid character for language-range
+ state = -1;
+ }
+ break;
+ case 2: // saw wild card range
+ if (c == ',') {
+ // language-q end
+ gotLanguageQ = true;
+ } else if (c == ' ' || c == '\t') {
+ // language-range end
+ state = 3;
+ } else if (c == ';') {
+ // before q
+ state = 4;
+ } else {
+ // invalid
+ state = -1;
+ }
+ break;
+ case 3: // language-range end
+ if (c == ',') {
+ // language-q end
+ gotLanguageQ = true;
+ } else if (c == ';') {
+ // before q
+ state =4;
+ } else if (c != ' ' && c != '\t') {
+ // invalid
+ state = -1;
+ }
+ break;
+ case 4: // before q
+ if (c == 'q') {
+ // before equal
+ state = 5;
+ } else if (c != ' ' && c != '\t') {
+ // invalid
+ state = -1;
+ }
+ break;
+ case 5: // before equal
+ if (c == '=') {
+ // before q value
+ state = 6;
+ } else if (c != ' ' && c != '\t') {
+ // invalid
+ state = -1;
+ }
+ break;
+ case 6: // before q value
+ if (c == '0') {
+ // q value start with 0
+ q1 = false;
+ qvalBuf.append(c);
+ state = 7;
+ } else if (c == '1') {
+ // q value start with 1
+ qvalBuf.append(c);
+ state = 7;
+ } else if (c == '.') {
+ if (isLenient) {
+ qvalBuf.append(c);
+ state = 8;
+ } else {
+ state = -1;
+ }
+ } else if (c != ' ' && c != '\t') {
+ // invalid
+ state = -1;
+ }
+ break;
+ case 7: // q value start
+ if (c == '.') {
+ // before q value fraction part
+ qvalBuf.append(c);
+ state = 8;
+ } else if (c == ',') {
+ // language-q end
+ gotLanguageQ = true;
+ } else if (c == ' ' || c == '\t') {
+ // after q value
+ state = 10;
+ } else {
+ // invalid
+ state = -1;
+ }
+ break;
+ case 8: // before q value fraction part
+ if ('0' <= c || c <= '9') {
+ if (q1 && c != '0' && !isLenient) {
+ // if q value starts with 1, the fraction part must be 0
+ state = -1;
+ } else {
+ // in q value fraction part
+ qvalBuf.append(c);
+ state = 9;
+ }
+ } else {
+ // invalid
+ state = -1;
+ }
+ break;
+ case 9: // in q value fraction part
+ if ('0' <= c && c <= '9') {
+ if (q1 && c != '0') {
+ // if q value starts with 1, the fraction part must be 0
+ state = -1;
+ } else {
+ qvalBuf.append(c);
+ }
+ } else if (c == ',') {
+ // language-q end
+ gotLanguageQ = true;
+ } else if (c == ' ' || c == '\t') {
+ // after q value
+ state = 10;
+ } else {
+ // invalid
+ state = -1;
+ }
+ break;
+ case 10: // after q value
+ if (c == ',') {
+ // language-q end
+ gotLanguageQ = true;
+ } else if (c != ' ' && c != '\t') {
+ // invalid
+ state = -1;
+ }
+ break;
+ }
+ if (state == -1) {
+ // error state
+ throw new ParseException("Invalid Accept-Language", n);
+ }
+ if (gotLanguageQ) {
+ double q = 1.0;
+ if (qvalBuf.length() != 0) {
+ try {
+ q = Double.parseDouble(qvalBuf.toString());
+ } catch (NumberFormatException nfe) {
+ // Already validated, so it should never happen
+ q = 1.0;
+ }
+ if (q > 1.0) {
+ q = 1.0;
+ }
+ }
+ if (languageRangeBuf.charAt(0) != '*') {
+ int serial = map.size();
+ ULocaleAcceptLanguageQ entry = new ULocaleAcceptLanguageQ(q, serial);
+ map.put(entry, new ULocale(canonicalize(languageRangeBuf.toString()))); // sort in reverse order.. 1.0, 0.9, 0.8 .. etc
+ }
+
+ // reset buffer and parse state
+ languageRangeBuf.setLength(0);
+ qvalBuf.setLength(0);
+ state = 0;
+ }
+ }
+ if (state != 0) {
+ // Well, the parser should handle all cases. So just in case.
+ throw new ParseException("Invalid AcceptlLanguage", n);
+ }
+
+ // pull out the map
+ ULocale acceptList[] = (ULocale[])map.values().toArray(new ULocale[map.size()]);
+ return acceptList;
+ }
+
+// private static final String UNDEFINED_LANGUAGE = "und";
+// private static final String UNDEFINED_SCRIPT = "Zzzz";
+// private static final String UNDEFINED_REGION = "ZZ";
+//
+// /**
+// * Supply most likely subtags to the given locale
+// * @param loc The input locale
+// * @return A ULocale with most likely subtags filled in.
+// * @internal
+// * @deprecated This API is ICU internal only.
+// */
+// public static ULocale addLikelySubtag(ULocale loc) {
+// return addLikelySubtags(loc);
+// }
+//
+// /**
+// * Add the likely subtags for a provided locale ID, per the algorithm described
+// * in the following CLDR technical report:
+// *
+// * http://www.unicode.org/reports/tr35/#Likely_Subtags
+// *
+// * If the provided ULocale instance is already in the maximal form, or there is no
+// * data available available for maximization, it will be returned. For example,
+// * "und-Zzzz" cannot be maximized, since there is no reasonable maximization.
+// * Otherwise, a new ULocale instance with the maximal form is returned.
+// *
+// * Examples:
+// *
+// * "en" maximizes to "en_Latn_US"
+// *
+// * "de" maximizes to "de_Latn_US"
+// *
+// * "sr" maximizes to "sr_Cyrl_RS"
+// *
+// * "sh" maximizes to "sr_Latn_RS" (Note this will not reverse.)
+// *
+// * "zh_Hani" maximizes to "zh_Hans_CN" (Note this will not reverse.)
+// *
+// * @param loc The ULocale to maximize
+// * @return The maximized ULocale instance.
+// * @draft ICU 4.0
+// * @provisional This API might change or be removed in a future release.
+// */
+// public static ULocale
+// addLikelySubtags(ULocale loc)
+// {
+// String[] tags = new String[3];
+// String trailing = null;
+//
+// int trailingIndex = parseTagString(
+// loc.localeID,
+// tags);
+//
+// if (trailingIndex < loc.localeID.length()) {
+// trailing = loc.localeID.substring(trailingIndex);
+// }
+//
+// String newLocaleID =
+// createLikelySubtagsString(
+// (String)tags[0],
+// (String)tags[1],
+// (String)tags[2],
+// trailing);
+//
+// return newLocaleID == null ? loc : new ULocale(newLocaleID);
+// }
+//
+// /**
+// * Minimize the subtags for a provided locale ID, per the algorithm described
+// * in the following CLDR technical report:
+// *
+// * http://www.unicode.org/reports/tr35/#Likely_Subtags
+// *
+// * If the provided ULocale instance is already in the minimal form, or there
+// * is no data available for minimization, it will be returned. Since the
+// * minimization algorithm relies on proper maximization, see the comments
+// * for addLikelySubtags for reasons why there might not be any data.
+// *
+// * Examples:
+// *
+// * "en_Latn_US" minimizes to "en"
+// *
+// * "de_Latn_US" minimizes to "de"
+// *
+// * "sr_Cyrl_RS" minimizes to "sr"
+// *
+// * "zh_Hant_TW" minimizes to "zh_TW" (The region is preferred to the
+// * script, and minimizing to "zh" would imply "zh_Hans_CN".)
+// *
+// * @param loc The ULocale to minimize
+// * @return The minimized ULocale instance.
+// * @draft ICU 4.0
+// * @provisional This API might change or be removed in a future release.
+// */
+// public static ULocale
+// minimizeSubtags(ULocale loc)
+// {
+// String[] tags = new String[3];
+//
+// int trailingIndex = parseTagString(
+// loc.localeID,
+// tags);
+//
+// String originalLang = (String)tags[0];
+// String originalScript = (String)tags[1];
+// String originalRegion = (String)tags[2];
+// String originalTrailing = null;
+//
+// if (trailingIndex < loc.localeID.length()) {
+// /*
+// * Create a String that contains everything
+// * after the language, script, and region.
+// */
+// originalTrailing = loc.localeID.substring(trailingIndex);
+// }
+//
+// /**
+// * First, we need to first get the maximization
+// * by adding any likely subtags.
+// **/
+// String maximizedLocaleID =
+// createLikelySubtagsString(
+// originalLang,
+// originalScript,
+// originalRegion,
+// null);
+//
+// /**
+// * If maximization fails, there's nothing
+// * we can do.
+// **/
+// if (isEmptyString(maximizedLocaleID)) {
+// return loc;
+// }
+// else {
+// /**
+// * Start first with just the language.
+// **/
+// String tag =
+// createLikelySubtagsString(
+// originalLang,
+// null,
+// null,
+// null);
+//
+// if (tag.equals(maximizedLocaleID)) {
+// String newLocaleID =
+// createTagString(
+// originalLang,
+// null,
+// null,
+// originalTrailing);
+//
+// return new ULocale(newLocaleID);
+// }
+// }
+//
+// /**
+// * Next, try the language and region.
+// **/
+// if (originalRegion.length() != 0) {
+//
+// String tag =
+// createLikelySubtagsString(
+// originalLang,
+// null,
+// originalRegion,
+// null);
+//
+// if (tag.equals(maximizedLocaleID)) {
+// String newLocaleID =
+// createTagString(
+// originalLang,
+// null,
+// originalRegion,
+// originalTrailing);
+//
+// return new ULocale(newLocaleID);
+// }
+// }
+//
+// /**
+// * Finally, try the language and script. This is our last chance,
+// * since trying with all three subtags would only yield the
+// * maximal version that we already have.
+// **/
+// if (originalRegion.length() != 0 &&
+// originalScript.length() != 0) {
+//
+// String tag =
+// createLikelySubtagsString(
+// originalLang,
+// originalScript,
+// null,
+// null);
+//
+// if (tag.equals(maximizedLocaleID)) {
+// String newLocaleID =
+// createTagString(
+// originalLang,
+// originalScript,
+// null,
+// originalTrailing);
+//
+// return new ULocale(newLocaleID);
+// }
+// }
+//
+// return loc;
+// }
+//
+// /**
+// * A trivial utility function that checks for a null
+// * reference or checks the length of the supplied String.
+// *
+// * @param string The string to check
+// *
+// * @return true if the String is empty, or if the reference is null.
+// */
+// private static boolean isEmptyString(String string) {
+// return string == null || string.length() == 0;
+// }
+//
+// /**
+// * Append a tag to a StringBuffer, adding the separator if necessary.The tag must
+// * not be a zero-length string.
+// *
+// * @param tag The tag to add.
+// * @param buffer The output buffer.
+// **/
+// private static void
+// appendTag(
+// String tag,
+// StringBuffer buffer) {
+//
+// if (buffer.length() != 0) {
+// buffer.append(UNDERSCORE);
+// }
+//
+// buffer.append(tag);
+// }
+//
+// /**
+// * Create a tag string from the supplied parameters. The lang, script and region
+// * parameters may be null references.
+// *
+// * If any of the language, script or region parameters are empty, and the alternateTags
+// * parameter is not null, it will be parsed for potential language, script and region tags
+// * to be used when constructing the new tag. If the alternateTags parameter is null, or
+// * it contains no language tag, the default tag for the unknown language is used.
+// *
+// * @param lang The language tag to use.
+// * @param script The script tag to use.
+// * @param region The region tag to use.
+// * @param trailing Any trailing data to append to the new tag.
+// * @param alternateTags A string containing any alternate tags.
+// * @return The new tag string.
+// **/
+// private static String
+// createTagString(
+// String lang,
+// String script,
+// String region,
+// String trailing,
+// String alternateTags) {
+//
+// IDParser parser = null;
+// boolean regionAppended = false;
+//
+// StringBuffer tag = new StringBuffer();
+//
+// if (!isEmptyString(lang)) {
+// appendTag(
+// lang,
+// tag);
+// }
+// else if (isEmptyString(alternateTags)) {
+// /*
+// * Append the value for an unknown language, if
+// * we found no language.
+// */
+// appendTag(
+// UNDEFINED_LANGUAGE,
+// tag);
+// }
+// else {
+// parser = new IDParser(alternateTags);
+//
+// String alternateLang = parser.getLanguage();
+//
+// /*
+// * Append the value for an unknown language, if
+// * we found no language.
+// */
+// appendTag(
+// !isEmptyString(alternateLang) ? alternateLang : UNDEFINED_LANGUAGE,
+// tag);
+// }
+//
+// if (!isEmptyString(script)) {
+// appendTag(
+// script,
+// tag);
+// }
+// else if (!isEmptyString(alternateTags)) {
+// /*
+// * Parse the alternateTags string for the script.
+// */
+// if (parser == null) {
+// parser = new IDParser(alternateTags);
+// }
+//
+// String alternateScript = parser.getScript();
+//
+// if (!isEmptyString(alternateScript)) {
+// appendTag(
+// alternateScript,
+// tag);
+// }
+// }
+//
+// if (!isEmptyString(region)) {
+// appendTag(
+// region,
+// tag);
+//
+// regionAppended = true;
+// }
+// else if (!isEmptyString(alternateTags)) {
+// /*
+// * Parse the alternateTags string for the region.
+// */
+// if (parser == null) {
+// parser = new IDParser(alternateTags);
+// }
+//
+// String alternateRegion = parser.getCountry();
+//
+// if (!isEmptyString(alternateRegion)) {
+// appendTag(
+// alternateRegion,
+// tag);
+//
+// regionAppended = true;
+// }
+// }
+//
+// if (trailing != null && trailing.length() > 1) {
+// /*
+// * The current ICU format expects two underscores
+// * will separate the variant from the preceeding
+// * parts of the tag, if there is no region.
+// */
+// int separators = 0;
+//
+// if (trailing.charAt(0) == UNDERSCORE) {
+// if (trailing.charAt(1) == UNDERSCORE) {
+// separators = 2;
+// }
+// }
+// else {
+// separators = 1;
+// }
+//
+// if (regionAppended) {
+// /*
+// * If we appended a region, we may need to strip
+// * the extra separator from the variant portion.
+// */
+// if (separators == 2) {
+// tag.append(trailing.substring(1));
+// }
+// else {
+// tag.append(trailing);
+// }
+// }
+// else {
+// /*
+// * If we did not append a region, we may need to add
+// * an extra separator to the variant portion.
+// */
+// if (separators == 1) {
+// tag.append(UNDERSCORE);
+// }
+// tag.append(trailing);
+// }
+// }
+//
+// return tag.toString();
+// }
+//
+// /**
+// * Create a tag string from the supplied parameters. The lang, script and region
+// * parameters may be null references.If the lang parameter is an empty string, the
+// * default value for an unknown language is written to the output buffer.
+// *
+// * @param lang The language tag to use.
+// * @param script The script tag to use.
+// * @param region The region tag to use.
+// * @param trailing Any trailing data to append to the new tag.
+// * @return The new String.
+// **/
+// static String
+// createTagString(
+// String lang,
+// String script,
+// String region,
+// String trailing) {
+//
+// return createTagString(
+// lang,
+// script,
+// region,
+// trailing,
+// null);
+// }
+//
+// /**
+// * Parse the language, script, and region subtags from a tag string, and return the results.
+// *
+// * This function does not return the canonical strings for the unknown script and region.
+// *
+// * @param localeID The locale ID to parse.
+// * @param tags An array of three String references to return the subtag strings.
+// * @return The number of chars of the localeID parameter consumed.
+// **/
+// private static int
+// parseTagString(
+// String localeID,
+// String tags[])
+// {
+// IDParser parser = new IDParser(localeID);
+//
+// String lang = parser.getLanguage();
+// String script = parser.getScript();
+// String region = parser.getCountry();
+//
+// if (isEmptyString(lang)) {
+// tags[0] = UNDEFINED_LANGUAGE;
+// }
+// else {
+// tags[0] = lang;
+// }
+//
+// if (script.equals(UNDEFINED_SCRIPT)) {
+// tags[1] = "";
+// }
+// else {
+// tags[1] = script;
+// }
+//
+// if (region.equals(UNDEFINED_REGION)) {
+// tags[2] = "";
+// }
+// else {
+// tags[2] = region;
+// }
+//
+// /*
+// * Search for the variant. If there is one, then return the index of
+// * the preceeding separator.
+// * If there's no variant, search for the keyword delimiter,
+// * and return its index. Otherwise, return the length of the
+// * string.
+// *
+// * $TOTO(dbertoni) we need to take into account that we might
+// * find a part of the language as the variant, since it can
+// * can have a variant portion that is long enough to contain
+// * the same characters as the variant.
+// */
+// String variant = parser.getVariant();
+//
+// if (!isEmptyString(variant)){
+// int index = localeID.indexOf(variant);
+//
+//
+// return index > 0 ? index - 1 : index;
+// }
+// else
+// {
+// int index = localeID.indexOf('@');
+//
+// return index == -1 ? localeID.length() : index;
+// }
+// }
+//
+// private static String
+// lookupLikelySubtags(String localeId) {
+// UResourceBundle bundle =
+// UResourceBundle.getBundleInstance(
+// ICUResourceBundle.ICU_BASE_NAME, "likelySubtags");
+// try {
+// return bundle.getString(localeId);
+// }
+// catch(MissingResourceException e) {
+// return null;
+// }
+// }
+//
+// private static String
+// createLikelySubtagsString(
+// String lang,
+// String script,
+// String region,
+// String variants) {
+//
+// /**
+// * Try the language with the script and region first.
+// **/
+// if (!isEmptyString(script) && !isEmptyString(region)) {
+//
+// String searchTag =
+// createTagString(
+// lang,
+// script,
+// region,
+// null);
+//
+// String likelySubtags = lookupLikelySubtags(searchTag);
+//
+// /*
+// if (likelySubtags == null) {
+// if (likelySubtags2 != null) {
+// System.err.println("Tag mismatch: \"(null)\" \"" + likelySubtags2 + "\"");
+// }
+// }
+// else if (likelySubtags2 == null) {
+// System.err.println("Tag mismatch: \"" + likelySubtags + "\" \"(null)\"");
+// }
+// else if (!likelySubtags.equals(likelySubtags2)) {
+// System.err.println("Tag mismatch: \"" + likelySubtags + "\" \"" + likelySubtags2 + "\"");
+// }
+// */
+// if (likelySubtags != null) {
+// // Always use the language tag from the
+// // maximal string, since it may be more
+// // specific than the one provided.
+// return createTagString(
+// null,
+// null,
+// null,
+// variants,
+// likelySubtags);
+// }
+// }
+//
+// /**
+// * Try the language with just the script.
+// **/
+// if (!isEmptyString(script)) {
+//
+// String searchTag =
+// createTagString(
+// lang,
+// script,
+// null,
+// null);
+//
+// String likelySubtags = lookupLikelySubtags(searchTag);
+// if (likelySubtags != null) {
+// // Always use the language tag from the
+// // maximal string, since it may be more
+// // specific than the one provided.
+// return createTagString(
+// null,
+// null,
+// region,
+// variants,
+// likelySubtags);
+// }
+// }
+//
+// /**
+// * Try the language with just the region.
+// **/
+// if (!isEmptyString(region)) {
+//
+// String searchTag =
+// createTagString(
+// lang,
+// null,
+// region,
+// null);
+//
+// String likelySubtags = lookupLikelySubtags(searchTag);
+//
+// if (likelySubtags != null) {
+// // Always use the language tag from the
+// // maximal string, since it may be more
+// // specific than the one provided.
+// return createTagString(
+// null,
+// script,
+// null,
+// variants,
+// likelySubtags);
+// }
+// }
+//
+// /**
+// * Finally, try just the language.
+// **/
+// {
+// String searchTag =
+// createTagString(
+// lang,
+// null,
+// null,
+// null);
+//
+// String likelySubtags = lookupLikelySubtags(searchTag);
+//
+// if (likelySubtags != null) {
+// // Always use the language tag from the
+// // maximal string, since it may be more
+// // specific than the one provided.
+// return createTagString(
+// null,
+// script,
+// region,
+// variants,
+// likelySubtags);
+// }
+// }
+//
+// return null;
+// }
}
diff --git a/src/com/ibm/icu/dev/eclipse/plugins/com.ibm.icu.tests/META-INF/MANIFEST.MF b/src/com/ibm/icu/dev/eclipse/plugins/com.ibm.icu.tests/META-INF/MANIFEST.MF
index 322434e..cb255cf 100644
--- a/src/com/ibm/icu/dev/eclipse/plugins/com.ibm.icu.tests/META-INF/MANIFEST.MF
+++ b/src/com/ibm/icu/dev/eclipse/plugins/com.ibm.icu.tests/META-INF/MANIFEST.MF
@@ -4,8 +4,9 @@
Bundle-SymbolicName: com.ibm.icu.tests
Bundle-Version: 1.0.0
Bundle-Vendor: IBM
-Fragment-Host: com.ibm.icu;bundle-version="[3.9.0,4.1.0)"
-Bundle-Localization: plugin
+Fragment-Host: com.ibm.icu;bundle-version="[4.0.0,4.2.0)"
Bundle-Copyright: @COPYRIGHT@
Require-Bundle: org.junit
Bundle-ClassPath: .,icu4jtests.jar
+Bundle-RequiredExecutionEnvironment: J2SE-1.3,
+ CDC-1.0/Foundation-1.0
diff --git a/src/com/ibm/icu/dev/eclipse/plugins/com.ibm.icu/META-INF/MANIFEST.MF b/src/com/ibm/icu/dev/eclipse/plugins/com.ibm.icu/META-INF/MANIFEST.MF
index 100098b..29da738 100644
--- a/src/com/ibm/icu/dev/eclipse/plugins/com.ibm.icu/META-INF/MANIFEST.MF
+++ b/src/com/ibm/icu/dev/eclipse/plugins/com.ibm.icu/META-INF/MANIFEST.MF
@@ -6,10 +6,10 @@
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Bundle-Copyright: @COPYRIGHT@
-Export-Package: com.ibm.icu.lang;version="@IMPL_VERSION@",
- com.ibm.icu.math;version="@IMPL_VERSION@",
- com.ibm.icu.text;version="@IMPL_VERSION@",
- com.ibm.icu.util;version="@IMPL_VERSION@",
+Export-Package: com.ibm.icu.lang;base=true;full=true;version="@IMPL_VERSION@",
+ com.ibm.icu.math;base=true;full=true;version="@IMPL_VERSION@",
+ com.ibm.icu.text;base=true;full=true;version="@IMPL_VERSION@",
+ com.ibm.icu.util;base=true;full=true;version="@IMPL_VERSION@",
com.ibm.icu.impl;x-internal:=true,
com.ibm.icu.impl.data;x-internal:=true,
com.ibm.icu.impl.data.icudt@DATA_VERSION_NUMBER@b;x-internal:=true,
diff --git a/src/com/ibm/icu/dev/test/calendar/CalendarRegression.java b/src/com/ibm/icu/dev/test/calendar/CalendarRegression.java
index 7bce6e6..592746c 100644
--- a/src/com/ibm/icu/dev/test/calendar/CalendarRegression.java
+++ b/src/com/ibm/icu/dev/test/calendar/CalendarRegression.java
@@ -1,6 +1,6 @@
/**
*******************************************************************************
- * Copyright (C) 2000-2008, International Business Machines Corporation and *
+ * Copyright (C) 2000-2009, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
@@ -770,13 +770,13 @@
public void Test4108764() {
java.util.Calendar tempcal = java.util.Calendar.getInstance();
tempcal.clear();
- tempcal.set(1997, Calendar.MARCH, 15, 12, 00, 00);
+ tempcal.set(1997, Calendar.FEBRUARY, 15, 12, 00, 00);
Date d00 = tempcal.getTime();
- tempcal.set(1997, Calendar.MARCH, 15, 12, 00, 56);
+ tempcal.set(1997, Calendar.FEBRUARY, 15, 12, 00, 56);
Date d01 = tempcal.getTime();
- tempcal.set(1997, Calendar.MARCH, 15, 12, 34, 00);
+ tempcal.set(1997, Calendar.FEBRUARY, 15, 12, 34, 00);
Date d10 = tempcal.getTime();
- tempcal.set(1997, Calendar.MARCH, 15, 12, 34, 56);
+ tempcal.set(1997, Calendar.FEBRUARY, 15, 12, 34, 56);
Date d11 = tempcal.getTime();
tempcal.set(1997, Calendar.JANUARY, 15, 12, 34, 56);
Date dM = tempcal.getTime();
diff --git a/src/com/ibm/icu/dev/test/calendar/CompatibilityTest.java b/src/com/ibm/icu/dev/test/calendar/CompatibilityTest.java
index e77bf83..4762fb8 100644
--- a/src/com/ibm/icu/dev/test/calendar/CompatibilityTest.java
+++ b/src/com/ibm/icu/dev/test/calendar/CompatibilityTest.java
@@ -1,6 +1,6 @@
/**
*******************************************************************************
- * Copyright (C) 2000-2008, International Business Machines Corporation and *
+ * Copyright (C) 2000-2009, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
@@ -339,9 +339,9 @@
}
cal.clear();
- cal.set(1985, 3, 2, 11, 49);
+ cal.set(1985, 2, 2, 11, 49);
tempcal.clear();
- tempcal.set(1985, 3, 2, 11, 49);
+ tempcal.set(1985, 2, 2, 11, 49);
if (cal.getTime().getTime() != tempcal.getTime().getTime()) {
errln("FAIL: Calendar.set(5 args) failed");
logln(" Got: " + cal.getTime() + " Expected: " + tempcal.getTime());
diff --git a/src/com/ibm/icu/dev/test/calendar/HolidayTest.java b/src/com/ibm/icu/dev/test/calendar/HolidayTest.java
index 863cde3..5611e26 100644
--- a/src/com/ibm/icu/dev/test/calendar/HolidayTest.java
+++ b/src/com/ibm/icu/dev/test/calendar/HolidayTest.java
@@ -19,6 +19,7 @@
import com.ibm.icu.util.RangeDateRule;
import com.ibm.icu.util.SimpleDateRule;
import com.ibm.icu.util.SimpleHoliday;
+import com.ibm.icu.util.ULocale;
/**
* Tests for the <code>Holiday</code> class.
@@ -208,4 +209,19 @@
logln("firstAfter: " + h);
}
}
+
+ public void TestDisplayName() {
+ Holiday[] holidays = Holiday.getHolidays(ULocale.US);
+ for (int i = 0; i < holidays.length; ++i) {
+ Holiday h = holidays[i];
+ // only need to test one
+ // if the display names differ, we're using our data. We know these names
+ // should differ for this holiday (not all will).
+ if ("Christmas".equals(h.getDisplayName(ULocale.US))) {
+ if ("Christmas".equals(h.getDisplayName(ULocale.GERMANY))) {
+ errln("Using default name for holidays");
+ }
+ }
+ }
+ }
}
diff --git a/src/com/ibm/icu/dev/test/charset/TestConversion.java b/src/com/ibm/icu/dev/test/charset/TestConversion.java
index a842d50..4b18d18 100644
--- a/src/com/ibm/icu/dev/test/charset/TestConversion.java
+++ b/src/com/ibm/icu/dev/test/charset/TestConversion.java
@@ -214,7 +214,7 @@
} catch (Exception e) {
// TODO implement loading of test data.
- if (skipIfBeforeICU(4,0,0)) {
+ if (skipIfBeforeICU(4,1,0)) {
logln("Skipping test:(" + cc.charset + ") due to ICU Charset not supported at this time");
} else {
errln(cc.charset + " was not found");
@@ -498,7 +498,7 @@
} catch (Exception e) {
// TODO implement loading of test data.
- if (skipIfBeforeICU(4,0,0)) {
+ if (skipIfBeforeICU(4,1,0)) {
logln("Skipping test:(" + cc.charset + ") due to ICU Charset not supported at this time");
} else {
errln(cc.charset + " was not found");
@@ -1095,16 +1095,38 @@
output.limit(output.position());
output.rewind();
+//TODO: Fix Me! After Ticket#6583 is completed, this code should be removed.
+ boolean ignoreError = (0 <= cc.caseNr && cc.caseNr <= 15) || cc.caseNr == 17 || cc.caseNr == 18;
+//TODO: End
+
// test to see if the conversion matches actual results
if (output.limit() != expected.length()) {
- errln("Test failed: output length does not match expected for charset: "+cc.charset+ " [" + cc.caseNr + "]");
- res = false;
+//TODO: Remove this
+ if (ignoreError) {
+ logln("Test failed: output length does not match expected for charset: "+cc.charset+ " [" + cc.caseNr + "]");
+ } else {
+ errln("Test failed: output length does not match expected for charset: "+cc.charset+ " [" + cc.caseNr + "]");
+ res = false;
+ }
+//TODO: End
+// errln("Test failed: output length does not match expected for charset: "+cc.charset+ " [" + cc.caseNr + "]");
+// res = false;
} else {
for (int i = 0; i < expected.length(); i++) {
if (output.get(i) != expected.charAt(i)) {
- errln("Test failed: output does not match expected for charset: " + cc.charset
- + " [" + cc.caseNr + "]");
- res = false;
+//TODO: Remove this
+ if (ignoreError) {
+ logln("Test failed: output does not match expected for charset: " + cc.charset
+ + " [" + cc.caseNr + "]");
+ } else {
+ errln("Test failed: output does not match expected for charset: " + cc.charset
+ + " [" + cc.caseNr + "]");
+ res = false;
+ }
+//TODO: End
+// errln("Test failed: output does not match expected for charset: " + cc.charset
+// + " [" + cc.caseNr + "]");
+// res = false;
break;
}
}
diff --git a/src/com/ibm/icu/dev/test/duration/ICUDurationTest.java b/src/com/ibm/icu/dev/test/duration/ICUDurationTest.java
index aa5d79d..0058a9d 100644
--- a/src/com/ibm/icu/dev/test/duration/ICUDurationTest.java
+++ b/src/com/ibm/icu/dev/test/duration/ICUDurationTest.java
@@ -236,4 +236,8 @@
}
}
+ public void TestResourceWithCalendar() {
+ DurationFormat df = DurationFormat.getInstance(new ULocale("th@calendar=buddhist"));
+ // should pass, but return a default formatter for th.
+ }
}
diff --git a/src/com/ibm/icu/dev/test/format/DateIntervalFormatTest.java b/src/com/ibm/icu/dev/test/format/DateIntervalFormatTest.java
index 01bc3c9..f684c02 100644
--- a/src/com/ibm/icu/dev/test/format/DateIntervalFormatTest.java
+++ b/src/com/ibm/icu/dev/test/format/DateIntervalFormatTest.java
@@ -627,9 +627,7 @@
}
DateInterval dtitv = new DateInterval(date.getTime(),
date_2.getTime());
-
String oneSkeleton = data[i++];
-
DateIntervalFormat dtitvfmt = DateIntervalFormat.getInstance(
oneSkeleton, loc);
String expected = data[i++];
diff --git a/src/com/ibm/icu/dev/test/format/DateTimeGeneratorTest.java b/src/com/ibm/icu/dev/test/format/DateTimeGeneratorTest.java
index 7847429..491ceb2 100644
--- a/src/com/ibm/icu/dev/test/format/DateTimeGeneratorTest.java
+++ b/src/com/ibm/icu/dev/test/format/DateTimeGeneratorTest.java
@@ -212,7 +212,7 @@
if (GENERATE_TEST_DATA) {
logln("new String[] {\"" + testSkeleton + "\", \"" + Utility.escape(formatted) + "\"},");
} else if (!formatted.equals(testFormatted)) {
- if(skipIfBeforeICU(4,0,0)&& uLocale.equals("zh_Hans_CN") && testSkeleton.equals("HHmm")){
+ if(skipIfBeforeICU(4,1,0)&& uLocale.equals("zh_Hans_CN") && testSkeleton.equals("HHmm")){
logln(uLocale + "\tformatted string doesn't match test case: " + testSkeleton + "\t generated: " + pattern + "\t expected: " + testFormatted + "\t got: " + formatted);
continue;
}
@@ -391,7 +391,7 @@
DateOrder order2 = getOrdering(style2, uLocale);
if (!order1.hasSameOrderAs(order2)) {
if (order1.monthLength == order2.monthLength) { // error if have same month length, different ordering
- if (skipIfBeforeICU(4,0,0)) {
+ if (skipIfBeforeICU(4,1,0)) {
logln(showOrderComparison(uLocale, style1, style2, order1, order2));
} else {
errln(showOrderComparison(uLocale, style1, style2, order1, order2));
diff --git a/src/com/ibm/icu/dev/test/format/RBNFParseTest.java b/src/com/ibm/icu/dev/test/format/RBNFParseTest.java
index e26c93b..b8c60be 100644
--- a/src/com/ibm/icu/dev/test/format/RBNFParseTest.java
+++ b/src/com/ibm/icu/dev/test/format/RBNFParseTest.java
@@ -1,12 +1,13 @@
/*
*******************************************************************************
- * Copyright (C) 2004, International Business Machines Corporation and *
+ * Copyright (C) 2004-2008, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
package com.ibm.icu.dev.test.format;
import com.ibm.icu.text.RuleBasedNumberFormat;
+import com.ibm.icu.util.ULocale;
import com.ibm.icu.dev.test.TestFmwk;
import java.util.Locale;
@@ -98,4 +99,59 @@
}
}
}
+
+ private void parseFormat(RuleBasedNumberFormat rbnf, String s, String target) {
+ try {
+ Number n = rbnf.parse(s);
+ String t = rbnf.format(n);
+ assertEquals(rbnf.getLocale(ULocale.ACTUAL_LOCALE) + ": " + s + " : " + n, target, t);
+ } catch (java.text.ParseException e){
+ fail("exception:" + e);
+ }
+ }
+
+ private void parseList(RuleBasedNumberFormat rbnf_en, RuleBasedNumberFormat rbnf_fr, String[][] lists) {
+ for (int i = 0; i < lists.length; ++i) {
+ String[] list = lists[i];
+ String s = list[0];
+ String target_en = list[1];
+ String target_fr = list[2];
+
+ parseFormat(rbnf_en, s, target_en);
+ parseFormat(rbnf_fr, s, target_fr);
+ }
+ }
+
+ public void TestLenientParse() throws Exception {
+ RuleBasedNumberFormat rbnf_en, rbnf_fr;
+
+ rbnf_en = new RuleBasedNumberFormat(Locale.ENGLISH, RuleBasedNumberFormat.SPELLOUT);
+ rbnf_en.setLenientParseMode(true);
+ rbnf_fr = new RuleBasedNumberFormat(Locale.FRENCH, RuleBasedNumberFormat.SPELLOUT);
+ rbnf_fr.setLenientParseMode(true);
+
+ Number n = rbnf_en.parse("1,2 million");
+ logln(n.toString());
+
+ String[][] lists = {
+ { "1,2", "twelve", "un virgule deux" },
+ { "1,2 million", "twelve million", "un million deux cents mille" },
+ { "1.2", "one point two", "douze" },
+// TODO: We'll update the English RBNF rule later
+// { "1.2 million", "one million two hundred thousand", "douze million" },
+ { "1.2 million", "one million, two hundred thousand, zero", "douze million" },
+ };
+
+ Locale.setDefault(Locale.FRANCE);
+ logln("Default locale:" + Locale.getDefault());
+ logln("rbnf_en:" + rbnf_en.getDefaultRuleSetName());
+ logln("rbnf_fr:" + rbnf_en.getDefaultRuleSetName());
+ parseList(rbnf_en, rbnf_fr, lists);
+
+ Locale.setDefault(Locale.US);
+ logln("Default locale:" + Locale.getDefault());
+ logln("rbnf_en:" + rbnf_en.getDefaultRuleSetName());
+ logln("rbnf_fr:" + rbnf_en.getDefaultRuleSetName());
+ parseList(rbnf_en, rbnf_fr, lists);
+ }
}
diff --git a/src/com/ibm/icu/dev/test/format/TestMessageFormat.java b/src/com/ibm/icu/dev/test/format/TestMessageFormat.java
index 0071289..f93be13 100644
--- a/src/com/ibm/icu/dev/test/format/TestMessageFormat.java
+++ b/src/com/ibm/icu/dev/test/format/TestMessageFormat.java
@@ -1293,6 +1293,27 @@
}
}
+ // Test case for null arguments.
+ // Ticket#6361
+ public void TestNullArgs() {
+ MessageFormat msgfmt = new MessageFormat("{0} - {1}");
+ Object[][] TEST_CASES = {
+ {null, "{0} - {1}"},
+ {new Object[] {null}, "null - {1}"},
+ {new Object[] {null, null}, "null - null"},
+ {new Object[] {"one"}, "one - {1}"},
+ {new Object[] {"one", null}, "one - null"},
+ {new Object[] {null, "two"}, "null - two"},
+ };
+
+ for (int i = 0; i < TEST_CASES.length; i++) {
+ String text = msgfmt.format(TEST_CASES[i][0]);
+ if (!text.equals(TEST_CASES[i][1])) {
+ errln("FAIL: Returned[" + text + "] Expected[" + TEST_CASES[i][1] + "]");
+ }
+ }
+ }
+
//#if defined(FOUNDATION10) || defined(J2SE13)
//#else
// Test case for formatToCharacterIterator
diff --git a/src/com/ibm/icu/dev/test/timezone/TimeZoneBoundaryTest.java b/src/com/ibm/icu/dev/test/timezone/TimeZoneBoundaryTest.java
index 85a5a3c..9049e50 100644
--- a/src/com/ibm/icu/dev/test/timezone/TimeZoneBoundaryTest.java
+++ b/src/com/ibm/icu/dev/test/timezone/TimeZoneBoundaryTest.java
@@ -1,6 +1,6 @@
/**
*******************************************************************************
- * Copyright (C) 2000-2005, International Business Machines Corporation and *
+ * Copyright (C) 2000-2009, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
@@ -430,7 +430,13 @@
TimeZone.setDefault(save);
}
- if (true)
+ // We no longer use ICU TimeZone implementation for Java
+ // default TimeZone. Java 1.3 or older version do not
+ // support historic transitions, therefore, the test below
+ // will fail on such environment (with the latest TimeZone
+ // patch for US 2007+ rule).
+ String javaver = System.getProperty("java.version", "1.3");
+ if (!javaver.startsWith("1.3"))
{
// This only works in PST/PDT
TimeZone.setDefault(safeGetTimeZone("PST"));
diff --git a/src/com/ibm/icu/dev/test/timezone/TimeZoneTest.java b/src/com/ibm/icu/dev/test/timezone/TimeZoneTest.java
index bc51f0e..4ff9c13 100644
--- a/src/com/ibm/icu/dev/test/timezone/TimeZoneTest.java
+++ b/src/com/ibm/icu/dev/test/timezone/TimeZoneTest.java
@@ -1,6 +1,6 @@
/**
*******************************************************************************
- * Copyright (C) 2000-2008, International Business Machines Corporation and *
+ * Copyright (C) 2000-2009, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
@@ -15,7 +15,6 @@
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.Date;
-import java.util.Hashtable;
import java.util.List;
import java.util.Locale;
@@ -105,7 +104,50 @@
*/
public void TestShortZoneIDs() throws Exception {
- ZoneDescriptor[] JDK_116_REFERENCE_LIST = {
+ // TODO: This test case is tzdata sensitive.
+ // We should actually put the data version in this test code
+ // at build time. For now, we just hardcode the version string
+ // and display warning instead of error if non-reference tzdata
+ // version is used.
+ final String REFERENCE_DATA_VERSION = "2008i";
+
+ boolean isNonReferenceTzdataVersion = false;
+ String tzdataVer = TimeZone.getTZDataVersion();
+ if (!tzdataVer.equals(REFERENCE_DATA_VERSION)) {
+ // Note: We want to display a warning message here if
+ // REFERENCE_DATA_VERSION is out of date - so we
+ // do not forget to update the value before GA.
+ isNonReferenceTzdataVersion = true;
+ logln("Warning: Active tzdata version (" + tzdataVer +
+ ") does not match the reference tzdata version ("
+ + REFERENCE_DATA_VERSION + ") for this test case data.");
+ }
+
+ // Note: If the default TimeZone type is JDK, some time zones
+ // may differ from the test data below. For example, "MST" on
+ // IBM JRE is an alias of "America/Denver" for supporting Java 1.1
+ // backward compatibility, while Olson tzdata (and ICU) treat it
+ // as -7hour fixed offset/no DST.
+ boolean isJDKTimeZone = (TimeZone.getDefaultTimeZoneType() == TimeZone.TIMEZONE_JDK);
+ if (isJDKTimeZone) {
+ logln("Warning: Using JDK TimeZone. Some test cases may not return expected results.");
+ }
+
+ // Note: useDaylightTime returns true if DST is observed
+ // in the time zone in the current calendar year. The test
+ // data is valid for the date after the reference year below.
+ // If system clock is before the year, some test cases may
+ // fail.
+ final int REFERENCE_YEAR = 2009;
+ GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone("Etc/GMT"));
+ cal.set(REFERENCE_YEAR, Calendar.JANUARY, 2); // day 2 in GMT
+
+ boolean isDateBeforeReferenceYear = System.currentTimeMillis() < cal.getTimeInMillis();
+ if (isDateBeforeReferenceYear) {
+ logln("Warning: Past time is set to the system clock. Some test cases may not return expected results.");
+ }
+
+ ZoneDescriptor[] REFERENCE_LIST = {
new ZoneDescriptor("MIT", -660, false),
new ZoneDescriptor("HST", -600, false),
new ZoneDescriptor("AST", -540, true),
@@ -119,22 +161,16 @@
new ZoneDescriptor("CNT", -210, true),
new ZoneDescriptor("AGT", -180, true), // updated by tzdata 2007k
new ZoneDescriptor("BET", -180, true),
- // new ZoneDescriptor("CAT", -60, false), // Wrong:
- // As of bug 4130885, fix CAT (Central Africa)
- new ZoneDescriptor("CAT", 120, false), // Africa/Harare
new ZoneDescriptor("GMT", 0, false),
new ZoneDescriptor("UTC", 0, false),
new ZoneDescriptor("ECT", 60, true),
+ new ZoneDescriptor("MET", 60, true),
+ new ZoneDescriptor("CAT", 120, false), // Africa/Harare
new ZoneDescriptor("ART", 120, true),
new ZoneDescriptor("EET", 120, true),
new ZoneDescriptor("EAT", 180, false),
- // new ZoneDescriptor("MET", 210, true),
- // This is a standard Unix zone, so don't remap it - Liu 3Jan01
- // new ZoneDescriptor("NET", 240, false);
- // As of bug 4191164, fix NET
new ZoneDescriptor("NET", 240, true),
- // PLT behaves differently under different JDKs, so we don't check it
- // new ZoneDescriptor("PLT", 300, true), // updated by tzdata 2008c
+ new ZoneDescriptor("PLT", 300, false), // updated by tzdata 2008c - no DST after 2008
new ZoneDescriptor("IST", 330, false),
new ZoneDescriptor("BST", 360, false),
new ZoneDescriptor("VST", 420, false),
@@ -143,37 +179,39 @@
new ZoneDescriptor("ACT", 570, false), // updated Oct 2003 aliu
new ZoneDescriptor("AET", 600, true),
new ZoneDescriptor("SST", 660, false),
- // new ZoneDescriptor("NST", 720, false),
- // As of bug 4130885, fix NST (New Zealand)
new ZoneDescriptor("NST", 720, true), // Pacific/Auckland
- // [3Jan01 Liu] Three of these zones have been updated.
- // The CTT and ACT zones just remap to Asia/Shanghai
- // and Australia/Darwin. Since those zones have changed,
- // I have updated the table. The MET zone used to be mapped
- // to Asia/Tehran but since MET is a standard Unix zone named
- // in the source data we no longer do this in icu or icu4j.
+ new ZoneDescriptor("Etc/Unknown", 0, false),
+ new ZoneDescriptor("SystemV/AST4ADT", -240, true),
+ new ZoneDescriptor("SystemV/EST5EDT", -300, true),
+ new ZoneDescriptor("SystemV/CST6CDT", -360, true),
+ new ZoneDescriptor("SystemV/MST7MDT", -420, true),
+ new ZoneDescriptor("SystemV/PST8PDT", -480, true),
+ new ZoneDescriptor("SystemV/YST9YDT", -540, true),
+ new ZoneDescriptor("SystemV/AST4", -240, false),
+ new ZoneDescriptor("SystemV/EST5", -300, false),
+ new ZoneDescriptor("SystemV/CST6", -360, false),
+ new ZoneDescriptor("SystemV/MST7", -420, false),
+ new ZoneDescriptor("SystemV/PST8", -480, false),
+ new ZoneDescriptor("SystemV/YST9", -540, false),
+ new ZoneDescriptor("SystemV/HST10", -600, false),
};
- Hashtable hash = new Hashtable();
-
- String[] ids = TimeZone.getAvailableIDs();
- for (int i=0; i<ids.length; ++i) {
- String id = ids[i];
- if (id.length() == 3) {
- hash.put(id, new ZoneDescriptor(TimeZone.getTimeZone(id)));
- }
- }
-
- for (int i=0; i<JDK_116_REFERENCE_LIST.length; ++i) {
- ZoneDescriptor referenceZone = JDK_116_REFERENCE_LIST[i];
- ZoneDescriptor currentZone = (ZoneDescriptor)hash.get(referenceZone.getID());
+ for (int i=0; i<REFERENCE_LIST.length; ++i) {
+ ZoneDescriptor referenceZone = REFERENCE_LIST[i];
+ ZoneDescriptor currentZone = new ZoneDescriptor(TimeZone.getTimeZone(referenceZone.getID()));
if (referenceZone.equals(currentZone)) {
logln("ok " + referenceZone);
}
else {
- warnln("Fail: Expected " + referenceZone +
- "; got " + currentZone);
+ if (isNonReferenceTzdataVersion
+ || isJDKTimeZone || isDateBeforeReferenceYear) {
+ logln("Warning: Expected " + referenceZone +
+ "; got " + currentZone);
+ } else {
+ errln("Fail: Expected " + referenceZone +
+ "; got " + currentZone);
+ }
}
}
}
@@ -1416,6 +1454,134 @@
}
}
}
+
+ public void TestSetDefault() {
+ java.util.TimeZone save = java.util.TimeZone.getDefault();
+
+ /*
+ * America/Caracs (Venezuela) changed the base offset from -4:00 to
+ * -4:30 on Dec 9, 2007.
+ */
+
+ TimeZone icuCaracas = TimeZone.getTimeZone("America/Caracas", TimeZone.TIMEZONE_ICU);
+ java.util.TimeZone jdkCaracas = java.util.TimeZone.getTimeZone("America/Caracas");
+
+ // Set JDK America/Caracas as the default
+ java.util.TimeZone.setDefault(jdkCaracas);
+
+ java.util.Calendar jdkCal = java.util.Calendar.getInstance();
+ jdkCal.clear();
+ jdkCal.set(2007, java.util.Calendar.JANUARY, 1);
+
+ int rawOffset = jdkCal.get(java.util.Calendar.ZONE_OFFSET);
+ int dstSavings = jdkCal.get(java.util.Calendar.DST_OFFSET);
+
+ int[] offsets = new int[2];
+ icuCaracas.getOffset(jdkCal.getTime().getTime(), false, offsets);
+
+ boolean isTimeZoneSynchronized = true;
+
+ if (rawOffset != offsets[0] || dstSavings != offsets[1]) {
+ // JDK time zone rule is out of sync...
+ logln("Rule for JDK America/Caracas is not same with ICU. Skipping the rest.");
+ isTimeZoneSynchronized = false;
+ }
+
+ if (isTimeZoneSynchronized) {
+ // If JDK America/Caracas uses the same rule with ICU,
+ // the following code should work well.
+ TimeZone.setDefault(icuCaracas);
+
+ // Create a new JDK calendar instance again.
+ // This calendar should reflect the new default
+ // set by ICU TimeZone#setDefault.
+ jdkCal = java.util.Calendar.getInstance();
+ jdkCal.clear();
+ jdkCal.set(2007, java.util.Calendar.JANUARY, 1);
+
+ rawOffset = jdkCal.get(java.util.Calendar.ZONE_OFFSET);
+ dstSavings = jdkCal.get(java.util.Calendar.DST_OFFSET);
+
+ if (rawOffset != offsets[0] || dstSavings != offsets[1]) {
+ errln("ERROR: Got offset [raw:" + rawOffset + "/dst:" + dstSavings
+ + "] Expected [raw:" + offsets[0] + "/dst:" + offsets[1] + "]");
+ }
+ }
+
+ // Restore the original JDK time zone
+ java.util.TimeZone.setDefault(save);
+ }
+
+ /*
+ * Test Display Names, choosing zones and lcoales where there are multiple
+ * meta-zones defined.
+ */
+ public void TestDisplayNamesMeta() {
+ final Integer TZSHORT = new Integer(TimeZone.SHORT);
+ final Integer TZLONG = new Integer(TimeZone.LONG);
+
+ final Object[][] zoneDisplayTestData = {
+ // zone id locale summer format expected display name
+ {"Europe/London", "en", Boolean.FALSE, TZSHORT, "GMT"},
+ {"Europe/London", "en", Boolean.FALSE, TZLONG, "Greenwich Mean Time"},
+ {"Europe/London", "en", Boolean.TRUE, TZSHORT, "GMT+01:00" /*"BST"*/},
+ {"Europe/London", "en", Boolean.TRUE, TZLONG, "British Summer Time"},
+
+ {"America/Anchorage", "en", Boolean.FALSE, TZSHORT, "AKST"},
+ {"America/Anchorage", "en", Boolean.FALSE, TZLONG, "Alaska Standard Time"},
+ {"America/Anchorage", "en", Boolean.TRUE, TZSHORT, "AKDT"},
+ {"America/Anchorage", "en", Boolean.TRUE, TZLONG, "Alaska Daylight Time"},
+
+ // Southern Hemisphere, all data from meta:Australia_Western
+ {"Australia/Perth", "en", Boolean.FALSE, TZSHORT, "GMT+08:00"/*"AWST"*/},
+ {"Australia/Perth", "en", Boolean.FALSE, TZLONG, "Australian Western Standard Time"},
+ {"Australia/Perth", "en", Boolean.TRUE, TZSHORT, "GMT+09:00"/*"AWDT"*/},
+ {"Australia/Perth", "en", Boolean.TRUE, TZLONG, "Australian Western Daylight Time"},
+
+ {"America/Sao_Paulo", "en", Boolean.FALSE, TZSHORT, "GMT-03:00"/*"BRT"*/},
+ {"America/Sao_Paulo", "en", Boolean.FALSE, TZLONG, "Brasilia Time"},
+ {"America/Sao_Paulo", "en", Boolean.TRUE, TZSHORT, "GMT-02:00"/*"BRST"*/},
+ {"America/Sao_Paulo", "en", Boolean.TRUE, TZLONG, "Brasilia Summer Time"},
+
+ // No Summer Time, but had it before 1983.
+ {"Pacific/Honolulu", "en", Boolean.FALSE, TZSHORT, "HST"},
+ {"Pacific/Honolulu", "en", Boolean.FALSE, TZLONG, "Hawaii-Aleutian Standard Time"},
+ {"Pacific/Honolulu", "en", Boolean.TRUE, TZSHORT, "HST"},
+ {"Pacific/Honolulu", "en", Boolean.TRUE, TZLONG, "Hawaii-Aleutian Standard Time"},
+
+ // Northern, has Summer, not commonly used.
+ {"Europe/Helsinki", "en", Boolean.FALSE, TZSHORT, "GMT+02:00"/*"EET"*/},
+ {"Europe/Helsinki", "en", Boolean.FALSE, TZLONG, "Eastern European Time"},
+ {"Europe/Helsinki", "en", Boolean.TRUE, TZSHORT, "GMT+03:00"/*"EEST"*/},
+ {"Europe/Helsinki", "en", Boolean.TRUE, TZLONG, "Eastern European Summer Time"},
+
+ // Repeating the test data for DST. The test data below trigger the problem reported
+ // by Ticket#6644
+ {"Europe/London", "en", Boolean.TRUE, TZSHORT, "GMT+01:00" /*"BST"*/},
+ {"Europe/London", "en", Boolean.TRUE, TZLONG, "British Summer Time"},
+ };
+
+ boolean sawAnError = false;
+ for (int testNum = 0; testNum < zoneDisplayTestData.length; testNum++) {
+ ULocale locale = new ULocale((String)zoneDisplayTestData[testNum][1]);
+ TimeZone zone = TimeZone.getTimeZone((String)zoneDisplayTestData[testNum][0]);
+ String displayName = zone.getDisplayName(((Boolean)zoneDisplayTestData[testNum][2]).booleanValue(),
+ ((Integer)zoneDisplayTestData[testNum][3]).intValue());
+ if (!displayName.equals(zoneDisplayTestData[testNum][4])) {
+ sawAnError = true;
+ errln("Incorrect time zone display name. zone = "
+ + zoneDisplayTestData[testNum][0] + ",\n"
+ + " locale = " + locale
+ + ", style = " + (zoneDisplayTestData[testNum][3] == TZSHORT ? "SHORT" : "LONG")
+ + ", Summertime = " + zoneDisplayTestData[testNum][2] + "\n"
+ + " Expected " + zoneDisplayTestData[testNum][4]
+ + ", Got " + displayName);
+ }
+ }
+ if (sawAnError) {
+ errln("Note: Errors could be the result of changes to zoneStrings locale data");
+ }
+ }
}
//eof
diff --git a/src/com/ibm/icu/dev/test/translit/RoundTripTest.java b/src/com/ibm/icu/dev/test/translit/RoundTripTest.java
index 4960390..6505481 100644
--- a/src/com/ibm/icu/dev/test/translit/RoundTripTest.java
+++ b/src/com/ibm/icu/dev/test/translit/RoundTripTest.java
@@ -206,7 +206,7 @@
String getGreekSet() {
// Time bomb
- if (skipIfBeforeICU(4,0,0)) {
+ if (skipIfBeforeICU(4,1,0)) {
// We temporarily filter against Unicode 4.1, but we only do this
// before version 3.5.
logln("TestGreek needs to be updated to remove delete the section marked [:Age=4.0:] filter");
@@ -268,7 +268,7 @@
public void TestHebrew() throws IOException {
// Time bomb
- if (skipIfBeforeICU(4,0,0)) {
+ if (skipIfBeforeICU(4,1,0)) {
// We temporarily filter against Unicode 4.1, but we only do this
// before version 3.5.
logln("TestHebrew needs to be updated to remove delete the section marked [:Age=4.0:] filter");
@@ -283,7 +283,7 @@
public void TestThai() throws IOException {
long start = System.currentTimeMillis();
- if(skipIfBeforeICU(4,0,0)){
+ if(skipIfBeforeICU(4,1,0)){
new Test("Latin-Thai")
.test("[a-zA-Z\u0142\u1ECD\u00E6\u0131\u0268\u02CC]",
"[\u0E01-\u0E3A\u0E40-\u0E5B]",
@@ -370,7 +370,7 @@
.test(latinForIndic, "[[:Devanagari:][\u094d][\u0964\u0965] & [:Age=3.2:]]", "[\u0965]", this, new LegalIndic());
}else{
- if (skipIfBeforeICU(4,0,0)) {
+ if (skipIfBeforeICU(4,1,0)) {
logln("Warning: TestDevanagariLatin needs to be updated to remove delete the section marked [:Age=4.1:] filter");
} else {
// We temporarily filter against Unicode 4.1, but we only do this
@@ -744,7 +744,7 @@
logln("Testing only 5 of "+ interIndicArray.length+" Skipping rest (use -e for exhaustive)");
num = 5;
}
- if (skipIfBeforeICU(4,0,0)) {
+ if (skipIfBeforeICU(4,1,0)) {
logln("Warning: TestInterIndic needs to be updated to remove delete the section marked [:Age=4.1:] filter");
} else {
// We temporarily filter against Unicode 4.1, but we only do this
diff --git a/src/com/ibm/icu/dev/test/util/DebugUtilitiesData.java b/src/com/ibm/icu/dev/test/util/DebugUtilitiesData.java
index 490fb1d..17d0d31 100644
--- a/src/com/ibm/icu/dev/test/util/DebugUtilitiesData.java
+++ b/src/com/ibm/icu/dev/test/util/DebugUtilitiesData.java
@@ -5,7 +5,7 @@
package com.ibm.icu.dev.test.util;
public class DebugUtilitiesData extends Object {
- public static final String ICU4C_VERSION="4.0";
+ public static final String ICU4C_VERSION="4.0.1";
public static final int UDebugEnumType = 0;
public static final int UCalendarDateFields = 1;
public static final int UCalendarMonths = 2;
diff --git a/src/com/ibm/icu/dev/test/util/ULocaleTest.java b/src/com/ibm/icu/dev/test/util/ULocaleTest.java
index 8fbe03f..80435de 100644
--- a/src/com/ibm/icu/dev/test/util/ULocaleTest.java
+++ b/src/com/ibm/icu/dev/test/util/ULocaleTest.java
@@ -1,6 +1,6 @@
/*
**********************************************************************
-* Copyright (c) 2004-2008, International Business Machines
+* Copyright (c) 2004-2009, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
* Author: Alan Liu
@@ -231,10 +231,23 @@
Locale.setDefault(backupDefault);
// Set default via ULocale
- ULocale.setDefault(new ULocale("ja_JP@calendar=japanese"));
+ ULocale ujaJP_calJP = new ULocale("ja_JP@calendar=japanese");
+ ULocale.setDefault(ujaJP_calJP);
if (!Locale.getDefault().equals(jaJPJP)) {
errln("FAIL: ULocale#setDefault failed to set Java Locale ja_JP_JP /actual: " + Locale.getDefault());
}
+ // Ticket#6672 - missing keywords
+ defUloc = ULocale.getDefault();
+ if (!defUloc.equals(ujaJP_calJP)) {
+ errln("FAIL: ULocale#getDefault returned " + defUloc + " /expected: ja_JP@calendar=japanese");
+ }
+ // Set a incompatible base locale via Locale#setDefault
+ Locale.setDefault(Locale.US);
+ defUloc = ULocale.getDefault();
+ if (defUloc.equals(ujaJP_calJP)) {
+ errln("FAIL: ULocale#getDefault returned " + defUloc + " /expected: " + ULocale.forLocale(Locale.US));
+ }
+
Locale.setDefault(backupDefault);
// We also want to map ICU locale ja@calendar=japanese to Java ja_JP_JP
diff --git a/src/com/ibm/icu/dev/tool/docs/icu4j400.api.gz b/src/com/ibm/icu/dev/tool/docs/icu4j400.api.gz
new file mode 100644
index 0000000..d655870
--- /dev/null
+++ b/src/com/ibm/icu/dev/tool/docs/icu4j400.api.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:75ece13e19c149456a6b86a13a0eab9bb851f2adb7119383c72e2ae3161c00c1
+size 31554
diff --git a/src/com/ibm/icu/impl/data/icudata.jar b/src/com/ibm/icu/impl/data/icudata.jar
index ee66726..19b5928 100755
--- a/src/com/ibm/icu/impl/data/icudata.jar
+++ b/src/com/ibm/icu/impl/data/icudata.jar
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:ab6c0a54519c1a1a78e8db91ebb73444e61c34f2524771a013f5ad8f8766babc
-size 6592291
+oid sha256:03c1083e0ec59571cf28e0653b038beb7f9c9ba5ebf82630b40dc52f32f61373
+size 6604371
diff --git a/src/com/ibm/icu/impl/duration/impl/ResourceBasedPeriodFormatterDataService.java b/src/com/ibm/icu/impl/duration/impl/ResourceBasedPeriodFormatterDataService.java
index 944573f..f3ac48e 100644
--- a/src/com/ibm/icu/impl/duration/impl/ResourceBasedPeriodFormatterDataService.java
+++ b/src/com/ibm/icu/impl/duration/impl/ResourceBasedPeriodFormatterDataService.java
@@ -74,6 +74,12 @@
}
public PeriodFormatterData get(String localeName) {
+ // remove tag info including calendar, we don't use the calendar
+ int x = localeName.indexOf('@');
+ if (x != -1) {
+ localeName = localeName.substring(0, x);
+ }
+
synchronized(this) {
if (lastLocale != null && lastLocale.equals(localeName)) {
return lastData;
diff --git a/src/com/ibm/icu/text/DateIntervalFormat.java b/src/com/ibm/icu/text/DateIntervalFormat.java
index bca9a90..1b48562 100644
--- a/src/com/ibm/icu/text/DateIntervalFormat.java
+++ b/src/com/ibm/icu/text/DateIntervalFormat.java
@@ -285,7 +285,6 @@
// Cache for the locale interval pattern
private static ICUCache LOCAL_PATTERN_CACHE = new SimpleCache();
-
/*
* The interval patterns for this locale.
@@ -321,22 +320,6 @@
}
/*
- * Construct a DateIntervalFormat from DateFormat and a DateIntervalInfo.
- *
- * This is the convenient override of
- * DateIntervalFormat(DateFormat, DateIntervalInfo, String)
- * with the String value as null.
- *
- * @param dtfmt the SimpleDateFormat object to be adopted.
- * @param dtitvinf the DateIntervalInfo object to be adopted.
- */
- private DateIntervalFormat(DateFormat dtfmt, DateIntervalInfo dtItvInfo)
- {
- this(dtfmt, dtItvInfo, null);
- }
-
-
- /*
* Construct a DateIntervalFormat from DateFormat,
* a DateIntervalInfo, and skeleton.
* DateFormat provides the timezone, calendar,
@@ -345,20 +328,23 @@
* has a pattern in it.
* the DateIntervalInfo provides the interval patterns.
*
- * @param dtfmt the SimpleDateFormat object to be adopted.
+ * @param locale the locale of this date interval formatter.
* @param dtitvinf the DateIntervalInfo object to be adopted.
* @param skeleton the skeleton of the date formatter
*/
- private DateIntervalFormat(DateFormat dtfmt, DateIntervalInfo dtItvInfo,
+ private DateIntervalFormat(ULocale locale, DateIntervalInfo dtItvInfo,
String skeleton)
{
// freeze date interval info
dtItvInfo.freeze();
fSkeleton = skeleton;
fInfo = dtItvInfo;
- fDateFormat = (SimpleDateFormat) dtfmt;
- fFromCalendar = (Calendar) dtfmt.getCalendar().clone();
- fToCalendar = (Calendar) dtfmt.getCalendar().clone();
+
+ DateTimePatternGenerator generator = DateTimePatternGenerator.getInstance(locale);
+ final String bestPattern = generator.getBestPattern(skeleton);
+ fDateFormat = new SimpleDateFormat(bestPattern, locale);
+ fFromCalendar = (Calendar) fDateFormat.getCalendar().clone();
+ fToCalendar = (Calendar) fDateFormat.getCalendar().clone();
initializePattern();
}
@@ -435,9 +421,8 @@
public static final DateIntervalFormat
getInstance(String skeleton, ULocale locale)
{
- DateFormat dtfmt = DateFormat.getPatternInstance(skeleton, locale);
DateIntervalInfo dtitvinf = new DateIntervalInfo(locale);
- return new DateIntervalFormat(dtfmt, dtitvinf, skeleton);
+ return new DateIntervalFormat(locale, dtitvinf, skeleton);
}
@@ -528,12 +513,11 @@
ULocale locale,
DateIntervalInfo dtitvinf)
{
- DateFormat dtfmt = DateFormat.getPatternInstance(skeleton, locale);
LOCAL_PATTERN_CACHE.clear();
// clone. If it is frozen, clone returns itself, otherwise, clone
// returns a copy.
dtitvinf = (DateIntervalInfo)dtitvinf.clone();
- return new DateIntervalFormat(dtfmt, dtitvinf, skeleton);
+ return new DateIntervalFormat(locale, dtitvinf, skeleton);
}
@@ -961,9 +945,9 @@
// TODO: if user asks "m", but "d" differ
//StringBuffer skeleton = new StringBuffer(skeleton);
if ( time.length() != 0 ) {
- //genFallbackForNotFound(Calendar.MINUTE, skeleton, dtpng);
- //genFallbackForNotFound(Calendar.HOUR, skeleton, dtpng);
- //genFallbackForNotFound(Calendar.AM_PM, skeleton, dtpng);
+ //genFallbackForNotFound(Calendar.MINUTE, skeleton);
+ //genFallbackForNotFound(Calendar.HOUR, skeleton);
+ //genFallbackForNotFound(Calendar.AM_PM, skeleton);
if ( date.length() == 0 ) {
// prefix with yMd
timeSkeleton = DateFormat.YEAR_NUM_MONTH_DAY + timeSkeleton;
@@ -984,14 +968,14 @@
intervalPatterns.put(DateIntervalInfo.
CALENDAR_FIELD_TO_PATTERN_LETTER[Calendar.YEAR], ptn);
} else {
- //genFallbackForNotFound(Calendar.DATE, skeleton, dtpng);
- //genFallbackForNotFound(Calendar.MONTH, skeleton, dtpng);
- //genFallbackForNotFound(Calendar.YEAR, skeleton, dtpng);
+ //genFallbackForNotFound(Calendar.DATE, skeleton);
+ //genFallbackForNotFound(Calendar.MONTH, skeleton);
+ //genFallbackForNotFound(Calendar.YEAR, skeleton);
}
} else {
- //genFallbackForNotFound(Calendar.DATE, skeleton, dtpng);
- //genFallbackForNotFound(Calendar.MONTH, skeleton, dtpng);
- //genFallbackForNotFound(Calendar.YEAR, skeleton, dtpng);
+ //genFallbackForNotFound(Calendar.DATE, skeleton);
+ //genFallbackForNotFound(Calendar.MONTH, skeleton);
+ //genFallbackForNotFound(Calendar.YEAR, skeleton);
}
return intervalPatterns;
} // end of skeleton not found
@@ -1004,11 +988,11 @@
* for example: 10 10:10 - 11 10:10, it is not
* clear that the first 10 is the 10th day
time.insert(0, 'd');
- genFallbackPattern(Calendar.DATE, time, dtpng);
+ genFallbackPattern(Calendar.DATE, time);
time.insert(0, 'M');
- genFallbackPattern(Calendar.MONTH, time, dtpng);
+ genFallbackPattern(Calendar.MONTH, time);
time.insert(0, 'y');
- genFallbackPattern(Calendar.YEAR, time, dtpng);
+ genFallbackPattern(Calendar.YEAR, time);
*/
// prefix with yMd
timeSkeleton = DateFormat.YEAR_NUM_MONTH_DAY + timeSkeleton;
@@ -1041,19 +1025,19 @@
// prefix skeleton with 'd'
skeleton = DateIntervalInfo.
CALENDAR_FIELD_TO_PATTERN_LETTER[Calendar.DATE] + skeleton;
- genFallbackPattern(Calendar.DATE, skeleton, dtpng, intervalPatterns);
+ genFallbackPattern(Calendar.DATE, skeleton, intervalPatterns, dtpng);
}
if ( !fieldExistsInSkeleton(Calendar.MONTH, dateSkeleton) ) {
// then prefix skeleton with 'M'
skeleton = DateIntervalInfo.
CALENDAR_FIELD_TO_PATTERN_LETTER[Calendar.MONTH] + skeleton;
- genFallbackPattern(Calendar.MONTH, skeleton, dtpng, intervalPatterns);
+ genFallbackPattern(Calendar.MONTH, skeleton, intervalPatterns, dtpng);
}
if ( !fieldExistsInSkeleton(Calendar.YEAR, dateSkeleton) ) {
// then prefix skeleton with 'y'
skeleton = DateIntervalInfo.
CALENDAR_FIELD_TO_PATTERN_LETTER[Calendar.YEAR] + skeleton;
- genFallbackPattern(Calendar.YEAR, skeleton, dtpng, intervalPatterns);
+ genFallbackPattern(Calendar.YEAR, skeleton, intervalPatterns, dtpng);
}
/*
@@ -1085,9 +1069,9 @@
* @param intervalPatterns interval patterns
*/
private void genFallbackPattern(int field, String skeleton,
- DateTimePatternGenerator dtpng,
- HashMap intervalPatterns) {
- String pattern =dtpng.getBestPattern(skeleton);
+ HashMap intervalPatterns,
+ DateTimePatternGenerator dtpng) {
+ String pattern = dtpng.getBestPattern(skeleton);
// for fall back interval patterns,
// the first part of the pattern is empty,
// the second part of the pattern is the full-pattern
@@ -1101,8 +1085,7 @@
/*
- private void genFallbackForNotFound(String field, StringBuffer skeleton,
- DateTimePatternGenerator dtpng) {
+ private void genFallbackForNotFound(String field, StringBuffer skeleton) {
if ( SimpleDateFormat.isFieldUnitIgnored(skeleton.toString(), field) ) {
// single date
DateIntervalInfo.PatternInfo ptnInfo =
@@ -1215,7 +1198,6 @@
++vCount;
timeSkeleton.append(ch);
break;
- // FIXME: what is the difference between CAP_V/Z and LOW_V/Z
case 'V':
case 'Z':
case 'k':
diff --git a/src/com/ibm/icu/text/DateIntervalInfo.java b/src/com/ibm/icu/text/DateIntervalInfo.java
index 98500db..9422730 100644
--- a/src/com/ibm/icu/text/DateIntervalInfo.java
+++ b/src/com/ibm/icu/text/DateIntervalInfo.java
@@ -333,7 +333,7 @@
if ( dii == null ) {
// initialize data from scratch
setup(locale);
- // FIXME: should put a clone in cache?
+ // TODO: should put a clone in cache?
// or put itself in cache?
// DIICACHE.put(key, this);
dii = (DateIntervalInfo)this.clone();
@@ -371,7 +371,7 @@
// loop through all locales to get all available skeletons'
// interval format
ULocale parentLocale = locale;
- // FIXME: how to check for root
+ // TODO: how to check for root
//while ( !parentLocale.equals(ULocale.ROOT) ) {
while (parentLocale != null && !parentLocale.equals(ULocale.ROOT)) {
String name = parentLocale.getName();
@@ -881,7 +881,7 @@
final int STRING_NUMERIC_DIFFERENCE = 0x100;
final int BASE = 0x41;
- // FIXME: hack for 'v' and 'z'
+ // TODO: this is a hack for 'v' and 'z'
// resource bundle only have time skeletons ending with 'v',
// but not for time skeletons ending with 'z'.
boolean replaceZWithV = false;
diff --git a/src/com/ibm/icu/text/DateTimePatternGenerator.java b/src/com/ibm/icu/text/DateTimePatternGenerator.java
index 7956af9..7d496ba 100644
--- a/src/com/ibm/icu/text/DateTimePatternGenerator.java
+++ b/src/com/ibm/icu/text/DateTimePatternGenerator.java
@@ -8,8 +8,10 @@
package com.ibm.icu.text;
import com.ibm.icu.impl.CalendarData;
+import com.ibm.icu.impl.ICUCache;
import com.ibm.icu.impl.ICUResourceBundle;
import com.ibm.icu.impl.PatternTokenizer;
+import com.ibm.icu.impl.SimpleCache;
import com.ibm.icu.impl.Utility;
import com.ibm.icu.util.Calendar;
import com.ibm.icu.util.Freezable;
@@ -123,7 +125,12 @@
* @stable ICU 3.6
*/
public static DateTimePatternGenerator getInstance(ULocale uLocale) {
- DateTimePatternGenerator result = new DateTimePatternGenerator();
+ String localeKey = uLocale.toString();
+ DateTimePatternGenerator result = (DateTimePatternGenerator)DTPNG_CACHE.get(localeKey);
+ if (result != null) {
+ return result;
+ }
+ result = new DateTimePatternGenerator();
String lang = uLocale.getLanguage();
if (lang.equals("zh") || lang.equals("ko") || lang.equals("ja")) {
result.chineseMonthHack = true;
@@ -221,6 +228,7 @@
// decimal point for seconds
DecimalFormatSymbols dfs = new DecimalFormatSymbols(uLocale);
result.setDecimal(String.valueOf(dfs.getDecimalSeparator()));
+ DTPNG_CACHE.put(localeKey, result);
return result;
}
@@ -1290,6 +1298,9 @@
private static final int FRACTIONAL_MASK = 1<<FRACTIONAL_SECOND;
private static final int SECOND_AND_FRACTIONAL_MASK = (1<<SECOND) | (1<<FRACTIONAL_SECOND);
+
+ // Cache for DateTimePatternGenerator
+ private static ICUCache DTPNG_CACHE = new SimpleCache();
private void checkFrozen() {
if (isFrozen()) {
diff --git a/src/com/ibm/icu/text/MessageFormat.java b/src/com/ibm/icu/text/MessageFormat.java
index 5671cd4..f3f05a6 100644
--- a/src/com/ibm/icu/text/MessageFormat.java
+++ b/src/com/ibm/icu/text/MessageFormat.java
@@ -1653,7 +1653,7 @@
result.append(pattern.substring(lastOffset, offsets[i]));
lastOffset = offsets[i];
String argumentName = argumentNames[i];
- if (arguments == null || arguments.get(argumentName) == null) {
+ if (arguments == null || !arguments.containsKey(argumentName)) {
result.append("{" + argumentName + "}");
continue;
}
diff --git a/src/com/ibm/icu/text/NFSubstitution.java b/src/com/ibm/icu/text/NFSubstitution.java
index 21bb6a8..deed4ec 100644
--- a/src/com/ibm/icu/text/NFSubstitution.java
+++ b/src/com/ibm/icu/text/NFSubstitution.java
@@ -39,6 +39,11 @@
* or null. (Either this or ruleSet has to be non-null.)
*/
DecimalFormat numberFormat = null;
+
+ /**
+ * Link to the RBNF so that we can access its decimalFormat if need be.
+ */
+ RuleBasedNumberFormat rbnf = null;
//-----------------------------------------------------------------------
// construction
@@ -158,6 +163,7 @@
String description) {
// initialize the substitution's position in its parent rule
this.pos = pos;
+ this.rbnf = formatter;
// the description should begin and end with the same character.
// If it doesn't that's a syntax error. Otherwise,
@@ -405,7 +411,7 @@
if (ruleSet != null) {
tempResult = ruleSet.parse(text, parsePosition, upperBound);
if (lenientParse && !ruleSet.isFractionSet() && parsePosition.getIndex() == 0) {
- tempResult = NumberFormat.getInstance().parse(text, parsePosition);
+ tempResult = rbnf.getDecimalFormat().parse(text, parsePosition);
}
// ...or use our DecimalFormat to parse the text
@@ -1327,7 +1333,7 @@
workPos.setIndex(0);
digit = ruleSet.parse(workText, workPos, 10).intValue();
if (lenientParse && workPos.getIndex() == 0) {
- digit = NumberFormat.getInstance().parse(workText, workPos).intValue();
+ digit = rbnf.getDecimalFormat().parse(workText, workPos).intValue();
}
if (workPos.getIndex() != 0) {
diff --git a/src/com/ibm/icu/text/RuleBasedNumberFormat.java b/src/com/ibm/icu/text/RuleBasedNumberFormat.java
index 34148c9..af5c1f2 100644
--- a/src/com/ibm/icu/text/RuleBasedNumberFormat.java
+++ b/src/com/ibm/icu/text/RuleBasedNumberFormat.java
@@ -543,6 +543,13 @@
* filled in if the rule set never uses a DecimalFormat pattern.
*/
private transient DecimalFormatSymbols decimalFormatSymbols = null;
+
+ /**
+ * The NumberFormat used when lenient parsing numbers. This needs to reflect
+ * the locale. This is lazy-evaluated, like decimalFormatSymbols. It is
+ * here so it can be shared by different NFSubstitutions.
+ */
+ private transient DecimalFormat decimalFormat = null;
/**
* Flag specifying whether lenient parse mode is on or off. Off by default.
@@ -873,6 +880,7 @@
defaultRuleSet = temp.defaultRuleSet;
publicRuleSetNames = temp.publicRuleSetNames;
decimalFormatSymbols = temp.decimalFormatSymbols;
+ decimalFormat = temp.decimalFormat;
locale = temp.locale;
}
@@ -1341,6 +1349,13 @@
}
return decimalFormatSymbols;
}
+
+ DecimalFormat getDecimalFormat() {
+ if (decimalFormat == null) {
+ decimalFormat = (DecimalFormat)NumberFormat.getInstance(locale);
+ }
+ return decimalFormat;
+ }
//-----------------------------------------------------------------------
// construction implementation
diff --git a/src/com/ibm/icu/text/TimeUnitFormat.java b/src/com/ibm/icu/text/TimeUnitFormat.java
index ebb4730..ccb5982 100644
--- a/src/com/ibm/icu/text/TimeUnitFormat.java
+++ b/src/com/ibm/icu/text/TimeUnitFormat.java
@@ -248,7 +248,7 @@
resultNumber = new Integer(2);
} else {
// should not happen.
- // FIXME: how to handle?
+ // TODO: how to handle?
resultNumber = new Integer(3);
}
}
diff --git a/src/com/ibm/icu/util/Holiday.java b/src/com/ibm/icu/util/Holiday.java
index 23b8776..0e2b646 100644
--- a/src/com/ibm/icu/util/Holiday.java
+++ b/src/com/ibm/icu/util/Holiday.java
@@ -56,7 +56,7 @@
}
/**
- * Return the first occurrance of this holiday on or after the given date
+ * Return the first occurrence of this holiday on or after the given date
*
* @param start Only holidays on or after this date are returned.
*
@@ -72,11 +72,11 @@
}
/**
- * Return the first occurrance of this holiday that is on or after
+ * Return the first occurrence of this holiday that is on or after
* the given start date and before the given end date.
*
- * @param start Only occurrances on or after this date are returned.
- * @param end Only occurrances before this date are returned.
+ * @param start Only occurrences on or after this date are returned.
+ * @param end Only occurrences before this date are returned.
*
* @return The date on which this event occurs, or null if it
* does not occur between the start and end dates.
@@ -123,7 +123,7 @@
* resource bundle object named HolidayBundle.
*
* @param rule The date rules used for determining when this holiday
- * falls. Holiday's implementation of the DateRule inteface
+ * falls. Holiday's implementation of the DateRule interface
* simply delegates to this DateRule object.
* @draft ICU 2.8
* @provisional This API might change or be removed in a future release.
@@ -135,7 +135,7 @@
}
/**
- * Return the name of this holiday in the language of the default locale
+ * Return the name of this holiday in the language of the default locale.
* @draft ICU 2.8
* @provisional This API might change or be removed in a future release.
*/
@@ -144,7 +144,7 @@
}
/**
- * Return the name of this holiday in the language of the specified locale
+ * Return the name of this holiday in the language of the specified locale.
* The <code>name</code> parameter passed to this object's constructor is used
* as a key to look up the holiday's localized name in a ResourceBundle object
* named HolidayBundle.
@@ -177,11 +177,10 @@
String dispName = name;
try {
- ResourceBundle bundle = UResourceBundle.getBundleInstance("HolidayBundle", locale);
+ ResourceBundle bundle = UResourceBundle.getBundleInstance("com.ibm.icu.impl.data.HolidayBundle", locale);
dispName = bundle.getString(name);
}
catch (MissingResourceException e) {
- //System.out.println("Using default display name for " + name);
}
return dispName;
}
diff --git a/src/com/ibm/icu/util/TimeZone.java b/src/com/ibm/icu/util/TimeZone.java
index 3d4c327..b9d3e5f 100644
--- a/src/com/ibm/icu/util/TimeZone.java
+++ b/src/com/ibm/icu/util/TimeZone.java
@@ -516,16 +516,14 @@
/**
* The public version of this API only accepts LONG/SHORT, the
* internal version (which this calls) also accepts LONG_GENERIC/SHORT_GENERIC.
- * @internal
- * @deprecated This API is ICU internal only.
*/
- private String _getDisplayName(boolean daylight, int style, ULocale locale) {
+ private synchronized String _getDisplayName(boolean daylight, int style, ULocale locale) {
/* NOTES:
* (1) We use SimpleDateFormat for simplicity; we could do this
* more efficiently but it would duplicate the SimpleDateFormat code
* here, which is undesirable.
* (2) Attempts to move the code from SimpleDateFormat to here also run
- * aground because this requires SimpleDateFormat to keep a Locale
+ * around because this requires SimpleDateFormat to keep a Locale
* object around, which it currently doesn't; to synthesize such a
* locale upon resurrection; and to somehow handle the special case of
* construction from a DateFormatSymbols object.
@@ -543,17 +541,16 @@
String[] patterns = { "z", "zzzz", "v", "vvvv" };
format.applyPattern(patterns[style]);
+ format.setTimeZone(this);
Date d = new Date();
if (style >= 2) {
// Generic names may change time to time even for a single time zone.
// This method returns the one used for the zone now.
- format.setTimeZone(this);
return format.format(d);
} else {
int[] offsets = new int[2];
getOffset(d.getTime(), false, offsets);
if ((daylight && offsets[1] != 0) || (!daylight && offsets[1] == 0)) {
- format.setTimeZone(this);
return format.format(d);
}
@@ -829,9 +826,27 @@
} else {
// Keep java.util.TimeZone default in sync so java.util.Date
// can interoperate with com.ibm.icu.util classes.
- jdkZone = null;
+
if (tz != null) {
- jdkZone = TimeZoneAdapter.wrap(tz);
+ if (tz instanceof com.ibm.icu.impl.OlsonTimeZone) {
+ // Because of the lack of APIs supporting historic
+ // zone offset/dst saving in JDK TimeZone,
+ // wrapping ICU TimeZone with JDK TimeZone will
+ // cause historic offset calculation in Calendar/Date.
+ // JDK calendar implementation calls getRawOffset() and
+ // getDSTSavings() when the instance of JDK TimeZone
+ // is not an instance of JDK internal TimeZone subclass
+ // (sun.util.calendar.ZoneInfo). Ticket#6459
+ String icuID = tz.getID();
+ jdkZone = java.util.TimeZone.getTimeZone(icuID);
+ if (!icuID.equals(jdkZone.getID())) {
+ // JDK does not know the ID..
+ jdkZone = null;
+ }
+ }
+ if (jdkZone == null) {
+ jdkZone = TimeZoneAdapter.wrap(tz);
+ }
}
}
java.util.TimeZone.setDefault(jdkZone);
diff --git a/src/com/ibm/icu/util/ULocale.java b/src/com/ibm/icu/util/ULocale.java
index 6fde05a..b7dd3f4 100644
--- a/src/com/ibm/icu/util/ULocale.java
+++ b/src/com/ibm/icu/util/ULocale.java
@@ -1,6 +1,6 @@
/*
******************************************************************************
-* Copyright (C) 2003-2008, International Business Machines Corporation and *
+* Copyright (C) 2003-2009, International Business Machines Corporation and *
* others. All Rights Reserved. *
******************************************************************************
*/
@@ -919,7 +919,7 @@
public static ULocale getDefault() {
synchronized (ULocale.class) {
Locale currentDefault = Locale.getDefault();
- if (defaultLocale != currentDefault) {
+ if (!defaultLocale.equals(currentDefault)) {
defaultLocale = currentDefault;
defaultULocale = new ULocale(defaultLocale);
}
diff --git a/src/com/ibm/icu/util/VersionInfo.java b/src/com/ibm/icu/util/VersionInfo.java
index 036b332..9959b52 100644
--- a/src/com/ibm/icu/util/VersionInfo.java
+++ b/src/com/ibm/icu/util/VersionInfo.java
@@ -445,7 +445,7 @@
UNICODE_4_0_1 = getInstance(4, 0, 1, 0);
UNICODE_4_1 = getInstance(4, 1, 0, 0);
UNICODE_5_0 = getInstance(4, 1, 0, 0);
- ICU_VERSION = getInstance(4, 0, 0, 0);
+ ICU_VERSION = getInstance(4, 0, 1, 0);
UCOL_RUNTIME_VERSION = getInstance(6);
UCOL_BUILDER_VERSION = getInstance(7);
UCOL_TAILORINGS_VERSION = getInstance(1);