diff --git a/.gitattributes b/.gitattributes
index 65b22c7..4e7f240 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -49,12 +49,10 @@
 *.tri2 -text
 
 /build.properties -text
+demos/.settings/org.eclipse.core.resources.prefs -text
 demos/manifest.stub -text
-eclipse-build/eclipse_mod_classes.txt -text
-eclipse-build/eclipse_mod_test_classes.txt -text
 eclipse-build/features.template/com.ibm.icu.base/.project -text
 eclipse-build/features.template/com.ibm.icu.base/build.properties -text
-eclipse-build/features.template/com.ibm.icu.base/feature.xml -text
 eclipse-build/plugins.template/com.ibm.icu.base.tests/.classpath -text
 eclipse-build/plugins.template/com.ibm.icu.base.tests/.project -text
 eclipse-build/plugins.template/com.ibm.icu.base.tests/.settings/org.eclipse.jdt.core.prefs -text
@@ -62,20 +60,6 @@
 eclipse-build/plugins.template/com.ibm.icu.base.tests/META-INF/MANIFEST.MF -text
 eclipse-build/plugins.template/com.ibm.icu.base.tests/build.properties -text
 eclipse-build/plugins.template/com.ibm.icu.base.tests/plugin.properties -text
-eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/BreakIteratorTest.java -text
-eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/CalendarTest.java -text
-eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/CollationKeyTest.java -text
-eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/CollatorTest.java -text
-eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/DateFormatSymbolsTest.java -text
-eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/DateFormatTest.java -text
-eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/DecimalFormatSymbolsTest.java -text
-eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/DecimalFormatTest.java -text
-eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/ICUTestCase.java -text
-eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/MessageFormatTest.java -text
-eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/NumberFormatTest.java -text
-eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/SimpleDateFormatTest.java -text
-eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/TimeZoneTest.java -text
-eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/ULocaleTest.java -text
 eclipse-build/plugins.template/com.ibm.icu.base/.classpath -text
 eclipse-build/plugins.template/com.ibm.icu.base/.project -text
 eclipse-build/plugins.template/com.ibm.icu.base/.settings/org.eclipse.jdt.core.prefs -text
@@ -83,63 +67,38 @@
 eclipse-build/plugins.template/com.ibm.icu.base/META-INF/MANIFEST.MF -text
 eclipse-build/plugins.template/com.ibm.icu.base/build.properties -text
 eclipse-build/plugins.template/com.ibm.icu.base/plugin.properties -text
-eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/ICUCache.java -text
-eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/LocaleIDParser.java -text
-eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/LocaleIDs.java -text
-eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/LocaleUtility.java -text
-eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/SimpleCache.java -text
-eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/locale/AsciiUtil.java -text
-eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/math/BigDecimal.java -text
-eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/math/MathContext.java -text
-eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/Bidi.java -text
-eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/BidiClassifier.java -text
-eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/BidiRun.java -text
-eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/BreakIterator.java -text
-eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/CollationKey.java -text
-eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/Collator.java -text
-eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/CurrencyPluralInfo.java -text
-eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/DateFormat.java -text
-eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/DateFormatSymbols.java -text
-eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/DecimalFormat.java -text
-eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/DecimalFormatSymbols.java -text
-eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/MessageFormat.java -text
-eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/NumberFormat.java -text
-eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/RawCollationKey.java -text
-eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/SimpleDateFormat.java -text
-eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/UFormat.java -text
-eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/UnicodeSet.java -text
-eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/Calendar.java -text
-eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/Currency.java -text
-eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/CurrencyAmount.java -text
-eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/TimeZone.java -text
-eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/ULocale.java -text
-eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/VersionInfo.java -text
 eclipse-build/plugins.template/com.ibm.icu.tests/META-INF/MANIFEST.MF -text
 eclipse-build/plugins.template/com.ibm.icu.tests/plugin.properties -text
 eclipse-build/plugins.template/com.ibm.icu/META-INF/MANIFEST.MF -text
 main/classes/charset/.classpath -text
 main/classes/charset/.project -text
+main/classes/charset/.settings/org.eclipse.core.resources.prefs -text
 main/classes/charset/.settings/org.eclipse.jdt.core.prefs -text
 main/classes/charset/manifest.stub -text
 main/classes/collate/.classpath -text
 main/classes/collate/.project -text
+main/classes/collate/.settings/org.eclipse.core.resources.prefs -text
 main/classes/collate/.settings/org.eclipse.jdt.core.prefs -text
 main/classes/collate/.settings/org.eclipse.jdt.ui.prefs -text
 main/classes/collate/collate-build.launch -text
 main/classes/core/.classpath -text
 main/classes/core/.project -text
+main/classes/core/.settings/org.eclipse.core.resources.prefs -text
 main/classes/core/.settings/org.eclipse.jdt.core.prefs -text
 main/classes/core/manifest.stub -text
 main/classes/currdata/.externalToolBuilders/copy-data-currdata.launch -text
+main/classes/currdata/.settings/org.eclipse.core.resources.prefs -text
 main/classes/currdata/.settings/org.eclipse.jdt.core.prefs -text
 main/classes/currdata/.settings/org.eclipse.jdt.ui.prefs -text
 main/classes/currdata/currdata-build.launch -text
 main/classes/langdata/.externalToolBuilders/copy-data-langdata.launch -text
+main/classes/langdata/.settings/org.eclipse.core.resources.prefs -text
 main/classes/langdata/.settings/org.eclipse.jdt.core.prefs -text
 main/classes/langdata/.settings/org.eclipse.jdt.ui.prefs -text
 main/classes/langdata/langdata-build.launch -text
 main/classes/localespi/.classpath -text
 main/classes/localespi/.project -text
+main/classes/localespi/.settings/org.eclipse.core.resources.prefs -text
 main/classes/localespi/.settings/org.eclipse.jdt.core.prefs -text
 main/classes/localespi/manifest.stub -text
 main/classes/localespi/src/META-INF/services/java.text.spi.BreakIteratorProvider -text
@@ -153,27 +112,33 @@
 main/classes/localespi/src/META-INF/services/java.util.spi.TimeZoneNameProvider -text
 main/classes/localespi/src/com/ibm/icu/impl/javaspi/ICULocaleServiceProviderConfig.properties -text
 main/classes/regiondata/.externalToolBuilders/copy-data-regiondata.launch -text
+main/classes/regiondata/.settings/org.eclipse.core.resources.prefs -text
 main/classes/regiondata/.settings/org.eclipse.jdt.core.prefs -text
 main/classes/regiondata/.settings/org.eclipse.jdt.ui.prefs -text
 main/classes/regiondata/regiondata-build.launch -text
 main/classes/translit/.externalToolBuilders/copy-data-translit.launch -text
+main/classes/translit/.settings/org.eclipse.core.resources.prefs -text
 main/classes/translit/.settings/org.eclipse.jdt.core.prefs -text
 main/classes/translit/.settings/org.eclipse.jdt.ui.prefs -text
 main/classes/translit/translit-build.launch -text
 main/shared/.project -text
+main/shared/.settings/org.eclipse.core.resources.prefs -text
 main/shared/data/icudata.jar -text
 main/shared/data/testdata.jar -text
 main/tests/charset/.classpath -text
 main/tests/charset/.project -text
+main/tests/charset/.settings/org.eclipse.core.resources.prefs -text
 main/tests/charset/.settings/org.eclipse.jdt.core.prefs -text
 main/tests/charset/manifest.stub -text
 main/tests/collate/.classpath -text
 main/tests/collate/.project -text
+main/tests/collate/.settings/org.eclipse.core.resources.prefs -text
 main/tests/collate/.settings/org.eclipse.jdt.core.prefs -text
 main/tests/collate/.settings/org.eclipse.jdt.ui.prefs -text
 main/tests/collate/collate-tests-build.launch -text
 main/tests/core/.classpath -text
 main/tests/core/.project -text
+main/tests/core/.settings/org.eclipse.core.resources.prefs -text
 main/tests/core/.settings/org.eclipse.jdt.core.prefs -text
 main/tests/core/manifest.stub -text
 main/tests/core/src/com/ibm/icu/dev/data/rbbi/english.dict -text
@@ -381,19 +346,24 @@
 main/tests/core/src/com/ibm/icu/dev/test/util/Trie2Test.setRangesSingleValue.32.tri2 -text
 main/tests/framework/.classpath -text
 main/tests/framework/.project -text
+main/tests/framework/.settings/org.eclipse.core.resources.prefs -text
 main/tests/framework/.settings/org.eclipse.jdt.core.prefs -text
 main/tests/framework/manifest.stub -text
 main/tests/localespi/.classpath -text
 main/tests/localespi/.project -text
+main/tests/localespi/.settings/org.eclipse.core.resources.prefs -text
 main/tests/localespi/manifest.stub -text
 main/tests/packaging/.externalToolBuilders/copy-test-data.launch -text
+main/tests/packaging/.settings/org.eclipse.core.resources.prefs -text
 main/tests/packaging/.settings/org.eclipse.jdt.core.prefs -text
 main/tests/packaging/.settings/org.eclipse.jdt.ui.prefs -text
 main/tests/packaging/packaging-tests-build.launch -text
 main/tests/translit/.externalToolBuilders/copy-translit-test-data.launch -text
+main/tests/translit/.settings/org.eclipse.core.resources.prefs -text
 main/tests/translit/.settings/org.eclipse.jdt.core.prefs -text
 main/tests/translit/.settings/org.eclipse.jdt.ui.prefs -text
 main/tests/translit/translit-tests-build.launch -text
+tools/build/.settings/org.eclipse.core.resources.prefs -text
 tools/build/icu4j28.api.gz -text
 tools/build/icu4j30.api.gz -text
 tools/build/icu4j32.api.gz -text
@@ -410,6 +380,7 @@
 tools/build/icu4j421.api.gz -text
 tools/build/icu4j44.api2.gz -text
 tools/build/manifest.stub -text
+tools/misc/.settings/org.eclipse.core.resources.prefs -text
 tools/misc/manifest.stub -text
 
 # The following file types are stored in Git-LFS.
diff --git a/.gitignore b/.gitignore
index 1109595..ca06dcd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,7 @@
 /.project
 demos/out
 /doc
+eclipse-build/out
 main/classes/charset/out
 main/classes/collate/out
 main/classes/core/out
diff --git a/build.xml b/build.xml
index f414443..f511e1c 100644
--- a/build.xml
+++ b/build.xml
@@ -1,6 +1,6 @@
 <!--
 *******************************************************************************
-* Copyright (C) 1997-2010, International Business Machines Corporation and    *
+* Copyright (C) 1997-2011, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 -->
@@ -444,8 +444,8 @@
                 nodeprecatedlist="true"
                 windowtitle="icu4j"
                 doctitle="icu4j"
-                encoding="iso-8859-1"
-                docencoding="iso-8859-1"
+                encoding="${java.src.encoding}"
+                docencoding="UTF-8"
                 bottom="&lt;font size=-1&gt;Copyright (c) ${current.year} IBM Corporation and others.&lt;/font&gt;"
                 additionalparam="-breakiterator -use -tagletpath ${icu4j.build-tools.jar} -taglet com.ibm.icu.dev.tool.docs.ICUTaglet"
                 link="http://java.sun.com/javase/6/docs/api/"
@@ -547,7 +547,8 @@
 
     <!-- Release management targets -->
     <target name="checktags" depends="info, build-tools" description="Check API tags before release">
-        <javadoc source="1.5">
+        <javadoc source="1.5"
+                 encoding="${java.src.encoding}">
             <packageset dir="${icu4j.core.dir}/src">
                 <include name="com/ibm/icu/lang/**"/>
                 <include name="com/ibm/icu/math/**"/>
@@ -566,7 +567,8 @@
 
     <target name="gatherapi" depends="info, build-tools" description="Run API database generator tool">
         <mkdir dir="${out.dir}"/>
-        <javadoc source="1.5">
+        <javadoc source="1.5"
+                 encoding="${java.src.encoding}">
             <packageset dir="${icu4j.core.dir}/src">
                 <include name="com/ibm/icu/lang/**"/>
                 <include name="com/ibm/icu/math/**"/>
@@ -609,7 +611,8 @@
 
     <target name="gatherapiOld" depends="info, build-tools" description="Run API database generator tool (Pre Java 5 style)">
         <mkdir dir="${out.dir}"/>
-        <javadoc source="1.5">
+        <javadoc source="1.5"
+                 encoding="${java.src.encoding}">
             <packageset dir="${icu4j.core.dir}/src">
                 <include name="com/ibm/icu/lang/**"/>
                 <include name="com/ibm/icu/math/**"/>
@@ -696,6 +699,7 @@
         <javac destdir="${translit.ime.out.dir}/bin"
                 source="${javac.source}"
                 target="${javac.target}"
+                encoding="${java.src.encoding}"
                 debug="on" deprecation="off">
             <src path="${icu4j.core.dir}/src"/>
             <src path="${icu4j.translit.dir}/src"/>
@@ -723,6 +727,7 @@
         <javac destdir="${indic.ime.out.dir}/bin"
                 source="${javac.source}"
                 target="${javac.target}"
+                encoding="${java.src.encoding}"
                 debug="on" deprecation="off">
             <src path="${icu4j.core.dir}/src"/>
             <src path="${icu4j.tools.dir}/src"/>
@@ -749,6 +754,7 @@
         <javac destdir="${cldr.util.out.dir}/bin"
                 source="${javac.source}"
                 target="${javac.target}"
+                encoding="${java.src.encoding}"
                 debug="on" deprecation="off">
 
             <src path="${icu4j.core.dir}/src"/>
@@ -782,6 +788,7 @@
         <javac destdir="${xliff.out.dir}/bin"
                 source="1.3"
                 target="1.3"
+                encoding="${java.src.encoding}"
                 debug="on" deprecation="off">
             <src path="${icu4j.tools.dir}/src"/>
             <include name="com/ibm/icu/dev/tool/localeconverter/CalculateCRC32.java"/>
@@ -863,6 +870,7 @@
                 destdir="${module.bin.dir}"
                 source="${javac.source}"
                 target="${javac.target}"
+                encoding="${java.src.encoding}"
                 debug="on" deprecation="off">
             <include name="com/ibm/icu/impl/UCharacterName.java"/>
             <include name="com/ibm/icu/impl/data/*Break*.java"/>
@@ -877,6 +885,7 @@
         <javac destdir="${module.tests.dir}"
                 source="${javac.source}"
                 target="${javac.target}"
+                encoding="${java.src.encoding}"
                 classpath="${module.bin.dir}"
                 debug="on" deprecation="off">
             <src path="${icu4j.core.dir}/src"/>
@@ -898,6 +907,7 @@
                 destdir="${module.bin.dir}"
                 source="${javac.source}"
                 target="${javac.target}"
+                encoding="${java.src.encoding}"
                 debug="on" deprecation="off">
             <include name="com/ibm/icu/impl/data/*Holiday*.java"/>
             <include name="com/ibm/icu/lang/UCharacter.java"/>
@@ -926,6 +936,7 @@
         <javac destdir="${module.tests.dir}"
                 source="${javac.source}"
                 target="${javac.target}"
+                encoding="${java.src.encoding}"
                 classpath="${module.bin.dir}"
                 debug="on" deprecation="off">
             <src path="${icu4j.core.dir}/src"/>
@@ -950,6 +961,7 @@
         <javac  destdir="${module.bin.dir}"
                 source="${javac.source}"
                 target="${javac.target}"
+                encoding="${java.src.encoding}"
                 debug="on" deprecation="off">
             <src path="${icu4j.core.dir}/src"/>
             <src path="${icu4j.collate.dir}/src"/>
@@ -981,6 +993,7 @@
         <javac destdir="${module.tests.dir}"
                 source="${javac.source}"
                 target="${javac.target}"
+                encoding="${java.src.encoding}"
                 classpath="${module.bin.dir}"
                 debug="on" deprecation="off">
             <src path="${icu4j.core.dir}/src"/>
@@ -1015,6 +1028,7 @@
                 destdir="${module.bin.dir}"
                 source="${javac.source}"
                 target="${javac.target}"
+                encoding="${java.src.encoding}"
                 debug="on" deprecation="off">
             <include name="com/ibm/icu/text/SCSU.java"/>
             <include name="com/ibm/icu/text/UnicodeCompressor.java"/>
@@ -1027,6 +1041,7 @@
         <javac destdir="${module.tests.dir}"
                 source="${javac.source}"
                 target="${javac.target}"
+                encoding="${java.src.encoding}"
                 classpath="${module.bin.dir}"
                 debug="on" deprecation="off">
             <src path="${icu4j.core.dir}/src"/>
@@ -1045,6 +1060,7 @@
                 destdir="${module.bin.dir}"
                 source="${javac.source}"
                 target="${javac.target}"
+                encoding="${java.src.encoding}"
                 debug="on" deprecation="off">
             <include name="com/ibm/icu/lang/UCharacter.java"/>
             <include name="com/ibm/icu/text/*Collator*.java"/>
@@ -1057,12 +1073,14 @@
                 destdir="${module.bin.dir}"
                 source="${javac.source}"
                 target="${javac.target}"
+                encoding="${java.src.encoding}"
                 debug="on" deprecation="off"/>
 
         <javac srcdir="${icu4j.currdata.dir}/src"
                 destdir="${module.bin.dir}"
                 source="${javac.source}"
                 target="${javac.target}"
+                encoding="${java.src.encoding}"
                 debug="on" deprecation="off"/>
 
         <!-- Format does not require BreakIterator data -->
@@ -1080,6 +1098,7 @@
         <javac destdir="${module.tests.dir}"
                 source="${javac.source}"
                 target="${javac.target}"
+                encoding="${java.src.encoding}"
                 classpath="${module.bin.dir}"
                 debug="on" deprecation="off">
             <src path="${icu4j.core.dir}/src"/>
@@ -1109,6 +1128,7 @@
                 destdir="${module.bin.dir}"
                 source="${javac.source}"
                 target="${javac.target}"
+                encoding="${java.src.encoding}"
                 debug="on" deprecation="off">
             <include name="com/ibm/icu/lang/**/*"/>
             <include name="com/ibm/icu/text/CanonicalIterator.java"/>
@@ -1139,6 +1159,7 @@
         <javac destdir="${module.tests.dir}"
                 source="${javac.source}"
                 target="${javac.target}"
+                encoding="${java.src.encoding}"
                 classpath="${module.bin.dir}"
                 debug="on" deprecation="off">
             <src path="${icu4j.core.dir}/src"/>
@@ -1208,6 +1229,7 @@
                 destdir="${module.bin.dir}"
                 source="${javac.source}"
                 target="${javac.target}"
+                encoding="${java.src.encoding}"
                 debug="on" deprecation="off">
             <include name="com/ibm/icu/impl/data/*Break*.java"/>
             <include name="com/ibm/icu/lang/**/*"/>
@@ -1222,6 +1244,7 @@
         <javac destdir="${module.tests.dir}"
                 source="${javac.source}"
                 target="${javac.target}"
+                encoding="${java.src.encoding}"
                 classpath="${module.bin.dir}"
                 debug="on" deprecation="off">
             <src path="${icu4j.core.dir}/src"/>
@@ -1256,6 +1279,7 @@
         <javac  destdir="${module.bin.dir}"
                 source="${javac.source}"
                 target="${javac.target}"
+                encoding="${java.src.encoding}"
                 debug="on" deprecation="off">
             <src path="${icu4j.core.dir}/src"/>
             <src path="${icu4j.translit.dir}/src"/>
@@ -1291,6 +1315,7 @@
         <javac destdir="${module.tests.dir}"
                 source="${javac.source}"
                 target="${javac.target}"
+                encoding="${java.src.encoding}"
                 classpath="${module.bin.dir}"
                 debug="on" deprecation="off">
             <src path="${icu4j.core.dir}/src"/>
@@ -1314,6 +1339,7 @@
                 destdir="${module.bin.dir}"
                 source="${javac.source}"
                 target="${javac.target}"
+                encoding="${java.src.encoding}"
                 debug="on" deprecation="off">
             <include name="com/ibm/icu/impl/*StringPrep*.java"/>
             <include name="com/ibm/icu/text/*IDNA*.java"/>
@@ -1338,6 +1364,7 @@
         <javac destdir="${module.tests.dir}"
                 source="${javac.source}"
                 target="${javac.target}"
+                encoding="${java.src.encoding}"
                 classpath="${module.bin.dir}"
                 debug="on" deprecation="off">
             <src path="${icu4j.core.dir}/src"/>
diff --git a/demos/.settings/org.eclipse.core.resources.prefs b/demos/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..7cc134b
--- /dev/null
+++ b/demos/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Wed Aug 31 03:50:12 EDT 2011
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/eclipse-build/build.properties b/eclipse-build/build.properties
index f03aa69..52cdff7 100644
--- a/eclipse-build/build.properties
+++ b/eclipse-build/build.properties
@@ -5,4 +5,4 @@
 icu4j.plugin.impl.version.string=4.4.2
 copyright.eclipse=Licensed Materials - Property of IBM \n (C) Copyright IBM Corp. 2000, 2011. All Rights Reserved. \n IBM is a registered trademark of IBM Corp.
 icu4j.data.version.number=44
-icu4j.eclipse.build.version.string=4.4.2.v20110823
+icu4j.eclipse.build.version.string=4.4.2.v20110831
diff --git a/eclipse-build/eclipse_mod_classes.txt b/eclipse-build/eclipse_mod_classes.txt
index dc2f9c6..d279e2e 100644
--- a/eclipse-build/eclipse_mod_classes.txt
+++ b/eclipse-build/eclipse_mod_classes.txt
@@ -1,5 +1,5 @@
-# Copyright (C) 2011, International Business Machines Corporation and
-# others. All Rights Reserved.
-
-com/ibm/icu/lang/UCharacter.java
-com/ibm/icu/text/DecimalFormat.java
+# Copyright (C) 2011, International Business Machines Corporation and
+# others. All Rights Reserved.
+
+com/ibm/icu/lang/UCharacter.java
+com/ibm/icu/text/DecimalFormat.java
diff --git a/eclipse-build/eclipse_mod_test_classes.txt b/eclipse-build/eclipse_mod_test_classes.txt
index 20b5292..7059aeb 100644
--- a/eclipse-build/eclipse_mod_test_classes.txt
+++ b/eclipse-build/eclipse_mod_test_classes.txt
@@ -1,7 +1,7 @@
-# Copyright (C) 2011, International Business Machines Corporation and
-# others. All Rights Reserved.
-
-com/ibm/icu/dev/test/format/IntlTestDecimalFormatAPI.java
-com/ibm/icu/dev/test/format/NumberFormatTest.java
-com/ibm/icu/dev/test/serializable/CompatibilityTest.java
-com/ibm/icu/dev/test/serializable/CoverageTest.java
+# Copyright (C) 2011, International Business Machines Corporation and
+# others. All Rights Reserved.
+
+com/ibm/icu/dev/test/format/IntlTestDecimalFormatAPI.java
+com/ibm/icu/dev/test/format/NumberFormatTest.java
+com/ibm/icu/dev/test/serializable/CompatibilityTest.java
+com/ibm/icu/dev/test/serializable/CoverageTest.java
diff --git a/eclipse-build/features.template/com.ibm.icu.base/feature.xml b/eclipse-build/features.template/com.ibm.icu.base/feature.xml
index 367bcd2..5102e29 100644
--- a/eclipse-build/features.template/com.ibm.icu.base/feature.xml
+++ b/eclipse-build/features.template/com.ibm.icu.base/feature.xml
@@ -1,33 +1,33 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<feature
-      id="com.ibm.icu.base"
-      label="com.ibm.icu.base"
-      version="@BUILD_VERSION@">
-
-   <description url="http://www.example.com/description">
-      [Enter Feature Description here.]
-   </description>
-
-   <copyright url="http://www.example.com/copyright">
-      [Enter Copyright Description here.]
-   </copyright>
-
-   <license url="http://www.example.com/license">
-      [Enter License Description here.]
-   </license>
-
-   <plugin
-         id="com.ibm.icu.base"
-         download-size="0"
-         install-size="0"
-         version="@BUILD_VERSION@"
-         unpack="false"/>
-
-   <plugin
-         id="com.ibm.icu.base.source"
-         download-size="0"
-         install-size="0"
-         version="@BUILD_VERSION@"
-         unpack="false"/>
-
-</feature>
+<?xml version="1.0" encoding="UTF-8"?>
+<feature
+      id="com.ibm.icu.base"
+      label="com.ibm.icu.base"
+      version="@BUILD_VERSION@">
+
+   <description url="http://www.example.com/description">
+      [Enter Feature Description here.]
+   </description>
+
+   <copyright url="http://www.example.com/copyright">
+      [Enter Copyright Description here.]
+   </copyright>
+
+   <license url="http://www.example.com/license">
+      [Enter License Description here.]
+   </license>
+
+   <plugin
+         id="com.ibm.icu.base"
+         download-size="0"
+         install-size="0"
+         version="@BUILD_VERSION@"
+         unpack="false"/>
+
+   <plugin
+         id="com.ibm.icu.base.source"
+         download-size="0"
+         install-size="0"
+         version="@BUILD_VERSION@"
+         unpack="false"/>
+
+</feature>
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/BreakIteratorTest.java b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/BreakIteratorTest.java
index 6b26f3b..3db1546 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/BreakIteratorTest.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/BreakIteratorTest.java
@@ -1,359 +1,359 @@
-/*
- *******************************************************************************
- * Copyright (C) 2006-2011, International Business Machines Corporation and    *
- * others. All Rights Reserved.                                                *
- *******************************************************************************
- */
-
-package com.ibm.icu.tests;
-
-import java.text.CharacterIterator;
-import java.text.StringCharacterIterator;
-import java.util.Locale;
-
-import com.ibm.icu.text.BreakIterator;
-import com.ibm.icu.util.ULocale;
-
-public class BreakIteratorTest extends ICUTestCase {
-    // ICU behaves a bit differently with this text, but the tested values aren't
-    // affected.  If Java changes behavior they might need to change.
-    private static final String text = "Mr. and Mrs. Mumblety-Peg paid $35.97 for a new 12\" cockatoo. " +
-        "When they got home they both cooed \"Isn't it lovely?\" and sighed softly. " +
-        "\"Let's name it u\u0308\u5098!\" they said with glee.";
-    private static int pos = text.indexOf("sn't");
-    private static BreakIterator cbr;
-    private static BreakIterator wbr;
-    private static BreakIterator lbr;
-    private static BreakIterator sbr;
-        
-    static {
-        cbr = BreakIterator.getCharacterInstance();
-        cbr.setText(text);
-        wbr = BreakIterator.getWordInstance();
-        wbr.setText(text);
-        lbr = BreakIterator.getLineInstance();
-        lbr.setText(text);
-        sbr = BreakIterator.getSentenceInstance();
-        sbr.setText(text);
-                
-        // diagnostic
-        //              dump(cbr);
-        //              dump(wbr);
-        //              dump(lbr);
-        //              dump(sbr);
-    }
-        
-    //      private static void dump(BreakIterator bi) {
-    //              for (int ix = bi.first(), lim = text.length(); ix != lim;) {
-    //                      int nx = bi.next();
-    //                      if (nx < 0) nx = lim;
-    //                      System.out.println(Integer.toString(ix) + ": " + text.substring(ix, nx));
-    //                      ix = nx;
-    //              }
-    //      }
-        
-    /*
-     * Test method for 'com.ibm.icu.text.BreakIterator.hashCode()'
-     */
-    public void testHashCode() {
-        BreakIterator br = BreakIterator.getWordInstance();
-        br.setText(text);
-        BreakIterator brne = BreakIterator.getWordInstance();
-        brne.setText(text + "X");
-        wbr.first();
-        testEHCS(br, wbr, brne);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.BreakIterator.BreakIterator(BreakIterator)'
-     */
-    public void testBreakIterator() {
-        // implicitly tested everywhere
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.BreakIterator.first()'
-     */
-    public void testFirst() {
-        assertEquals(0, cbr.first());
-        assertEquals(0, wbr.first());
-        assertEquals(0, lbr.first());
-        assertEquals(0, sbr.first());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.BreakIterator.last()'
-     */
-    public void testLast() {
-        assertEquals(text.length(), cbr.last());
-        assertEquals(text.length(), wbr.last());
-        assertEquals(text.length(), lbr.last());
-        assertEquals(text.length(), sbr.last());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.BreakIterator.next(int)'
-     */
-    public void testNextInt() {
-        cbr.first();
-        wbr.first();
-        lbr.first();
-        sbr.first();
-        assertEquals(2, cbr.next(2));
-        assertEquals(3, wbr.next(2));
-        assertEquals(8, lbr.next(2));
-        assertEquals(62, sbr.next(2));
-                
-        cbr.last();
-        wbr.last();
-        lbr.last();
-        sbr.last();
-        assertEquals(174, cbr.next(-2));
-        assertEquals(171, wbr.next(-2));
-        assertEquals(166, lbr.next(-2));
-        assertEquals(135, sbr.next(-2));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.BreakIterator.next()'
-     */
-    public void testNext() {
-        cbr.first();
-        wbr.first();
-        lbr.first();
-        sbr.first();
-        assertEquals(1, cbr.next());
-        assertEquals(2, wbr.next());
-        assertEquals(4, lbr.next());
-        assertEquals(13, sbr.next());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.BreakIterator.previous()'
-     */
-    public void testPrevious() {
-        cbr.last();
-        wbr.last();
-        lbr.last();
-        sbr.last();
-        assertEquals(175, cbr.previous());
-        assertEquals(175, wbr.previous());
-        assertEquals(171, lbr.previous());
-        assertEquals(156, sbr.previous());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.BreakIterator.following(int)'
-     */
-    public void testFollowing() {
-        assertEquals(100, cbr.following(pos));
-        assertEquals(103, wbr.following(pos));
-        assertEquals(104, lbr.following(pos));
-        assertEquals(116, sbr.following(pos));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.BreakIterator.preceding(int)'
-     */
-    public void testPreceding() {
-        assertEquals(98, cbr.preceding(pos));
-        assertEquals(98, wbr.preceding(pos));
-        assertEquals(97, lbr.preceding(pos));
-        assertEquals(62, sbr.preceding(pos));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.BreakIterator.isBoundary(int)'
-     */
-    public void testIsBoundary() {
-        assertTrue(cbr.isBoundary(pos));
-        assertFalse(wbr.isBoundary(pos));
-        assertFalse(lbr.isBoundary(pos));
-        assertFalse(sbr.isBoundary(pos));
-
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.BreakIterator.current()'
-     */
-    public void testCurrent() {
-        cbr.following(pos);
-        wbr.following(pos);
-        lbr.following(pos);
-        sbr.following(pos);
-        assertEquals(100, cbr.current());
-        assertEquals(103, wbr.current());
-        assertEquals(104, lbr.current());
-        assertEquals(116, sbr.current());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.BreakIterator.getText()'
-     */
-    public void testGetText() {
-        CharacterIterator ci = cbr.getText();
-        StringBuffer buf = new StringBuffer(ci.getEndIndex() - ci.getBeginIndex());
-        for (char c = ci.first(); c != CharacterIterator.DONE; c = ci.next()) {
-            buf.append(c);
-        }
-        String result = buf.toString();
-        assertEquals(text, result);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.BreakIterator.setText(String)'
-     */
-    public void testSetTextString() {
-        // implicitly tested
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.BreakIterator.setText(CharacterIterator)'
-     */
-    public void testSetTextCharacterIterator() {
-        CharacterIterator ci = new StringCharacterIterator(text, pos);
-        BreakIterator bi = BreakIterator.getWordInstance();
-        bi.setText(ci);
-        assertEquals(2, bi.next());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.BreakIterator.getWordInstance()'
-     */
-    public void testGetWordInstance() {
-        // implicitly tested
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.BreakIterator.getWordInstance(Locale)'
-     */
-    public void testGetWordInstanceLocale() {
-        assertNotNull(BreakIterator.getWordInstance(Locale.JAPAN));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.BreakIterator.getWordInstance(ULocale)'
-     */
-    public void testGetWordInstanceULocale() {
-        assertNotNull(BreakIterator.getWordInstance(ULocale.JAPAN));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.BreakIterator.getLineInstance()'
-     */
-    public void testGetLineInstance() {
-        // implicitly tested
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.BreakIterator.getLineInstance(Locale)'
-     */
-    public void testGetLineInstanceLocale() {
-        assertNotNull(BreakIterator.getLineInstance(Locale.JAPAN));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.BreakIterator.getLineInstance(ULocale)'
-     */
-    public void testGetLineInstanceULocale() {
-        assertNotNull(BreakIterator.getLineInstance(ULocale.JAPAN));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.BreakIterator.getCharacterInstance()'
-     */
-    public void testGetCharacterInstance() {
-        // implicitly tested
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.BreakIterator.getCharacterInstance(Locale)'
-     */
-    public void testGetCharacterInstanceLocale() {
-        assertNotNull(BreakIterator.getCharacterInstance(Locale.JAPAN));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.BreakIterator.getCharacterInstance(ULocale)'
-     */
-    public void testGetCharacterInstanceULocale() {
-        assertNotNull(BreakIterator.getCharacterInstance(ULocale.JAPAN));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.BreakIterator.getSentenceInstance()'
-     */
-    public void testGetSentenceInstance() {
-        // implicitly tested
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.BreakIterator.getSentenceInstance(Locale)'
-     */
-    public void testGetSentenceInstanceLocale() {
-        assertNotNull(BreakIterator.getSentenceInstance(Locale.JAPAN));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.BreakIterator.getSentenceInstance(ULocale)'
-     */
-    public void testGetSentenceInstanceULocale() {
-        assertNotNull(BreakIterator.getSentenceInstance(ULocale.JAPAN));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.BreakIterator.getTitleInstance()'
-     */
-    public void testGetTitleInstance() {
-        // not implemented
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.BreakIterator.getTitleInstance(Locale)'
-     */
-    public void testGetTitleInstanceLocale() {
-        // not implemented
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.BreakIterator.getTitleInstance(ULocale)'
-     */
-    public void testGetTitleInstanceULocale() {
-        // not implemented
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.BreakIterator.getAvailableLocales()'
-     */
-    public void testGetAvailableLocales() {
-        assertNotNull(BreakIterator.getAvailableLocales());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.BreakIterator.getAvailableULocales()'
-     */
-    public void testGetAvailableULocales() {
-        assertNotNull(BreakIterator.getAvailableULocales());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.BreakIterator.toString()'
-     */
-    public void testToString() {
-        assertNotNull(cbr.toString());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.BreakIterator.clone()'
-     */
-    public void testClone() {
-        // see testHashCode
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.BreakIterator.equals(Object)'
-     */
-    public void testEqualsObject() {
-        // see testHashCode
-    }
-}
+/*
+ *******************************************************************************
+ * Copyright (C) 2006-2011, International Business Machines Corporation and    *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+
+package com.ibm.icu.tests;
+
+import java.text.CharacterIterator;
+import java.text.StringCharacterIterator;
+import java.util.Locale;
+
+import com.ibm.icu.text.BreakIterator;
+import com.ibm.icu.util.ULocale;
+
+public class BreakIteratorTest extends ICUTestCase {
+    // ICU behaves a bit differently with this text, but the tested values aren't
+    // affected.  If Java changes behavior they might need to change.
+    private static final String text = "Mr. and Mrs. Mumblety-Peg paid $35.97 for a new 12\" cockatoo. " +
+        "When they got home they both cooed \"Isn't it lovely?\" and sighed softly. " +
+        "\"Let's name it u\u0308\u5098!\" they said with glee.";
+    private static int pos = text.indexOf("sn't");
+    private static BreakIterator cbr;
+    private static BreakIterator wbr;
+    private static BreakIterator lbr;
+    private static BreakIterator sbr;
+        
+    static {
+        cbr = BreakIterator.getCharacterInstance();
+        cbr.setText(text);
+        wbr = BreakIterator.getWordInstance();
+        wbr.setText(text);
+        lbr = BreakIterator.getLineInstance();
+        lbr.setText(text);
+        sbr = BreakIterator.getSentenceInstance();
+        sbr.setText(text);
+                
+        // diagnostic
+        //              dump(cbr);
+        //              dump(wbr);
+        //              dump(lbr);
+        //              dump(sbr);
+    }
+        
+    //      private static void dump(BreakIterator bi) {
+    //              for (int ix = bi.first(), lim = text.length(); ix != lim;) {
+    //                      int nx = bi.next();
+    //                      if (nx < 0) nx = lim;
+    //                      System.out.println(Integer.toString(ix) + ": " + text.substring(ix, nx));
+    //                      ix = nx;
+    //              }
+    //      }
+        
+    /*
+     * Test method for 'com.ibm.icu.text.BreakIterator.hashCode()'
+     */
+    public void testHashCode() {
+        BreakIterator br = BreakIterator.getWordInstance();
+        br.setText(text);
+        BreakIterator brne = BreakIterator.getWordInstance();
+        brne.setText(text + "X");
+        wbr.first();
+        testEHCS(br, wbr, brne);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.BreakIterator.BreakIterator(BreakIterator)'
+     */
+    public void testBreakIterator() {
+        // implicitly tested everywhere
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.BreakIterator.first()'
+     */
+    public void testFirst() {
+        assertEquals(0, cbr.first());
+        assertEquals(0, wbr.first());
+        assertEquals(0, lbr.first());
+        assertEquals(0, sbr.first());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.BreakIterator.last()'
+     */
+    public void testLast() {
+        assertEquals(text.length(), cbr.last());
+        assertEquals(text.length(), wbr.last());
+        assertEquals(text.length(), lbr.last());
+        assertEquals(text.length(), sbr.last());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.BreakIterator.next(int)'
+     */
+    public void testNextInt() {
+        cbr.first();
+        wbr.first();
+        lbr.first();
+        sbr.first();
+        assertEquals(2, cbr.next(2));
+        assertEquals(3, wbr.next(2));
+        assertEquals(8, lbr.next(2));
+        assertEquals(62, sbr.next(2));
+                
+        cbr.last();
+        wbr.last();
+        lbr.last();
+        sbr.last();
+        assertEquals(174, cbr.next(-2));
+        assertEquals(171, wbr.next(-2));
+        assertEquals(166, lbr.next(-2));
+        assertEquals(135, sbr.next(-2));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.BreakIterator.next()'
+     */
+    public void testNext() {
+        cbr.first();
+        wbr.first();
+        lbr.first();
+        sbr.first();
+        assertEquals(1, cbr.next());
+        assertEquals(2, wbr.next());
+        assertEquals(4, lbr.next());
+        assertEquals(13, sbr.next());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.BreakIterator.previous()'
+     */
+    public void testPrevious() {
+        cbr.last();
+        wbr.last();
+        lbr.last();
+        sbr.last();
+        assertEquals(175, cbr.previous());
+        assertEquals(175, wbr.previous());
+        assertEquals(171, lbr.previous());
+        assertEquals(156, sbr.previous());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.BreakIterator.following(int)'
+     */
+    public void testFollowing() {
+        assertEquals(100, cbr.following(pos));
+        assertEquals(103, wbr.following(pos));
+        assertEquals(104, lbr.following(pos));
+        assertEquals(116, sbr.following(pos));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.BreakIterator.preceding(int)'
+     */
+    public void testPreceding() {
+        assertEquals(98, cbr.preceding(pos));
+        assertEquals(98, wbr.preceding(pos));
+        assertEquals(97, lbr.preceding(pos));
+        assertEquals(62, sbr.preceding(pos));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.BreakIterator.isBoundary(int)'
+     */
+    public void testIsBoundary() {
+        assertTrue(cbr.isBoundary(pos));
+        assertFalse(wbr.isBoundary(pos));
+        assertFalse(lbr.isBoundary(pos));
+        assertFalse(sbr.isBoundary(pos));
+
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.BreakIterator.current()'
+     */
+    public void testCurrent() {
+        cbr.following(pos);
+        wbr.following(pos);
+        lbr.following(pos);
+        sbr.following(pos);
+        assertEquals(100, cbr.current());
+        assertEquals(103, wbr.current());
+        assertEquals(104, lbr.current());
+        assertEquals(116, sbr.current());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.BreakIterator.getText()'
+     */
+    public void testGetText() {
+        CharacterIterator ci = cbr.getText();
+        StringBuffer buf = new StringBuffer(ci.getEndIndex() - ci.getBeginIndex());
+        for (char c = ci.first(); c != CharacterIterator.DONE; c = ci.next()) {
+            buf.append(c);
+        }
+        String result = buf.toString();
+        assertEquals(text, result);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.BreakIterator.setText(String)'
+     */
+    public void testSetTextString() {
+        // implicitly tested
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.BreakIterator.setText(CharacterIterator)'
+     */
+    public void testSetTextCharacterIterator() {
+        CharacterIterator ci = new StringCharacterIterator(text, pos);
+        BreakIterator bi = BreakIterator.getWordInstance();
+        bi.setText(ci);
+        assertEquals(2, bi.next());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.BreakIterator.getWordInstance()'
+     */
+    public void testGetWordInstance() {
+        // implicitly tested
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.BreakIterator.getWordInstance(Locale)'
+     */
+    public void testGetWordInstanceLocale() {
+        assertNotNull(BreakIterator.getWordInstance(Locale.JAPAN));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.BreakIterator.getWordInstance(ULocale)'
+     */
+    public void testGetWordInstanceULocale() {
+        assertNotNull(BreakIterator.getWordInstance(ULocale.JAPAN));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.BreakIterator.getLineInstance()'
+     */
+    public void testGetLineInstance() {
+        // implicitly tested
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.BreakIterator.getLineInstance(Locale)'
+     */
+    public void testGetLineInstanceLocale() {
+        assertNotNull(BreakIterator.getLineInstance(Locale.JAPAN));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.BreakIterator.getLineInstance(ULocale)'
+     */
+    public void testGetLineInstanceULocale() {
+        assertNotNull(BreakIterator.getLineInstance(ULocale.JAPAN));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.BreakIterator.getCharacterInstance()'
+     */
+    public void testGetCharacterInstance() {
+        // implicitly tested
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.BreakIterator.getCharacterInstance(Locale)'
+     */
+    public void testGetCharacterInstanceLocale() {
+        assertNotNull(BreakIterator.getCharacterInstance(Locale.JAPAN));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.BreakIterator.getCharacterInstance(ULocale)'
+     */
+    public void testGetCharacterInstanceULocale() {
+        assertNotNull(BreakIterator.getCharacterInstance(ULocale.JAPAN));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.BreakIterator.getSentenceInstance()'
+     */
+    public void testGetSentenceInstance() {
+        // implicitly tested
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.BreakIterator.getSentenceInstance(Locale)'
+     */
+    public void testGetSentenceInstanceLocale() {
+        assertNotNull(BreakIterator.getSentenceInstance(Locale.JAPAN));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.BreakIterator.getSentenceInstance(ULocale)'
+     */
+    public void testGetSentenceInstanceULocale() {
+        assertNotNull(BreakIterator.getSentenceInstance(ULocale.JAPAN));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.BreakIterator.getTitleInstance()'
+     */
+    public void testGetTitleInstance() {
+        // not implemented
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.BreakIterator.getTitleInstance(Locale)'
+     */
+    public void testGetTitleInstanceLocale() {
+        // not implemented
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.BreakIterator.getTitleInstance(ULocale)'
+     */
+    public void testGetTitleInstanceULocale() {
+        // not implemented
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.BreakIterator.getAvailableLocales()'
+     */
+    public void testGetAvailableLocales() {
+        assertNotNull(BreakIterator.getAvailableLocales());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.BreakIterator.getAvailableULocales()'
+     */
+    public void testGetAvailableULocales() {
+        assertNotNull(BreakIterator.getAvailableULocales());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.BreakIterator.toString()'
+     */
+    public void testToString() {
+        assertNotNull(cbr.toString());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.BreakIterator.clone()'
+     */
+    public void testClone() {
+        // see testHashCode
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.BreakIterator.equals(Object)'
+     */
+    public void testEqualsObject() {
+        // see testHashCode
+    }
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/CalendarTest.java b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/CalendarTest.java
index 69195a2..3237a94 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/CalendarTest.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/CalendarTest.java
@@ -1,565 +1,565 @@
-/*
- *******************************************************************************
- * Copyright (C) 2006-2011, International Business Machines Corporation and    *
- * others. All Rights Reserved.                                                *
- *******************************************************************************
- */
-
-package com.ibm.icu.tests;
-
-import java.util.Date;
-import java.util.Locale;
-
-import com.ibm.icu.text.DateFormat;
-import com.ibm.icu.util.Calendar;
-import com.ibm.icu.util.TimeZone;
-import com.ibm.icu.util.ULocale;
-
-public class CalendarTest extends ICUTestCase {
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.hashCode()'
-     */
-    public void testHashCode() {
-        Calendar cal1 = Calendar.getInstance();
-        Calendar cal2 = Calendar.getInstance();
-        Calendar cal3 = Calendar.getInstance();
-
-        long t = System.currentTimeMillis();
-        cal1.setTimeInMillis(t);
-        cal2.setTimeInMillis(t);
-        cal3.setTimeInMillis(t);
-
-        cal3.setMinimalDaysInFirstWeek(cal3.getMinimalDaysInFirstWeek()+1);
-        testEHCS(cal1, cal2, cal3);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.Calendar(Calendar)'
-     */
-    public void testCalendar() {
-        // tested implicitly everywhere
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.getInstance()'
-     */
-    public void testGetInstance() {
-        // tested by testEHCS
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.getInstance(TimeZone)'
-     */
-    public void testGetInstanceTimeZone() {
-        TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
-        Calendar cal = Calendar.getInstance(tz);
-        assertNotNull(cal);
-        assertNotNull(cal.getTime());
-        assertEquals(tz, cal.getTimeZone());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.getInstance(Locale)'
-     */
-    public void testGetInstanceLocale() {
-        Calendar cal = Calendar.getInstance(Locale.US);
-        assertNotNull(cal);
-        assertNotNull(cal.getTime());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.getInstance(ULocale)'
-     */
-    public void testGetInstanceULocale() {
-        Calendar cal = Calendar.getInstance(ULocale.US);
-        assertNotNull(cal);
-        assertNotNull(cal.getTime());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.getInstance(TimeZone, Locale)'
-     */
-    public void testGetInstanceTimeZoneLocale() {
-        TimeZone tz = TimeZone.getTimeZone("America/New_York");
-        Calendar cal = Calendar.getInstance(tz, Locale.US);
-        assertNotNull(cal);
-        assertNotNull(cal.getTime());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.getInstance(TimeZone, ULocale)'
-     */
-    public void testGetInstanceTimeZoneULocale() {
-        TimeZone tz = TimeZone.getTimeZone("America/New_York");
-        Calendar cal = Calendar.getInstance(tz, ULocale.US);
-        assertNotNull(cal);
-        assertNotNull(cal.getTime());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.getAvailableLocales()'
-     */
-    public void testGetAvailableLocales() {
-        assertNotNull(Calendar.getAvailableLocales());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.getAvailableULocales()'
-     */
-    public void testGetAvailableULocales() {
-        assertNotNull(Calendar.getAvailableULocales());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.getTime()'
-     */
-    public void testGetTime() {
-        Calendar cal = Calendar.getInstance();
-        assertNotNull(cal.getTime());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.setTime(Date)'
-     */
-    public void testSetTime() {
-        Calendar cal = Calendar.getInstance();
-        cal.clear();
-        cal.set(2006, 0, 20, 9, 30, 0);
-        Date date = cal.getTime();
-        cal = Calendar.getInstance();
-        cal.setTime(date);
-        assertEquals(date, cal.getTime());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.getTimeInMillis()'
-     */
-    public void testGetTimeInMillis() {
-        Calendar cal = Calendar.getInstance();
-        assertTrue(0 != cal.getTimeInMillis());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.setTimeInMillis(long)'
-     */
-    public void testSetTimeInMillis() {
-        Calendar cal = Calendar.getInstance();
-        cal.clear();
-        cal.set(2006, 0, 20, 9, 30, 0);
-        long millis = cal.getTimeInMillis();
-        Date date = cal.getTime();
-        
-        cal = Calendar.getInstance();
-        cal.setTimeInMillis(millis);
-        
-        assertEquals(date, cal.getTime());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.get(int)'
-     */
-    public void testGet() {
-        Calendar cal = Calendar.getInstance();
-        cal.clear();
-        cal.set(2006, 0, 20, 9, 30, 0);
-        assertEquals(0, cal.get(Calendar.MONTH));
-        assertEquals(20, cal.get(Calendar.DAY_OF_MONTH));
-        assertEquals(30, cal.get(Calendar.MINUTE));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.set(int, int)'
-     */
-    public void testSetIntInt() {
-        Calendar cal = Calendar.getInstance();
-        cal.set(Calendar.YEAR, 1977);
-        assertEquals(1977, cal.get(Calendar.YEAR));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.set(int, int, int)'
-     */
-    public void testSetIntIntInt() {
-        Calendar cal = Calendar.getInstance();
-        cal.set(1997, 9, 15);
-        assertEquals(15, cal.get(Calendar.DATE));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.set(int, int, int, int, int)'
-     */
-    public void testSetIntIntIntIntInt() {
-        Calendar cal = Calendar.getInstance();
-        cal.set(1997, 9, 15, 14, 25);
-        assertEquals(25, cal.get(Calendar.MINUTE));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.set(int, int, int, int, int, int)'
-     */
-    public void testSetIntIntIntIntIntInt() {
-        Calendar cal = Calendar.getInstance();
-        cal.set(1997, 9, 15, 14, 25, 51);
-        assertEquals(51, cal.get(Calendar.SECOND));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.clear()'
-     */
-    public void testClear() {
-        Calendar cal = Calendar.getInstance();
-        cal.set(1997, 9, 15, 14, 25, 51);
-        cal.clear();
-        assertEquals(0, cal.get(Calendar.MONTH));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.clear(int)'
-     */
-    public void testClearInt() {
-        Calendar cal = Calendar.getInstance();
-        cal.set(1997, 9, 15, 14, 25, 51);
-        assertTrue(cal.isSet(Calendar.DAY_OF_MONTH));
-        cal.clear(Calendar.DAY_OF_MONTH);
-        assertFalse(cal.isSet(Calendar.DAY_OF_MONTH));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.isSet(int)'
-     */
-    public void testIsSet() {
-        // see testClearInt
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.equals(Object)'
-     */
-    public void testEqualsObject() {
-        // tested by testHashCode
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.isEquivalentTo(Calendar)'
-     */
-    public void testIsEquivalentTo() {
-        Calendar cal = Calendar.getInstance();
-        Calendar cal2 = Calendar.getInstance();
-        cal2.set(1994, 6, 21, 8, 7);
-        assertTrue(cal.isEquivalentTo(cal2));
-        cal.setTimeZone(TimeZone.getTimeZone("CST"));
-        cal2.setTimeZone(TimeZone.getTimeZone("PDT"));
-        assertFalse(cal.isEquivalentTo(cal2));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.before(Object)'
-     */
-    public void testBefore() {
-        Calendar cal = Calendar.getInstance();
-        cal.set(Calendar.YEAR, 1990);
-        assertTrue(cal.before(new Date()));
-        assertTrue(cal.before(Calendar.getInstance()));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.after(Object)'
-     */
-    public void testAfter() {
-        Calendar cal = Calendar.getInstance();
-        cal.set(Calendar.YEAR, 3058);
-        assertTrue(cal.after(new Date()));
-        assertTrue(cal.after(Calendar.getInstance()));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.getActualMaximum(int)'
-     */
-    public void testGetActualMaximum() {
-        Calendar cal = Calendar.getInstance(Locale.US);
-        assertEquals(11, cal.getActualMaximum(Calendar.MONTH));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.getActualMinimum(int)'
-     */
-    public void testGetActualMinimum() {
-        Calendar cal = Calendar.getInstance(Locale.US);
-        assertEquals(0, cal.getActualMinimum(Calendar.MONTH));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.roll(int, boolean)'
-     */
-    public void testRollIntBoolean() {
-        Calendar cal = Calendar.getInstance(Locale.US);
-        cal.set(1997, 1, 27);
-        cal.roll(Calendar.DATE, true);
-        assertEquals(28, cal.get(Calendar.DATE));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.roll(int, int)'
-     */
-    public void testRollIntInt() {
-        Calendar cal = Calendar.getInstance(Locale.US);
-        cal.set(1997, 1, 27);
-        cal.roll(Calendar.DATE, 3);
-        assertEquals(2, cal.get(Calendar.DATE));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.add(int, int)'
-     */
-    public void testAdd() {
-        Calendar cal = Calendar.getInstance(Locale.US);
-        cal.set(1997, 1, 27);
-        cal.add(Calendar.DATE, 3);
-        assertEquals(2, cal.get(Calendar.DATE));
-        assertEquals(2, cal.get(Calendar.MONTH));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.getDisplayName(Locale)'
-     */
-    public void testGetDisplayNameLocale() {
-        Calendar cal = Calendar.getInstance();
-        assertEquals("Gregorian Calendar", cal.getDisplayName(Locale.US));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.getDisplayName(ULocale)'
-     */
-    public void testGetDisplayNameULocale() {
-        Calendar cal = Calendar.getInstance();
-        assertEquals("Gregorian Calendar", cal.getDisplayName(ULocale.US));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.compareTo(Calendar)'
-     */
-    public void testCompareToCalendar() {
-        Calendar cal = Calendar.getInstance();
-        cal.set(Calendar.YEAR, 1990);
-        assertTrue(0 > cal.compareTo(Calendar.getInstance()));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.compareTo(Object)'
-     */
-    public void testCompareToObject() {
-        Calendar cal = Calendar.getInstance();
-        cal.set(Calendar.YEAR, 1990);
-        assertTrue(0 > cal.compareTo(Calendar.getInstance()));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.getDateTimeFormat(int, int, Locale)'
-     */
-    public void testGetDateTimeFormatIntIntLocale() {
-        Calendar cal = Calendar.getInstance();
-        cal.set(1990, 8, 16, 20, 3);
-        DateFormat df = cal.getDateTimeFormat(DateFormat.LONG, DateFormat.SHORT, Locale.US);
-        assertEquals("September 16, 1990 8:03 PM", df.format(cal));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.getDateTimeFormat(int, int, ULocale)'
-     */
-    public void testGetDateTimeFormatIntIntULocale() {
-        Calendar cal = Calendar.getInstance();
-        cal.set(1990, 8, 16, 20, 3);
-        DateFormat df = cal.getDateTimeFormat(DateFormat.LONG, DateFormat.SHORT, ULocale.US);
-        assertEquals("September 16, 1990 8:03 PM", df.format(cal));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.fieldDifference(Date, int)'
-     */
-    public void testFieldDifference() {
-        Calendar cal = Calendar.getInstance();
-        cal.set(Calendar.DAY_OF_MONTH, 0);
-        Date date = cal.getTime();
-        cal.add(Calendar.DAY_OF_MONTH, 5);
-        assertEquals(-5, cal.fieldDifference(date, Calendar.DAY_OF_MONTH));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.getTimeZone()'
-     */
-    public void testGetTimeZone() {
-        Calendar cal = Calendar.getInstance();
-        assertNotNull(cal.getTimeZone());
-    }
-    
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.setTimeZone(TimeZone)'
-     */
-    public void testSetTimeZone() {
-        Calendar cal = Calendar.getInstance();
-        TimeZone value1 = cal.getTimeZone();
-        String tzn = "PDT".equals(value1.getID()) ? "CST" : "PDT";
-        TimeZone value2 = TimeZone.getTimeZone(tzn);
-        cal.setTimeZone(value2);
-        TimeZone result = cal.getTimeZone();
-        assertNotEqual(value1, result);
-        assertEquals(value2, result);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.setLenient(boolean)'
-     */
-    public void testSetLenient() {
-        Calendar cal = Calendar.getInstance();
-        boolean lenient = cal.isLenient();
-        cal.setLenient(!lenient);
-        assertFalse(lenient == cal.isLenient());
-        
-        // not testing if it has the expected effect
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.isLenient()'
-     */
-    public void testIsLenient() {
-        // tested by testSetLenient
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.setFirstDayOfWeek(int)'
-     */
-    public void testSetFirstDayOfWeek() {
-        Calendar cal = Calendar.getInstance();
-        int firstDay = cal.getFirstDayOfWeek();
-        cal.setFirstDayOfWeek(firstDay+1);
-        assertEquals(firstDay+1, cal.getFirstDayOfWeek());
-
-        // don't test functionality
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.getFirstDayOfWeek()'
-     */
-    public void testGetFirstDayOfWeek() {
-        // tested by testSetFirstDayOfWeek
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.setMinimalDaysInFirstWeek(int)'
-     */
-    public void testSetMinimalDaysInFirstWeek() {
-        Calendar cal = Calendar.getInstance();
-        int firstDay = cal.getMinimalDaysInFirstWeek();
-        cal.setMinimalDaysInFirstWeek(firstDay+1);
-        assertEquals(firstDay+1, cal.getMinimalDaysInFirstWeek());
-
-        // don't test functionality
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.getMinimalDaysInFirstWeek()'
-     */
-    public void testGetMinimalDaysInFirstWeek() {
-        // tested by testSetMinimalDaysInFirstWeek
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.getMinimum(int)'
-     */
-    public void testGetMinimum() {
-        Calendar cal = Calendar.getInstance();
-        assertEquals(1, cal.getMinimum(Calendar.DAY_OF_WEEK));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.getMaximum(int)'
-     */
-    public void testGetMaximum() {
-        Calendar cal = Calendar.getInstance();
-        assertEquals(7, cal.getMaximum(Calendar.DAY_OF_WEEK));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.getGreatestMinimum(int)'
-     */
-    public void testGetGreatestMinimum() {
-        Calendar cal = Calendar.getInstance();
-        assertEquals(1, cal.getGreatestMinimum(Calendar.DATE));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.getLeastMaximum(int)'
-     */
-    public void testGetLeastMaximum() {
-        Calendar cal = Calendar.getInstance();
-        assertEquals(28, cal.getLeastMaximum(Calendar.DATE));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.getDayOfWeekType(int)'
-     */
-    public void testGetDayOfWeekType() {
-        Calendar cal = Calendar.getInstance(Locale.US);
-        assertEquals(Calendar.WEEKDAY, cal.getDayOfWeekType(Calendar.FRIDAY));
-        assertEquals(Calendar.WEEKEND, cal.getDayOfWeekType(Calendar.SATURDAY));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.getWeekendTransition(int)'
-     */
-    public void testGetWeekendTransition() {
-        Calendar cal = Calendar.getInstance(Locale.US);
-        try {
-            cal.getWeekendTransition(Calendar.WEEKEND_ONSET);
-            fail("expected IllegalArgumentException from getWeekendTransition");
-        }
-        catch (UnsupportedOperationException e) {
-            // ok
-        }
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.isWeekend(Date)'
-     */
-    public void testIsWeekendDate() {
-        Calendar cal = Calendar.getInstance(Locale.US);
-        cal.set(Calendar.DAY_OF_WEEK, Calendar.SATURDAY);
-        assertTrue(cal.isWeekend(cal.getTime()));
-        cal.set(Calendar.DAY_OF_WEEK, Calendar.WEDNESDAY);
-        assertFalse(cal.isWeekend(cal.getTime()));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.isWeekend()'
-     */
-    public void testIsWeekend() {
-        Calendar cal = Calendar.getInstance(Locale.US);
-        cal.set(Calendar.DAY_OF_WEEK, Calendar.SATURDAY);
-        assertTrue(cal.isWeekend());
-        cal.set(Calendar.DAY_OF_WEEK, Calendar.WEDNESDAY);
-        assertFalse(cal.isWeekend());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.clone()'
-     */
-    public void testClone() {
-        // tested by testHashCode
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.toString()'
-     */
-    public void testToString() {
-        Calendar cal = Calendar.getInstance();
-        assertNotNull(cal.toString());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.Calendar.getType()'
-     */
-    public void testGetType() {
-        Calendar cal = Calendar.getInstance(Locale.US);
-        assertEquals("gregorian", cal.getType());
-    }
-}
+/*
+ *******************************************************************************
+ * Copyright (C) 2006-2011, International Business Machines Corporation and    *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+
+package com.ibm.icu.tests;
+
+import java.util.Date;
+import java.util.Locale;
+
+import com.ibm.icu.text.DateFormat;
+import com.ibm.icu.util.Calendar;
+import com.ibm.icu.util.TimeZone;
+import com.ibm.icu.util.ULocale;
+
+public class CalendarTest extends ICUTestCase {
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.hashCode()'
+     */
+    public void testHashCode() {
+        Calendar cal1 = Calendar.getInstance();
+        Calendar cal2 = Calendar.getInstance();
+        Calendar cal3 = Calendar.getInstance();
+
+        long t = System.currentTimeMillis();
+        cal1.setTimeInMillis(t);
+        cal2.setTimeInMillis(t);
+        cal3.setTimeInMillis(t);
+
+        cal3.setMinimalDaysInFirstWeek(cal3.getMinimalDaysInFirstWeek()+1);
+        testEHCS(cal1, cal2, cal3);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.Calendar(Calendar)'
+     */
+    public void testCalendar() {
+        // tested implicitly everywhere
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.getInstance()'
+     */
+    public void testGetInstance() {
+        // tested by testEHCS
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.getInstance(TimeZone)'
+     */
+    public void testGetInstanceTimeZone() {
+        TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
+        Calendar cal = Calendar.getInstance(tz);
+        assertNotNull(cal);
+        assertNotNull(cal.getTime());
+        assertEquals(tz, cal.getTimeZone());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.getInstance(Locale)'
+     */
+    public void testGetInstanceLocale() {
+        Calendar cal = Calendar.getInstance(Locale.US);
+        assertNotNull(cal);
+        assertNotNull(cal.getTime());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.getInstance(ULocale)'
+     */
+    public void testGetInstanceULocale() {
+        Calendar cal = Calendar.getInstance(ULocale.US);
+        assertNotNull(cal);
+        assertNotNull(cal.getTime());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.getInstance(TimeZone, Locale)'
+     */
+    public void testGetInstanceTimeZoneLocale() {
+        TimeZone tz = TimeZone.getTimeZone("America/New_York");
+        Calendar cal = Calendar.getInstance(tz, Locale.US);
+        assertNotNull(cal);
+        assertNotNull(cal.getTime());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.getInstance(TimeZone, ULocale)'
+     */
+    public void testGetInstanceTimeZoneULocale() {
+        TimeZone tz = TimeZone.getTimeZone("America/New_York");
+        Calendar cal = Calendar.getInstance(tz, ULocale.US);
+        assertNotNull(cal);
+        assertNotNull(cal.getTime());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.getAvailableLocales()'
+     */
+    public void testGetAvailableLocales() {
+        assertNotNull(Calendar.getAvailableLocales());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.getAvailableULocales()'
+     */
+    public void testGetAvailableULocales() {
+        assertNotNull(Calendar.getAvailableULocales());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.getTime()'
+     */
+    public void testGetTime() {
+        Calendar cal = Calendar.getInstance();
+        assertNotNull(cal.getTime());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.setTime(Date)'
+     */
+    public void testSetTime() {
+        Calendar cal = Calendar.getInstance();
+        cal.clear();
+        cal.set(2006, 0, 20, 9, 30, 0);
+        Date date = cal.getTime();
+        cal = Calendar.getInstance();
+        cal.setTime(date);
+        assertEquals(date, cal.getTime());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.getTimeInMillis()'
+     */
+    public void testGetTimeInMillis() {
+        Calendar cal = Calendar.getInstance();
+        assertTrue(0 != cal.getTimeInMillis());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.setTimeInMillis(long)'
+     */
+    public void testSetTimeInMillis() {
+        Calendar cal = Calendar.getInstance();
+        cal.clear();
+        cal.set(2006, 0, 20, 9, 30, 0);
+        long millis = cal.getTimeInMillis();
+        Date date = cal.getTime();
+        
+        cal = Calendar.getInstance();
+        cal.setTimeInMillis(millis);
+        
+        assertEquals(date, cal.getTime());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.get(int)'
+     */
+    public void testGet() {
+        Calendar cal = Calendar.getInstance();
+        cal.clear();
+        cal.set(2006, 0, 20, 9, 30, 0);
+        assertEquals(0, cal.get(Calendar.MONTH));
+        assertEquals(20, cal.get(Calendar.DAY_OF_MONTH));
+        assertEquals(30, cal.get(Calendar.MINUTE));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.set(int, int)'
+     */
+    public void testSetIntInt() {
+        Calendar cal = Calendar.getInstance();
+        cal.set(Calendar.YEAR, 1977);
+        assertEquals(1977, cal.get(Calendar.YEAR));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.set(int, int, int)'
+     */
+    public void testSetIntIntInt() {
+        Calendar cal = Calendar.getInstance();
+        cal.set(1997, 9, 15);
+        assertEquals(15, cal.get(Calendar.DATE));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.set(int, int, int, int, int)'
+     */
+    public void testSetIntIntIntIntInt() {
+        Calendar cal = Calendar.getInstance();
+        cal.set(1997, 9, 15, 14, 25);
+        assertEquals(25, cal.get(Calendar.MINUTE));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.set(int, int, int, int, int, int)'
+     */
+    public void testSetIntIntIntIntIntInt() {
+        Calendar cal = Calendar.getInstance();
+        cal.set(1997, 9, 15, 14, 25, 51);
+        assertEquals(51, cal.get(Calendar.SECOND));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.clear()'
+     */
+    public void testClear() {
+        Calendar cal = Calendar.getInstance();
+        cal.set(1997, 9, 15, 14, 25, 51);
+        cal.clear();
+        assertEquals(0, cal.get(Calendar.MONTH));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.clear(int)'
+     */
+    public void testClearInt() {
+        Calendar cal = Calendar.getInstance();
+        cal.set(1997, 9, 15, 14, 25, 51);
+        assertTrue(cal.isSet(Calendar.DAY_OF_MONTH));
+        cal.clear(Calendar.DAY_OF_MONTH);
+        assertFalse(cal.isSet(Calendar.DAY_OF_MONTH));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.isSet(int)'
+     */
+    public void testIsSet() {
+        // see testClearInt
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.equals(Object)'
+     */
+    public void testEqualsObject() {
+        // tested by testHashCode
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.isEquivalentTo(Calendar)'
+     */
+    public void testIsEquivalentTo() {
+        Calendar cal = Calendar.getInstance();
+        Calendar cal2 = Calendar.getInstance();
+        cal2.set(1994, 6, 21, 8, 7);
+        assertTrue(cal.isEquivalentTo(cal2));
+        cal.setTimeZone(TimeZone.getTimeZone("CST"));
+        cal2.setTimeZone(TimeZone.getTimeZone("PDT"));
+        assertFalse(cal.isEquivalentTo(cal2));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.before(Object)'
+     */
+    public void testBefore() {
+        Calendar cal = Calendar.getInstance();
+        cal.set(Calendar.YEAR, 1990);
+        assertTrue(cal.before(new Date()));
+        assertTrue(cal.before(Calendar.getInstance()));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.after(Object)'
+     */
+    public void testAfter() {
+        Calendar cal = Calendar.getInstance();
+        cal.set(Calendar.YEAR, 3058);
+        assertTrue(cal.after(new Date()));
+        assertTrue(cal.after(Calendar.getInstance()));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.getActualMaximum(int)'
+     */
+    public void testGetActualMaximum() {
+        Calendar cal = Calendar.getInstance(Locale.US);
+        assertEquals(11, cal.getActualMaximum(Calendar.MONTH));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.getActualMinimum(int)'
+     */
+    public void testGetActualMinimum() {
+        Calendar cal = Calendar.getInstance(Locale.US);
+        assertEquals(0, cal.getActualMinimum(Calendar.MONTH));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.roll(int, boolean)'
+     */
+    public void testRollIntBoolean() {
+        Calendar cal = Calendar.getInstance(Locale.US);
+        cal.set(1997, 1, 27);
+        cal.roll(Calendar.DATE, true);
+        assertEquals(28, cal.get(Calendar.DATE));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.roll(int, int)'
+     */
+    public void testRollIntInt() {
+        Calendar cal = Calendar.getInstance(Locale.US);
+        cal.set(1997, 1, 27);
+        cal.roll(Calendar.DATE, 3);
+        assertEquals(2, cal.get(Calendar.DATE));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.add(int, int)'
+     */
+    public void testAdd() {
+        Calendar cal = Calendar.getInstance(Locale.US);
+        cal.set(1997, 1, 27);
+        cal.add(Calendar.DATE, 3);
+        assertEquals(2, cal.get(Calendar.DATE));
+        assertEquals(2, cal.get(Calendar.MONTH));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.getDisplayName(Locale)'
+     */
+    public void testGetDisplayNameLocale() {
+        Calendar cal = Calendar.getInstance();
+        assertEquals("Gregorian Calendar", cal.getDisplayName(Locale.US));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.getDisplayName(ULocale)'
+     */
+    public void testGetDisplayNameULocale() {
+        Calendar cal = Calendar.getInstance();
+        assertEquals("Gregorian Calendar", cal.getDisplayName(ULocale.US));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.compareTo(Calendar)'
+     */
+    public void testCompareToCalendar() {
+        Calendar cal = Calendar.getInstance();
+        cal.set(Calendar.YEAR, 1990);
+        assertTrue(0 > cal.compareTo(Calendar.getInstance()));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.compareTo(Object)'
+     */
+    public void testCompareToObject() {
+        Calendar cal = Calendar.getInstance();
+        cal.set(Calendar.YEAR, 1990);
+        assertTrue(0 > cal.compareTo(Calendar.getInstance()));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.getDateTimeFormat(int, int, Locale)'
+     */
+    public void testGetDateTimeFormatIntIntLocale() {
+        Calendar cal = Calendar.getInstance();
+        cal.set(1990, 8, 16, 20, 3);
+        DateFormat df = cal.getDateTimeFormat(DateFormat.LONG, DateFormat.SHORT, Locale.US);
+        assertEquals("September 16, 1990 8:03 PM", df.format(cal));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.getDateTimeFormat(int, int, ULocale)'
+     */
+    public void testGetDateTimeFormatIntIntULocale() {
+        Calendar cal = Calendar.getInstance();
+        cal.set(1990, 8, 16, 20, 3);
+        DateFormat df = cal.getDateTimeFormat(DateFormat.LONG, DateFormat.SHORT, ULocale.US);
+        assertEquals("September 16, 1990 8:03 PM", df.format(cal));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.fieldDifference(Date, int)'
+     */
+    public void testFieldDifference() {
+        Calendar cal = Calendar.getInstance();
+        cal.set(Calendar.DAY_OF_MONTH, 0);
+        Date date = cal.getTime();
+        cal.add(Calendar.DAY_OF_MONTH, 5);
+        assertEquals(-5, cal.fieldDifference(date, Calendar.DAY_OF_MONTH));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.getTimeZone()'
+     */
+    public void testGetTimeZone() {
+        Calendar cal = Calendar.getInstance();
+        assertNotNull(cal.getTimeZone());
+    }
+    
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.setTimeZone(TimeZone)'
+     */
+    public void testSetTimeZone() {
+        Calendar cal = Calendar.getInstance();
+        TimeZone value1 = cal.getTimeZone();
+        String tzn = "PDT".equals(value1.getID()) ? "CST" : "PDT";
+        TimeZone value2 = TimeZone.getTimeZone(tzn);
+        cal.setTimeZone(value2);
+        TimeZone result = cal.getTimeZone();
+        assertNotEqual(value1, result);
+        assertEquals(value2, result);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.setLenient(boolean)'
+     */
+    public void testSetLenient() {
+        Calendar cal = Calendar.getInstance();
+        boolean lenient = cal.isLenient();
+        cal.setLenient(!lenient);
+        assertFalse(lenient == cal.isLenient());
+        
+        // not testing if it has the expected effect
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.isLenient()'
+     */
+    public void testIsLenient() {
+        // tested by testSetLenient
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.setFirstDayOfWeek(int)'
+     */
+    public void testSetFirstDayOfWeek() {
+        Calendar cal = Calendar.getInstance();
+        int firstDay = cal.getFirstDayOfWeek();
+        cal.setFirstDayOfWeek(firstDay+1);
+        assertEquals(firstDay+1, cal.getFirstDayOfWeek());
+
+        // don't test functionality
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.getFirstDayOfWeek()'
+     */
+    public void testGetFirstDayOfWeek() {
+        // tested by testSetFirstDayOfWeek
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.setMinimalDaysInFirstWeek(int)'
+     */
+    public void testSetMinimalDaysInFirstWeek() {
+        Calendar cal = Calendar.getInstance();
+        int firstDay = cal.getMinimalDaysInFirstWeek();
+        cal.setMinimalDaysInFirstWeek(firstDay+1);
+        assertEquals(firstDay+1, cal.getMinimalDaysInFirstWeek());
+
+        // don't test functionality
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.getMinimalDaysInFirstWeek()'
+     */
+    public void testGetMinimalDaysInFirstWeek() {
+        // tested by testSetMinimalDaysInFirstWeek
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.getMinimum(int)'
+     */
+    public void testGetMinimum() {
+        Calendar cal = Calendar.getInstance();
+        assertEquals(1, cal.getMinimum(Calendar.DAY_OF_WEEK));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.getMaximum(int)'
+     */
+    public void testGetMaximum() {
+        Calendar cal = Calendar.getInstance();
+        assertEquals(7, cal.getMaximum(Calendar.DAY_OF_WEEK));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.getGreatestMinimum(int)'
+     */
+    public void testGetGreatestMinimum() {
+        Calendar cal = Calendar.getInstance();
+        assertEquals(1, cal.getGreatestMinimum(Calendar.DATE));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.getLeastMaximum(int)'
+     */
+    public void testGetLeastMaximum() {
+        Calendar cal = Calendar.getInstance();
+        assertEquals(28, cal.getLeastMaximum(Calendar.DATE));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.getDayOfWeekType(int)'
+     */
+    public void testGetDayOfWeekType() {
+        Calendar cal = Calendar.getInstance(Locale.US);
+        assertEquals(Calendar.WEEKDAY, cal.getDayOfWeekType(Calendar.FRIDAY));
+        assertEquals(Calendar.WEEKEND, cal.getDayOfWeekType(Calendar.SATURDAY));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.getWeekendTransition(int)'
+     */
+    public void testGetWeekendTransition() {
+        Calendar cal = Calendar.getInstance(Locale.US);
+        try {
+            cal.getWeekendTransition(Calendar.WEEKEND_ONSET);
+            fail("expected IllegalArgumentException from getWeekendTransition");
+        }
+        catch (UnsupportedOperationException e) {
+            // ok
+        }
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.isWeekend(Date)'
+     */
+    public void testIsWeekendDate() {
+        Calendar cal = Calendar.getInstance(Locale.US);
+        cal.set(Calendar.DAY_OF_WEEK, Calendar.SATURDAY);
+        assertTrue(cal.isWeekend(cal.getTime()));
+        cal.set(Calendar.DAY_OF_WEEK, Calendar.WEDNESDAY);
+        assertFalse(cal.isWeekend(cal.getTime()));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.isWeekend()'
+     */
+    public void testIsWeekend() {
+        Calendar cal = Calendar.getInstance(Locale.US);
+        cal.set(Calendar.DAY_OF_WEEK, Calendar.SATURDAY);
+        assertTrue(cal.isWeekend());
+        cal.set(Calendar.DAY_OF_WEEK, Calendar.WEDNESDAY);
+        assertFalse(cal.isWeekend());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.clone()'
+     */
+    public void testClone() {
+        // tested by testHashCode
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.toString()'
+     */
+    public void testToString() {
+        Calendar cal = Calendar.getInstance();
+        assertNotNull(cal.toString());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.Calendar.getType()'
+     */
+    public void testGetType() {
+        Calendar cal = Calendar.getInstance(Locale.US);
+        assertEquals("gregorian", cal.getType());
+    }
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/CollationKeyTest.java b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/CollationKeyTest.java
index 45725be..a1afd34 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/CollationKeyTest.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/CollationKeyTest.java
@@ -1,102 +1,102 @@
-/*
- *******************************************************************************
- * Copyright (C) 2006-2011, International Business Machines Corporation and    *
- * others. All Rights Reserved.                                                *
- *******************************************************************************
- */
-
-package com.ibm.icu.tests;
-
-import com.ibm.icu.text.CollationKey;
-import com.ibm.icu.text.Collator;
-
-public class CollationKeyTest extends ICUTestCase {
-
-    /*
-     * Test method for 'com.ibm.icu.text.CollationKey.hashCode()'
-     */
-    public void testHashCode() {
-        Collator c = Collator.getInstance();
-        c.setStrength(Collator.PRIMARY);
-        CollationKey k1 = c.getCollationKey("This");
-        CollationKey k2 = c.getCollationKey("this");
-        c.setStrength(Collator.TERTIARY);
-        CollationKey kn = c.getCollationKey("this");
-        testEHCS(k1, k2, kn);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.CollationKey.CollationKey(CollationKey)'
-     */
-    public void testCollationKey() {
-        // implicitly tested everywhere
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.CollationKey.compareTo(CollationKey)'
-     */
-    public void testCompareToCollationKey() {
-        Collator c = Collator.getInstance();
-        c.setStrength(Collator.PRIMARY);
-        CollationKey k1 = c.getCollationKey("This");
-        CollationKey k2 = c.getCollationKey("this");
-        c.setStrength(Collator.TERTIARY);
-        CollationKey k3 = c.getCollationKey("this");
-        assertTrue(0 == k1.compareTo(k2));
-        assertFalse(0 == k1.compareTo(k3));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.CollationKey.compareTo(Object)'
-     */
-    public void testCompareToObject() {
-        Collator c = Collator.getInstance();
-        c.setStrength(Collator.PRIMARY);
-        CollationKey k1 = c.getCollationKey("This");
-        CollationKey k2 = c.getCollationKey("this");
-        assertTrue(0 == k1.compareTo(k2));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.CollationKey.equals(Object)'
-     */
-    public void testEqualsObject() {
-        Collator c = Collator.getInstance();
-        c.setStrength(Collator.PRIMARY);
-        CollationKey k1 = c.getCollationKey("This");
-        CollationKey k2 = c.getCollationKey("this");
-        assertTrue(k1.equals((Object)k2));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.CollationKey.toString()'
-     */
-    public void testToString() {
-        Collator c = Collator.getInstance();
-        c.setStrength(Collator.PRIMARY);
-        CollationKey k1 = c.getCollationKey("This");
-        assertNotNull(k1.toString());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.CollationKey.getSourceString()'
-     */
-    public void testGetSourceString() {
-        Collator c = Collator.getInstance();
-        c.setStrength(Collator.PRIMARY);
-        CollationKey k1 = c.getCollationKey("This");
-        assertEquals("This", k1.getSourceString());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.CollationKey.toByteArray()'
-     */
-    public void testToByteArray() {
-        Collator c = Collator.getInstance();
-        c.setStrength(Collator.PRIMARY);
-        CollationKey k1 = c.getCollationKey("This");
-        byte[] key = k1.toByteArray();
-        assertNotNull(key);
-        assertTrue(0 < key.length);
-    }
-}
+/*
+ *******************************************************************************
+ * Copyright (C) 2006-2011, International Business Machines Corporation and    *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+
+package com.ibm.icu.tests;
+
+import com.ibm.icu.text.CollationKey;
+import com.ibm.icu.text.Collator;
+
+public class CollationKeyTest extends ICUTestCase {
+
+    /*
+     * Test method for 'com.ibm.icu.text.CollationKey.hashCode()'
+     */
+    public void testHashCode() {
+        Collator c = Collator.getInstance();
+        c.setStrength(Collator.PRIMARY);
+        CollationKey k1 = c.getCollationKey("This");
+        CollationKey k2 = c.getCollationKey("this");
+        c.setStrength(Collator.TERTIARY);
+        CollationKey kn = c.getCollationKey("this");
+        testEHCS(k1, k2, kn);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.CollationKey.CollationKey(CollationKey)'
+     */
+    public void testCollationKey() {
+        // implicitly tested everywhere
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.CollationKey.compareTo(CollationKey)'
+     */
+    public void testCompareToCollationKey() {
+        Collator c = Collator.getInstance();
+        c.setStrength(Collator.PRIMARY);
+        CollationKey k1 = c.getCollationKey("This");
+        CollationKey k2 = c.getCollationKey("this");
+        c.setStrength(Collator.TERTIARY);
+        CollationKey k3 = c.getCollationKey("this");
+        assertTrue(0 == k1.compareTo(k2));
+        assertFalse(0 == k1.compareTo(k3));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.CollationKey.compareTo(Object)'
+     */
+    public void testCompareToObject() {
+        Collator c = Collator.getInstance();
+        c.setStrength(Collator.PRIMARY);
+        CollationKey k1 = c.getCollationKey("This");
+        CollationKey k2 = c.getCollationKey("this");
+        assertTrue(0 == k1.compareTo(k2));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.CollationKey.equals(Object)'
+     */
+    public void testEqualsObject() {
+        Collator c = Collator.getInstance();
+        c.setStrength(Collator.PRIMARY);
+        CollationKey k1 = c.getCollationKey("This");
+        CollationKey k2 = c.getCollationKey("this");
+        assertTrue(k1.equals((Object)k2));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.CollationKey.toString()'
+     */
+    public void testToString() {
+        Collator c = Collator.getInstance();
+        c.setStrength(Collator.PRIMARY);
+        CollationKey k1 = c.getCollationKey("This");
+        assertNotNull(k1.toString());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.CollationKey.getSourceString()'
+     */
+    public void testGetSourceString() {
+        Collator c = Collator.getInstance();
+        c.setStrength(Collator.PRIMARY);
+        CollationKey k1 = c.getCollationKey("This");
+        assertEquals("This", k1.getSourceString());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.CollationKey.toByteArray()'
+     */
+    public void testToByteArray() {
+        Collator c = Collator.getInstance();
+        c.setStrength(Collator.PRIMARY);
+        CollationKey k1 = c.getCollationKey("This");
+        byte[] key = k1.toByteArray();
+        assertNotNull(key);
+        assertTrue(0 < key.length);
+    }
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/CollatorTest.java b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/CollatorTest.java
index 08349f1..28f003d 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/CollatorTest.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/CollatorTest.java
@@ -1,205 +1,205 @@
-/*
- *******************************************************************************
- * Copyright (C) 2006-2011, International Business Machines Corporation and    *
- * others. All Rights Reserved.                                                *
- *******************************************************************************
- */
-
-package com.ibm.icu.tests;
-
-import java.util.Locale;
-
-import com.ibm.icu.text.CollationKey;
-import com.ibm.icu.text.Collator;
-import com.ibm.icu.util.ULocale;
-
-public class CollatorTest extends ICUTestCase {
-    private static final String s1 = "Fu\u0308nf"; // capital F + u + diaresis
-    private static final String s2 = "fu\u0308nf"; // u + diaresis
-    private static final String s3 = "f\u00fcnf"; // u-umlaut
-    private static final String s4 = "fu\u0308\u0316nf"; // u + diaresis above + grave below
-    private static final String s5 = "fu\u0316\u0308nf"; // u + grave below + diaresis above
-
-    /*
-     * Test method for 'com.ibm.icu.text.Collator.hashCode()'
-     */
-    public void testHashCode() {
-        Collator c = Collator.getInstance();
-        c.setStrength(Collator.SECONDARY);
-        Collator c2 = Collator.getInstance();
-        c2.setStrength(Collator.SECONDARY);
-        Collator cn = Collator.getInstance();
-        cn.setStrength(Collator.TERTIARY);
-        testEHCS(c, c2, cn);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.Collator.Collator(Collator)'
-     */
-    public void testCollator() {
-        // implicitly tested everywhere
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.Collator.setStrength(int)'
-     */
-    public void testSetStrength() {
-        Collator c = Collator.getInstance();
-        c.setStrength(Collator.PRIMARY);
-        assertTrue(0 == c.compare(s1, s2));
-        c.setStrength(Collator.SECONDARY);
-        assertTrue(0 == c.compare(s1, s2));
-        c.setStrength(Collator.TERTIARY);
-        assertTrue(0 < c.compare(s1, s2));
-        assertTrue(0 == c.compare(s2, s3));
-        c.setStrength(Collator.QUATERNARY);
-        assertTrue(0 > c.compare(s2, s3));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.Collator.setDecomposition(int)'
-     */
-    public void testSetDecomposition() {
-        Collator c = Collator.getInstance();
-        c.setStrength(Collator.TERTIARY);
-        assertTrue(0 != c.compare(s4, s5));
-        c.setDecomposition(Collator.IDENTICAL);
-        assertTrue(0 == c.compare(s4, s5));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.Collator.getInstance()'
-     */
-    public void testGetInstance() {
-        // implicitly tested everywhere
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.Collator.getInstance(ULocale)'
-     */
-    public void testGetInstanceULocale() {
-        Collator c = Collator.getInstance(ULocale.GERMANY);
-        assertNotNull(c);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.Collator.getInstance(Locale)'
-     */
-    public void testGetInstanceLocale() {
-        Collator c = Collator.getInstance(Locale.GERMANY);
-        assertNotNull(c);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.Collator.getAvailableLocales()'
-     */
-    public void testGetAvailableLocales() {
-        assertNotNull(Collator.getAvailableLocales());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.Collator.getAvailableULocales()'
-     */
-    public void testGetAvailableULocales() {
-        assertNotNull(Collator.getAvailableULocales());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.Collator.getKeywords()'
-     */
-    public void testGetKeywords() {
-        assertEquals(0, Collator.getKeywords().length);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.Collator.getKeywordValues(String)'
-     */
-    public void testGetKeywordValues() {
-        assertEquals(0, Collator.getKeywordValues("").length);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.Collator.getStrength()'
-     */
-    public void testGetStrength() {
-        Collator c = Collator.getInstance();
-        c.setStrength(Collator.PRIMARY);
-        assertEquals(Collator.PRIMARY, c.getStrength());
-        c.setStrength(Collator.SECONDARY);
-        assertEquals(Collator.SECONDARY, c.getStrength());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.Collator.getDecomposition()'
-     */
-    public void testGetDecomposition() {
-        Collator c = Collator.getInstance();
-        c.setDecomposition(Collator.CANONICAL_DECOMPOSITION);
-        assertEquals(Collator.CANONICAL_DECOMPOSITION, c.getDecomposition());
-        c.setDecomposition(Collator.NO_DECOMPOSITION);
-        assertEquals(Collator.NO_DECOMPOSITION, c.getDecomposition());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.Collator.compare(Object, Object)'
-     */
-    public void testCompareObjectObject() {
-        Collator c = Collator.getInstance();
-        c.setStrength(Collator.PRIMARY);
-        assertTrue(0 == c.compare((Object)s1, (Object)s2));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.Collator.equals(String, String)'
-     */
-    public void testEqualsStringString() {
-        Collator c = Collator.getInstance();
-        c.setStrength(Collator.PRIMARY);
-        assertTrue(c.equals(s1, s2));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.Collator.compare(String, String)'
-     */
-    public void testCompareStringString() {
-        Collator c = Collator.getInstance();
-        c.setStrength(Collator.PRIMARY);
-        assertTrue(0 == c.compare(s1, s2));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.Collator.getCollationKey(String)'
-     */
-    public void testGetCollationKey() {
-        Collator c = Collator.getInstance();
-        c.setStrength(Collator.PRIMARY);
-        CollationKey k1 = c.getCollationKey(s1);
-        CollationKey k2 = c.getCollationKey(s2);
-        assertTrue(k1.equals(k2));
-        c.setStrength(Collator.TERTIARY);
-        k1 = c.getCollationKey(s1);
-        k2 = c.getCollationKey(s2);
-        assertFalse(k1.equals(k2));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.Collator.toString()'
-     */
-    public void testToString() {
-        assertNotNull(Collator.getInstance().toString());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.Collator.clone()'
-     */
-    public void testClone() {
-        // tested above
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.Collator.equals(Object)'
-     */
-    public void testEqualsObject() {
-        // tested above
-    }
-}
+/*
+ *******************************************************************************
+ * Copyright (C) 2006-2011, International Business Machines Corporation and    *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+
+package com.ibm.icu.tests;
+
+import java.util.Locale;
+
+import com.ibm.icu.text.CollationKey;
+import com.ibm.icu.text.Collator;
+import com.ibm.icu.util.ULocale;
+
+public class CollatorTest extends ICUTestCase {
+    private static final String s1 = "Fu\u0308nf"; // capital F + u + diaresis
+    private static final String s2 = "fu\u0308nf"; // u + diaresis
+    private static final String s3 = "f\u00fcnf"; // u-umlaut
+    private static final String s4 = "fu\u0308\u0316nf"; // u + diaresis above + grave below
+    private static final String s5 = "fu\u0316\u0308nf"; // u + grave below + diaresis above
+
+    /*
+     * Test method for 'com.ibm.icu.text.Collator.hashCode()'
+     */
+    public void testHashCode() {
+        Collator c = Collator.getInstance();
+        c.setStrength(Collator.SECONDARY);
+        Collator c2 = Collator.getInstance();
+        c2.setStrength(Collator.SECONDARY);
+        Collator cn = Collator.getInstance();
+        cn.setStrength(Collator.TERTIARY);
+        testEHCS(c, c2, cn);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.Collator.Collator(Collator)'
+     */
+    public void testCollator() {
+        // implicitly tested everywhere
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.Collator.setStrength(int)'
+     */
+    public void testSetStrength() {
+        Collator c = Collator.getInstance();
+        c.setStrength(Collator.PRIMARY);
+        assertTrue(0 == c.compare(s1, s2));
+        c.setStrength(Collator.SECONDARY);
+        assertTrue(0 == c.compare(s1, s2));
+        c.setStrength(Collator.TERTIARY);
+        assertTrue(0 < c.compare(s1, s2));
+        assertTrue(0 == c.compare(s2, s3));
+        c.setStrength(Collator.QUATERNARY);
+        assertTrue(0 > c.compare(s2, s3));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.Collator.setDecomposition(int)'
+     */
+    public void testSetDecomposition() {
+        Collator c = Collator.getInstance();
+        c.setStrength(Collator.TERTIARY);
+        assertTrue(0 != c.compare(s4, s5));
+        c.setDecomposition(Collator.IDENTICAL);
+        assertTrue(0 == c.compare(s4, s5));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.Collator.getInstance()'
+     */
+    public void testGetInstance() {
+        // implicitly tested everywhere
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.Collator.getInstance(ULocale)'
+     */
+    public void testGetInstanceULocale() {
+        Collator c = Collator.getInstance(ULocale.GERMANY);
+        assertNotNull(c);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.Collator.getInstance(Locale)'
+     */
+    public void testGetInstanceLocale() {
+        Collator c = Collator.getInstance(Locale.GERMANY);
+        assertNotNull(c);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.Collator.getAvailableLocales()'
+     */
+    public void testGetAvailableLocales() {
+        assertNotNull(Collator.getAvailableLocales());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.Collator.getAvailableULocales()'
+     */
+    public void testGetAvailableULocales() {
+        assertNotNull(Collator.getAvailableULocales());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.Collator.getKeywords()'
+     */
+    public void testGetKeywords() {
+        assertEquals(0, Collator.getKeywords().length);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.Collator.getKeywordValues(String)'
+     */
+    public void testGetKeywordValues() {
+        assertEquals(0, Collator.getKeywordValues("").length);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.Collator.getStrength()'
+     */
+    public void testGetStrength() {
+        Collator c = Collator.getInstance();
+        c.setStrength(Collator.PRIMARY);
+        assertEquals(Collator.PRIMARY, c.getStrength());
+        c.setStrength(Collator.SECONDARY);
+        assertEquals(Collator.SECONDARY, c.getStrength());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.Collator.getDecomposition()'
+     */
+    public void testGetDecomposition() {
+        Collator c = Collator.getInstance();
+        c.setDecomposition(Collator.CANONICAL_DECOMPOSITION);
+        assertEquals(Collator.CANONICAL_DECOMPOSITION, c.getDecomposition());
+        c.setDecomposition(Collator.NO_DECOMPOSITION);
+        assertEquals(Collator.NO_DECOMPOSITION, c.getDecomposition());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.Collator.compare(Object, Object)'
+     */
+    public void testCompareObjectObject() {
+        Collator c = Collator.getInstance();
+        c.setStrength(Collator.PRIMARY);
+        assertTrue(0 == c.compare((Object)s1, (Object)s2));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.Collator.equals(String, String)'
+     */
+    public void testEqualsStringString() {
+        Collator c = Collator.getInstance();
+        c.setStrength(Collator.PRIMARY);
+        assertTrue(c.equals(s1, s2));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.Collator.compare(String, String)'
+     */
+    public void testCompareStringString() {
+        Collator c = Collator.getInstance();
+        c.setStrength(Collator.PRIMARY);
+        assertTrue(0 == c.compare(s1, s2));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.Collator.getCollationKey(String)'
+     */
+    public void testGetCollationKey() {
+        Collator c = Collator.getInstance();
+        c.setStrength(Collator.PRIMARY);
+        CollationKey k1 = c.getCollationKey(s1);
+        CollationKey k2 = c.getCollationKey(s2);
+        assertTrue(k1.equals(k2));
+        c.setStrength(Collator.TERTIARY);
+        k1 = c.getCollationKey(s1);
+        k2 = c.getCollationKey(s2);
+        assertFalse(k1.equals(k2));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.Collator.toString()'
+     */
+    public void testToString() {
+        assertNotNull(Collator.getInstance().toString());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.Collator.clone()'
+     */
+    public void testClone() {
+        // tested above
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.Collator.equals(Object)'
+     */
+    public void testEqualsObject() {
+        // tested above
+    }
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/DateFormatSymbolsTest.java b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/DateFormatSymbolsTest.java
index 2021969..4636e69 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/DateFormatSymbolsTest.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/DateFormatSymbolsTest.java
@@ -1,257 +1,257 @@
-/*
- *******************************************************************************
- * Copyright (C) 2006-2011, International Business Machines Corporation and    *
- * others. All Rights Reserved.                                                *
- *******************************************************************************
- */
-
-package com.ibm.icu.tests;
-
-import java.util.Locale;
-
-import com.ibm.icu.text.DateFormatSymbols;
-import com.ibm.icu.util.ULocale;
-
-public class DateFormatSymbolsTest extends ICUTestCase {
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormatSymbols.hashCode()'
-     */
-    public void testHashCode() {
-        DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
-        DateFormatSymbols dfs2 = new DateFormatSymbols(ULocale.US);
-        DateFormatSymbols dfsn = new DateFormatSymbols(Locale.US);
-        dfsn.setAmPmStrings(new String[] { "sw", "xw" });
-        testEHCS(dfs, dfs2, dfsn);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormatSymbols.DateFormatSymbols(DateFormatSymbols)'
-     */
-    public void testDateFormatSymbolsDateFormatSymbols() {
-        // implicitly tested everywhere
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormatSymbols.DateFormatSymbols()'
-     */
-    public void testDateFormatSymbols() {
-        DateFormatSymbols dfs = new DateFormatSymbols();
-        assertNotNull(dfs.getWeekdays());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormatSymbols.DateFormatSymbols(Locale)'
-     */
-    public void testDateFormatSymbolsLocale() {
-        DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
-        assertNotNull(dfs.getWeekdays());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormatSymbols.DateFormatSymbols(ULocale)'
-     */
-    public void testDateFormatSymbolsULocale() {
-        DateFormatSymbols dfs = new DateFormatSymbols(ULocale.US);
-        assertNotNull(dfs.getWeekdays());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormatSymbols.getEras()'
-     */
-    public void testGetEras() {
-        DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
-        assertNotNull(dfs.getEras());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormatSymbols.setEras(String[])'
-     */
-    public void testSetEras() {
-        DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
-        String[] oldvalue = dfs.getEras();
-        String[] newvalue = (String[])oldvalue.clone();
-        newvalue[0] = newvalue[0] + "!";
-        dfs.setEras(newvalue);
-        String[] result = dfs.getEras();
-        assertArraysNotEqual(oldvalue, result);
-        assertArraysEqual(newvalue, result);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormatSymbols.getMonths()'
-     */
-    public void testGetMonths() {
-        DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
-        assertNotNull(dfs.getMonths());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormatSymbols.setMonths(String[])'
-     */
-    public void testSetMonths() {
-        DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
-        String[] oldvalue = dfs.getMonths();
-        String[] newvalue = (String[])oldvalue.clone();
-        newvalue[0] = newvalue[0] + "!";
-        dfs.setMonths(newvalue);
-        String[] result = dfs.getMonths();
-        assertArraysNotEqual(oldvalue, result);
-        assertArraysEqual(newvalue, result);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormatSymbols.getShortMonths()'
-     */
-    public void testGetShortMonths() {
-        DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
-        assertNotNull(dfs.getShortMonths());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormatSymbols.setShortMonths(String[])'
-     */
-    public void testSetShortMonths() {
-        DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
-        String[] oldvalue = dfs.getShortMonths();
-        String[] newvalue = (String[])oldvalue.clone();
-        newvalue[0] = newvalue[0] + "!";
-        dfs.setShortMonths(newvalue);
-        String[] result = dfs.getShortMonths();
-        assertArraysNotEqual(oldvalue, result);
-        assertArraysEqual(newvalue, result);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormatSymbols.getWeekdays()'
-     */
-    public void testGetWeekdays() {
-        DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
-        assertNotNull(dfs.getShortMonths());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormatSymbols.setWeekdays(String[])'
-     */
-    public void testSetWeekdays() {
-        DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
-        String[] oldvalue = dfs.getWeekdays();
-        String[] newvalue = (String[])oldvalue.clone();
-        newvalue[0] = newvalue[0] + "!";
-        dfs.setWeekdays(newvalue);
-        String[] result = dfs.getWeekdays();
-        assertArraysNotEqual(oldvalue, result);
-        assertArraysEqual(newvalue, result);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormatSymbols.getShortWeekdays()'
-     */
-    public void testGetShortWeekdays() {
-        DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
-        assertNotNull(dfs.getShortWeekdays());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormatSymbols.setShortWeekdays(String[])'
-     */
-    public void testSetShortWeekdays() {
-        DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
-        String[] oldvalue = dfs.getShortWeekdays();
-        String[] newvalue = (String[])oldvalue.clone();
-        newvalue[0] = newvalue[0] + "!";
-        dfs.setShortWeekdays(newvalue);
-        String[] result = dfs.getShortWeekdays();
-        assertArraysNotEqual(oldvalue, result);
-        assertArraysEqual(newvalue, result);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormatSymbols.getAmPmStrings()'
-     */
-    public void testGetAmPmStrings() {
-        DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
-        assertNotNull(dfs.getAmPmStrings());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormatSymbols.setAmPmStrings(String[])'
-     */
-    public void testSetAmPmStrings() {
-        DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
-        String[] oldvalue = dfs.getAmPmStrings();
-        String[] newvalue = (String[])oldvalue.clone();
-        newvalue[0] = newvalue[0] + "!";
-        dfs.setAmPmStrings(newvalue);
-        String[] result = dfs.getAmPmStrings();
-        assertArraysNotEqual(oldvalue, result);
-        assertArraysEqual(newvalue, result);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormatSymbols.getZoneStrings()'
-     */
-    public void testGetZoneStrings() {
-        DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
-        assertNotNull(dfs.getZoneStrings());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormatSymbols.setZoneStrings(String[][])'
-     */
-    public void testSetZoneStrings() {
-        DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
-        String[][] oldvalue = dfs.getZoneStrings();
-        String[][] newvalue = (String[][])cloneComplex(oldvalue);
-        newvalue[0][0] = newvalue[0][0] + "!";
-        dfs.setZoneStrings(newvalue);
-        String[][] result = dfs.getZoneStrings();
-        assertArraysNotEqual(oldvalue, result);
-        assertArraysEqual(newvalue, result);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormatSymbols.getLocalPatternChars()'
-     */
-    public void testGetLocalPatternChars() {
-        DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
-        assertNotNull(dfs.getLocalPatternChars());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormatSymbols.setLocalPatternChars(String)'
-     */
-    public void testSetLocalPatternChars() {
-        DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
-        String pat = dfs.getLocalPatternChars();
-        StringBuffer buf = new StringBuffer(pat);
-        buf.setCharAt(0, (char)(pat.charAt(0) + 1));
-        String pat2 = buf.toString();
-        dfs.setLocalPatternChars(pat2);
-        String pat3 = dfs.getLocalPatternChars();
-        assertNotEqual(pat, pat2);
-        assertEquals(pat2, pat3);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormatSymbols.toString()'
-     */
-    public void testToString() {
-        DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
-        assertNotNull(dfs.toString());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormatSymbols.clone()'
-     */
-    public void testClone() {
-        // tested by testHashCode
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormatSymbols.equals(Object)'
-     */
-    public void testEqualsObject() {
-        // tested by testHashCode
-    }
-}
+/*
+ *******************************************************************************
+ * Copyright (C) 2006-2011, International Business Machines Corporation and    *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+
+package com.ibm.icu.tests;
+
+import java.util.Locale;
+
+import com.ibm.icu.text.DateFormatSymbols;
+import com.ibm.icu.util.ULocale;
+
+public class DateFormatSymbolsTest extends ICUTestCase {
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormatSymbols.hashCode()'
+     */
+    public void testHashCode() {
+        DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
+        DateFormatSymbols dfs2 = new DateFormatSymbols(ULocale.US);
+        DateFormatSymbols dfsn = new DateFormatSymbols(Locale.US);
+        dfsn.setAmPmStrings(new String[] { "sw", "xw" });
+        testEHCS(dfs, dfs2, dfsn);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormatSymbols.DateFormatSymbols(DateFormatSymbols)'
+     */
+    public void testDateFormatSymbolsDateFormatSymbols() {
+        // implicitly tested everywhere
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormatSymbols.DateFormatSymbols()'
+     */
+    public void testDateFormatSymbols() {
+        DateFormatSymbols dfs = new DateFormatSymbols();
+        assertNotNull(dfs.getWeekdays());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormatSymbols.DateFormatSymbols(Locale)'
+     */
+    public void testDateFormatSymbolsLocale() {
+        DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
+        assertNotNull(dfs.getWeekdays());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormatSymbols.DateFormatSymbols(ULocale)'
+     */
+    public void testDateFormatSymbolsULocale() {
+        DateFormatSymbols dfs = new DateFormatSymbols(ULocale.US);
+        assertNotNull(dfs.getWeekdays());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormatSymbols.getEras()'
+     */
+    public void testGetEras() {
+        DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
+        assertNotNull(dfs.getEras());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormatSymbols.setEras(String[])'
+     */
+    public void testSetEras() {
+        DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
+        String[] oldvalue = dfs.getEras();
+        String[] newvalue = (String[])oldvalue.clone();
+        newvalue[0] = newvalue[0] + "!";
+        dfs.setEras(newvalue);
+        String[] result = dfs.getEras();
+        assertArraysNotEqual(oldvalue, result);
+        assertArraysEqual(newvalue, result);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormatSymbols.getMonths()'
+     */
+    public void testGetMonths() {
+        DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
+        assertNotNull(dfs.getMonths());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormatSymbols.setMonths(String[])'
+     */
+    public void testSetMonths() {
+        DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
+        String[] oldvalue = dfs.getMonths();
+        String[] newvalue = (String[])oldvalue.clone();
+        newvalue[0] = newvalue[0] + "!";
+        dfs.setMonths(newvalue);
+        String[] result = dfs.getMonths();
+        assertArraysNotEqual(oldvalue, result);
+        assertArraysEqual(newvalue, result);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormatSymbols.getShortMonths()'
+     */
+    public void testGetShortMonths() {
+        DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
+        assertNotNull(dfs.getShortMonths());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormatSymbols.setShortMonths(String[])'
+     */
+    public void testSetShortMonths() {
+        DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
+        String[] oldvalue = dfs.getShortMonths();
+        String[] newvalue = (String[])oldvalue.clone();
+        newvalue[0] = newvalue[0] + "!";
+        dfs.setShortMonths(newvalue);
+        String[] result = dfs.getShortMonths();
+        assertArraysNotEqual(oldvalue, result);
+        assertArraysEqual(newvalue, result);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormatSymbols.getWeekdays()'
+     */
+    public void testGetWeekdays() {
+        DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
+        assertNotNull(dfs.getShortMonths());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormatSymbols.setWeekdays(String[])'
+     */
+    public void testSetWeekdays() {
+        DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
+        String[] oldvalue = dfs.getWeekdays();
+        String[] newvalue = (String[])oldvalue.clone();
+        newvalue[0] = newvalue[0] + "!";
+        dfs.setWeekdays(newvalue);
+        String[] result = dfs.getWeekdays();
+        assertArraysNotEqual(oldvalue, result);
+        assertArraysEqual(newvalue, result);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormatSymbols.getShortWeekdays()'
+     */
+    public void testGetShortWeekdays() {
+        DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
+        assertNotNull(dfs.getShortWeekdays());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormatSymbols.setShortWeekdays(String[])'
+     */
+    public void testSetShortWeekdays() {
+        DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
+        String[] oldvalue = dfs.getShortWeekdays();
+        String[] newvalue = (String[])oldvalue.clone();
+        newvalue[0] = newvalue[0] + "!";
+        dfs.setShortWeekdays(newvalue);
+        String[] result = dfs.getShortWeekdays();
+        assertArraysNotEqual(oldvalue, result);
+        assertArraysEqual(newvalue, result);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormatSymbols.getAmPmStrings()'
+     */
+    public void testGetAmPmStrings() {
+        DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
+        assertNotNull(dfs.getAmPmStrings());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormatSymbols.setAmPmStrings(String[])'
+     */
+    public void testSetAmPmStrings() {
+        DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
+        String[] oldvalue = dfs.getAmPmStrings();
+        String[] newvalue = (String[])oldvalue.clone();
+        newvalue[0] = newvalue[0] + "!";
+        dfs.setAmPmStrings(newvalue);
+        String[] result = dfs.getAmPmStrings();
+        assertArraysNotEqual(oldvalue, result);
+        assertArraysEqual(newvalue, result);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormatSymbols.getZoneStrings()'
+     */
+    public void testGetZoneStrings() {
+        DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
+        assertNotNull(dfs.getZoneStrings());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormatSymbols.setZoneStrings(String[][])'
+     */
+    public void testSetZoneStrings() {
+        DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
+        String[][] oldvalue = dfs.getZoneStrings();
+        String[][] newvalue = (String[][])cloneComplex(oldvalue);
+        newvalue[0][0] = newvalue[0][0] + "!";
+        dfs.setZoneStrings(newvalue);
+        String[][] result = dfs.getZoneStrings();
+        assertArraysNotEqual(oldvalue, result);
+        assertArraysEqual(newvalue, result);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormatSymbols.getLocalPatternChars()'
+     */
+    public void testGetLocalPatternChars() {
+        DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
+        assertNotNull(dfs.getLocalPatternChars());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormatSymbols.setLocalPatternChars(String)'
+     */
+    public void testSetLocalPatternChars() {
+        DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
+        String pat = dfs.getLocalPatternChars();
+        StringBuffer buf = new StringBuffer(pat);
+        buf.setCharAt(0, (char)(pat.charAt(0) + 1));
+        String pat2 = buf.toString();
+        dfs.setLocalPatternChars(pat2);
+        String pat3 = dfs.getLocalPatternChars();
+        assertNotEqual(pat, pat2);
+        assertEquals(pat2, pat3);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormatSymbols.toString()'
+     */
+    public void testToString() {
+        DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
+        assertNotNull(dfs.toString());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormatSymbols.clone()'
+     */
+    public void testClone() {
+        // tested by testHashCode
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormatSymbols.equals(Object)'
+     */
+    public void testEqualsObject() {
+        // tested by testHashCode
+    }
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/DateFormatTest.java b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/DateFormatTest.java
index 37f5559..1e1e7e9 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/DateFormatTest.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/DateFormatTest.java
@@ -1,454 +1,454 @@
-/*
- *******************************************************************************
- * Copyright (C) 2006-2011, International Business Machines Corporation and    *
- * others. All Rights Reserved.                                                *
- *******************************************************************************
- */
-
-package com.ibm.icu.tests;
-
-import java.text.FieldPosition;
-import java.text.ParseException;
-import java.text.ParsePosition;
-import java.util.Date;
-import java.util.Locale;
-
-import com.ibm.icu.text.DateFormat;
-import com.ibm.icu.text.NumberFormat;
-import com.ibm.icu.util.Calendar;
-import com.ibm.icu.util.TimeZone;
-import com.ibm.icu.util.ULocale;
-
-public class DateFormatTest extends ICUTestCase {
-    private Calendar aCal;
-    private Calendar anESTCal;
-    private Date aDate;
-    private String aDateString;
-    private String aTimeString;
-    private String anESTTimeString;
-    private String aDateTimeString;
-    private String aShortDateTimeString;
-    private String aDefaultESTDateTimeString;
-    private DateFormat aDF;
-    private StringBuffer aBuf;
-    private FieldPosition anFP;
-    private FieldPosition anFPField;
-
-    private static int YEAR_POS_START = 8;
-    private static int YEAR_POS_END = 12;
-
-    protected void setUp() throws Exception {
-        super.setUp();
-                
-        java.util.GregorianCalendar gcal = new java.util.GregorianCalendar();
-        gcal.clear();
-        gcal.set(java.util.GregorianCalendar.YEAR, 1990);
-        gcal.set(java.util.GregorianCalendar.MONTH, java.util.GregorianCalendar.DECEMBER);
-        gcal.set(java.util.GregorianCalendar.DATE, 17);
-        gcal.set(java.util.GregorianCalendar.HOUR, 5);
-        gcal.set(java.util.GregorianCalendar.MINUTE, 17);
-        aCal = new Calendar(gcal);
-        anESTCal = Calendar.getInstance();
-        anESTCal.setTimeZone(TimeZone.getTimeZone("EST"));
-        aDate = gcal.getTime();
-        aDateString = "Dec 17, 1990"; // medium -- the default
-        aTimeString = "5:17:00 AM"; // medium
-        anESTTimeString = "8:17:00 AM";
-        aDateTimeString = "Dec 17, 1990 5:17:00 AM"; // medium, medium
-        aDefaultESTDateTimeString = "Dec 17, 1990 8:17 AM"; // medium, short -- the default
-        aShortDateTimeString = "12/17/90 5:17 AM"; // short, short
-        aDF = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.US);
-        aBuf = new StringBuffer();
-        anFP = new FieldPosition(DateFormat.YEAR_FIELD);
-        anFPField = new FieldPosition(DateFormat.Field.YEAR);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.hashCode()'
-     */
-    public final void testHashCode() {
-        DateFormat df = DateFormat.getInstance();
-        DateFormat eq = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
-        testEHCS(df, eq, aDF);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.DateFormat(DateFormat)'
-     */
-    public final void testDateFormat() {
-        DateFormat df = new DateFormat(java.text.DateFormat.getInstance());
-        assertEquals(DateFormat.getInstance(), df);
-    }
-
-    private void assertEqualDateString(StringBuffer buf) {
-        assertEquals(aDateTimeString, buf.toString());
-    }
-        
-    private void assertEqualDateString(String str) {
-        assertEquals(aDateTimeString, str);
-    }
-        
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.format(Object, StringBuffer, FieldPosition)'
-     */
-    public final void testFormatObjectStringBufferFieldPosition() {
-        assertEqualDateString(aDF.format(aDate, aBuf, anFP));
-        assertEquals(YEAR_POS_START, anFP.getBeginIndex());
-        assertEquals(YEAR_POS_END, anFP.getEndIndex());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.format(Calendar, StringBuffer, FieldPosition)'
-     */
-    public final void testFormatCalendarStringBufferFieldPosition() {
-        assertEqualDateString(aDF.format(aCal, aBuf, anFP));
-        assertEquals(YEAR_POS_START, anFP.getBeginIndex());
-        assertEquals(YEAR_POS_END, anFP.getEndIndex());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.format(Date, StringBuffer, FieldPosition)'
-     */
-    public final void testFormatDateStringBufferFieldPosition() {
-        assertEqualDateString(aDF.format(aDate, aBuf, anFPField));
-        assertEquals(YEAR_POS_START, anFPField.getBeginIndex());
-        assertEquals(YEAR_POS_END, anFPField.getEndIndex());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.format(Date)'
-     */
-    public final void testFormatDate() {
-        assertEqualDateString(aDF.format(aDate));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.parse(String)'
-     */
-    public final void testParseString() throws Exception {
-        assertEquals(aDate, aDF.parse(aDateTimeString));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.parse(String, Calendar, ParsePosition)'
-     */
-    public final void testParseStringCalendarParsePosition() {
-        aDF.parse(aDateTimeString, aCal, new ParsePosition(0));
-        assertEquals(aDate, aCal.getTime());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.parse(String, ParsePosition)'
-     */
-    public final void testParseStringParsePosition() {
-        assertEquals(aDate, aDF.parse(aDateTimeString, new ParsePosition(0)));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.parseObject(String, ParsePosition)'
-     */
-    public final void testParseObjectStringParsePosition() {
-        assertEquals(aDate, aDF.parseObject(aDateTimeString, new ParsePosition(0)));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.getTimeInstance()'
-     */
-    public final void testGetTimeInstance() {
-        assertEquals(aTimeString, DateFormat.getTimeInstance().format(aDate));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.getTimeInstance(int)'
-     */
-    public final void testGetTimeInstanceInt() {
-        assertEquals(aTimeString, DateFormat.getTimeInstance(DateFormat.MEDIUM).format(aDate));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.getTimeInstance(int, Locale)'
-     */
-    public final void testGetTimeInstanceIntLocale() {
-        assertEquals(aTimeString, DateFormat.getTimeInstance(DateFormat.MEDIUM, Locale.US).format(aDate));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.getTimeInstance(int, ULocale)'
-     */
-    public final void testGetTimeInstanceIntULocale() {
-        assertEquals(aTimeString, DateFormat.getTimeInstance(DateFormat.MEDIUM, ULocale.US).format(aDate));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.getDateInstance()'
-     */
-    public final void testGetDateInstance() {
-        assertEquals(aDateString, DateFormat.getDateInstance().format(aDate));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.getDateInstance(int)'
-     */
-    public final void testGetDateInstanceInt() {
-        assertEquals(aDateString, DateFormat.getDateInstance(DateFormat.MEDIUM).format(aDate));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.getDateInstance(int, Locale)'
-     */
-    public final void testGetDateInstanceIntLocale() {
-        assertEquals(aDateString, DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.US).format(aDate));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.getDateInstance(int, ULocale)'
-     */
-    public final void testGetDateInstanceIntULocale() {
-        assertEquals(aDateString, DateFormat.getDateInstance(DateFormat.MEDIUM, ULocale.US).format(aDate));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.getDateTimeInstance()'
-     */
-    public final void testGetDateTimeInstance() {
-        assertEquals(aDateTimeString, DateFormat.getDateTimeInstance().format(aDate));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.getDateTimeInstance(int, int)'
-     */
-    public final void testGetDateTimeInstanceIntInt() {
-        assertEquals(aDateTimeString, 
-                     DateFormat.getDateTimeInstance(
-                                                    DateFormat.MEDIUM, DateFormat.MEDIUM).format(aDate));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.getDateTimeInstance(int, int, Locale)'
-     */
-    public final void testGetDateTimeInstanceIntIntLocale() {
-        assertEquals(aDateTimeString, 
-                     DateFormat.getDateTimeInstance(
-                                                    DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.US).format(aDate));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.getDateTimeInstance(int, int, ULocale)'
-     */
-    public final void testGetDateTimeInstanceIntIntULocale() {
-        assertEquals(aDateTimeString, 
-                     DateFormat.getDateTimeInstance(
-                                                    DateFormat.MEDIUM, DateFormat.MEDIUM, ULocale.US).format(aDate));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.getInstance()'
-     */
-    public final void testGetInstance() {
-        assertEquals(aShortDateTimeString, DateFormat.getInstance().format(aDate));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.getAvailableLocales()'
-     */
-    public final void testGetAvailableLocales() {
-        Locale[] locales = DateFormat.getAvailableLocales();
-        if (ICUTestCase.testingWrapper) {
-            ICUTestCase.assertArraysEqual(java.text.DateFormat.getAvailableLocales(), locales);
-        } else {
-            assertNotNull(locales);
-        }
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.setCalendar(Calendar)'
-     */
-    public final void testSetCalendar() {
-        Calendar cal = Calendar.getInstance();
-        cal.setTimeZone(TimeZone.getTimeZone("EST"));
-        DateFormat df = DateFormat.getTimeInstance(DateFormat.SHORT);
-        df.setCalendar(cal);
-        assertEquals("8:17 AM", df.format(aDate));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.getCalendar()'
-     */
-    public final void testGetCalendar() {
-        Calendar cal = Calendar.getInstance();
-        cal.setTimeZone(TimeZone.getTimeZone("EST"));
-        DateFormat df = DateFormat.getTimeInstance(DateFormat.SHORT);
-        df.setCalendar(cal);
-        assertEquals(cal, df.getCalendar());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.setNumberFormat(NumberFormat)'
-     */
-    public final void testSetNumberFormat() {
-        // no easy way to test effect of setting the number format
-        NumberFormat nf = NumberFormat.getInstance();
-        DateFormat df = DateFormat.getTimeInstance(DateFormat.SHORT);
-        df.setNumberFormat(nf);
-        // note, can't actually USE the dateformat since it changes the calendar
-        assertEquals(nf, df.getNumberFormat());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.getNumberFormat()'
-     */
-    public final void testGetNumberFormat() {
-        // see testSetNumberFormat
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.setTimeZone(TimeZone)'
-     */
-    public final void testSetTimeZone() {
-        DateFormat df = DateFormat.getTimeInstance(DateFormat.SHORT);
-        TimeZone tz = TimeZone.getTimeZone("EST");
-        df.setTimeZone(tz);
-        assertEquals("8:17 AM", df.format(aDate));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.getTimeZone()'
-     */
-    public final void testGetTimeZone() {
-        DateFormat df = DateFormat.getTimeInstance(DateFormat.SHORT);
-        TimeZone tz = TimeZone.getTimeZone("EST");
-        df.setTimeZone(tz);
-        assertEquals(tz, df.getTimeZone());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.setLenient(boolean)'
-     */
-    public final void testSetLenient() throws Exception {
-        DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT);
-        df.parse("2/31/90"); // succeeds, default is lenient
-        df.setLenient(false);
-        try {
-            df.parse("2/31/90");
-            throw new Exception("strict parse should have failed");
-        }
-        catch (ParseException e) {
-            // ok, this is what we expect
-        }
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.isLenient()'
-     */
-    public final void testIsLenient() {
-        DateFormat df = DateFormat.getInstance();
-        assertTrue(df.isLenient());
-        df.setLenient(false);
-        assertFalse(df.isLenient());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.getDateInstance(Calendar, int, Locale)'
-     */
-    public final void testGetDateInstanceCalendarIntLocale() {
-        assertEquals(aDateString, DateFormat.getDateInstance(aCal, DateFormat.MEDIUM, Locale.US).format(aDate));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.getDateInstance(Calendar, int, ULocale)'
-     */
-    public final void testGetDateInstanceCalendarIntULocale() {
-        assertEquals(aDateString, DateFormat.getDateInstance(aCal, DateFormat.MEDIUM, ULocale.US).format(aDate));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.getTimeInstance(Calendar, int, Locale)'
-     */
-    public final void testGetTimeInstanceCalendarIntLocale() {
-        assertEquals(anESTTimeString, DateFormat.getTimeInstance(anESTCal, DateFormat.MEDIUM, Locale.US).format(aDate));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.getTimeInstance(Calendar, int, ULocale)'
-     */
-    public final void testGetTimeInstanceCalendarIntULocale() {
-        assertEquals(anESTTimeString, DateFormat.getTimeInstance(anESTCal, DateFormat.MEDIUM, ULocale.US).format(aDate));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.getDateTimeInstance(Calendar, int, int, Locale)'
-     */
-    public final void testGetDateTimeInstanceCalendarIntIntLocale() {
-        assertEquals(aDefaultESTDateTimeString, DateFormat.getDateTimeInstance(anESTCal, DateFormat.MEDIUM, DateFormat.SHORT, Locale.US).format(aDate));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.getDateTimeInstance(Calendar, int, int, ULocale)'
-     */
-    public final void testGetDateTimeInstanceCalendarIntIntULocale() {
-        assertEquals(aDefaultESTDateTimeString, DateFormat.getDateTimeInstance(anESTCal, DateFormat.MEDIUM, DateFormat.SHORT, ULocale.US).format(aDate));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.getInstance(Calendar, Locale)'
-     */
-    public final void testGetInstanceCalendarLocale() {
-        assertEquals(aDefaultESTDateTimeString, DateFormat.getInstance(anESTCal, Locale.US).format(aDate));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.getInstance(Calendar, ULocale)'
-     */
-    public final void testGetInstanceCalendarULocale() {
-        assertEquals(aDefaultESTDateTimeString, DateFormat.getInstance(anESTCal, ULocale.US).format(aDate));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.getInstance(Calendar)'
-     */
-    public final void testGetInstanceCalendar() {
-        assertEquals(aDefaultESTDateTimeString, DateFormat.getInstance(anESTCal).format(aDate));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.getDateInstance(Calendar, int)'
-     */
-    public final void testGetDateInstanceCalendarInt() {
-        assertEquals(aDateString, DateFormat.getDateInstance(aCal, DateFormat.MEDIUM).format(aDate));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.getTimeInstance(Calendar, int)'
-     */
-    public final void testGetTimeInstanceCalendarInt() {
-        assertEquals(anESTTimeString, DateFormat.getTimeInstance(anESTCal, DateFormat.MEDIUM).format(aDate));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.getDateTimeInstance(Calendar, int, int)'
-     */
-    public final void testGetDateTimeInstanceCalendarIntInt() {
-        assertEquals(aDefaultESTDateTimeString, DateFormat.getDateTimeInstance(anESTCal, DateFormat.MEDIUM, DateFormat.SHORT).format(aDate));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.toString()'
-     */
-    public final void testToString() {
-        assertNotNull(aDF.toString());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.clone()'
-     */
-    public final void testClone() {
-        // see testHashCode
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DateFormat.equals(Object)'
-     */
-    public final void testEqualsObject() {
-        // see testHashCode
-    }
-}
+/*
+ *******************************************************************************
+ * Copyright (C) 2006-2011, International Business Machines Corporation and    *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+
+package com.ibm.icu.tests;
+
+import java.text.FieldPosition;
+import java.text.ParseException;
+import java.text.ParsePosition;
+import java.util.Date;
+import java.util.Locale;
+
+import com.ibm.icu.text.DateFormat;
+import com.ibm.icu.text.NumberFormat;
+import com.ibm.icu.util.Calendar;
+import com.ibm.icu.util.TimeZone;
+import com.ibm.icu.util.ULocale;
+
+public class DateFormatTest extends ICUTestCase {
+    private Calendar aCal;
+    private Calendar anESTCal;
+    private Date aDate;
+    private String aDateString;
+    private String aTimeString;
+    private String anESTTimeString;
+    private String aDateTimeString;
+    private String aShortDateTimeString;
+    private String aDefaultESTDateTimeString;
+    private DateFormat aDF;
+    private StringBuffer aBuf;
+    private FieldPosition anFP;
+    private FieldPosition anFPField;
+
+    private static int YEAR_POS_START = 8;
+    private static int YEAR_POS_END = 12;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+                
+        java.util.GregorianCalendar gcal = new java.util.GregorianCalendar();
+        gcal.clear();
+        gcal.set(java.util.GregorianCalendar.YEAR, 1990);
+        gcal.set(java.util.GregorianCalendar.MONTH, java.util.GregorianCalendar.DECEMBER);
+        gcal.set(java.util.GregorianCalendar.DATE, 17);
+        gcal.set(java.util.GregorianCalendar.HOUR, 5);
+        gcal.set(java.util.GregorianCalendar.MINUTE, 17);
+        aCal = new Calendar(gcal);
+        anESTCal = Calendar.getInstance();
+        anESTCal.setTimeZone(TimeZone.getTimeZone("EST"));
+        aDate = gcal.getTime();
+        aDateString = "Dec 17, 1990"; // medium -- the default
+        aTimeString = "5:17:00 AM"; // medium
+        anESTTimeString = "8:17:00 AM";
+        aDateTimeString = "Dec 17, 1990 5:17:00 AM"; // medium, medium
+        aDefaultESTDateTimeString = "Dec 17, 1990 8:17 AM"; // medium, short -- the default
+        aShortDateTimeString = "12/17/90 5:17 AM"; // short, short
+        aDF = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.US);
+        aBuf = new StringBuffer();
+        anFP = new FieldPosition(DateFormat.YEAR_FIELD);
+        anFPField = new FieldPosition(DateFormat.Field.YEAR);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.hashCode()'
+     */
+    public final void testHashCode() {
+        DateFormat df = DateFormat.getInstance();
+        DateFormat eq = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
+        testEHCS(df, eq, aDF);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.DateFormat(DateFormat)'
+     */
+    public final void testDateFormat() {
+        DateFormat df = new DateFormat(java.text.DateFormat.getInstance());
+        assertEquals(DateFormat.getInstance(), df);
+    }
+
+    private void assertEqualDateString(StringBuffer buf) {
+        assertEquals(aDateTimeString, buf.toString());
+    }
+        
+    private void assertEqualDateString(String str) {
+        assertEquals(aDateTimeString, str);
+    }
+        
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.format(Object, StringBuffer, FieldPosition)'
+     */
+    public final void testFormatObjectStringBufferFieldPosition() {
+        assertEqualDateString(aDF.format(aDate, aBuf, anFP));
+        assertEquals(YEAR_POS_START, anFP.getBeginIndex());
+        assertEquals(YEAR_POS_END, anFP.getEndIndex());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.format(Calendar, StringBuffer, FieldPosition)'
+     */
+    public final void testFormatCalendarStringBufferFieldPosition() {
+        assertEqualDateString(aDF.format(aCal, aBuf, anFP));
+        assertEquals(YEAR_POS_START, anFP.getBeginIndex());
+        assertEquals(YEAR_POS_END, anFP.getEndIndex());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.format(Date, StringBuffer, FieldPosition)'
+     */
+    public final void testFormatDateStringBufferFieldPosition() {
+        assertEqualDateString(aDF.format(aDate, aBuf, anFPField));
+        assertEquals(YEAR_POS_START, anFPField.getBeginIndex());
+        assertEquals(YEAR_POS_END, anFPField.getEndIndex());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.format(Date)'
+     */
+    public final void testFormatDate() {
+        assertEqualDateString(aDF.format(aDate));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.parse(String)'
+     */
+    public final void testParseString() throws Exception {
+        assertEquals(aDate, aDF.parse(aDateTimeString));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.parse(String, Calendar, ParsePosition)'
+     */
+    public final void testParseStringCalendarParsePosition() {
+        aDF.parse(aDateTimeString, aCal, new ParsePosition(0));
+        assertEquals(aDate, aCal.getTime());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.parse(String, ParsePosition)'
+     */
+    public final void testParseStringParsePosition() {
+        assertEquals(aDate, aDF.parse(aDateTimeString, new ParsePosition(0)));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.parseObject(String, ParsePosition)'
+     */
+    public final void testParseObjectStringParsePosition() {
+        assertEquals(aDate, aDF.parseObject(aDateTimeString, new ParsePosition(0)));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.getTimeInstance()'
+     */
+    public final void testGetTimeInstance() {
+        assertEquals(aTimeString, DateFormat.getTimeInstance().format(aDate));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.getTimeInstance(int)'
+     */
+    public final void testGetTimeInstanceInt() {
+        assertEquals(aTimeString, DateFormat.getTimeInstance(DateFormat.MEDIUM).format(aDate));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.getTimeInstance(int, Locale)'
+     */
+    public final void testGetTimeInstanceIntLocale() {
+        assertEquals(aTimeString, DateFormat.getTimeInstance(DateFormat.MEDIUM, Locale.US).format(aDate));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.getTimeInstance(int, ULocale)'
+     */
+    public final void testGetTimeInstanceIntULocale() {
+        assertEquals(aTimeString, DateFormat.getTimeInstance(DateFormat.MEDIUM, ULocale.US).format(aDate));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.getDateInstance()'
+     */
+    public final void testGetDateInstance() {
+        assertEquals(aDateString, DateFormat.getDateInstance().format(aDate));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.getDateInstance(int)'
+     */
+    public final void testGetDateInstanceInt() {
+        assertEquals(aDateString, DateFormat.getDateInstance(DateFormat.MEDIUM).format(aDate));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.getDateInstance(int, Locale)'
+     */
+    public final void testGetDateInstanceIntLocale() {
+        assertEquals(aDateString, DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.US).format(aDate));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.getDateInstance(int, ULocale)'
+     */
+    public final void testGetDateInstanceIntULocale() {
+        assertEquals(aDateString, DateFormat.getDateInstance(DateFormat.MEDIUM, ULocale.US).format(aDate));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.getDateTimeInstance()'
+     */
+    public final void testGetDateTimeInstance() {
+        assertEquals(aDateTimeString, DateFormat.getDateTimeInstance().format(aDate));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.getDateTimeInstance(int, int)'
+     */
+    public final void testGetDateTimeInstanceIntInt() {
+        assertEquals(aDateTimeString, 
+                     DateFormat.getDateTimeInstance(
+                                                    DateFormat.MEDIUM, DateFormat.MEDIUM).format(aDate));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.getDateTimeInstance(int, int, Locale)'
+     */
+    public final void testGetDateTimeInstanceIntIntLocale() {
+        assertEquals(aDateTimeString, 
+                     DateFormat.getDateTimeInstance(
+                                                    DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.US).format(aDate));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.getDateTimeInstance(int, int, ULocale)'
+     */
+    public final void testGetDateTimeInstanceIntIntULocale() {
+        assertEquals(aDateTimeString, 
+                     DateFormat.getDateTimeInstance(
+                                                    DateFormat.MEDIUM, DateFormat.MEDIUM, ULocale.US).format(aDate));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.getInstance()'
+     */
+    public final void testGetInstance() {
+        assertEquals(aShortDateTimeString, DateFormat.getInstance().format(aDate));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.getAvailableLocales()'
+     */
+    public final void testGetAvailableLocales() {
+        Locale[] locales = DateFormat.getAvailableLocales();
+        if (ICUTestCase.testingWrapper) {
+            ICUTestCase.assertArraysEqual(java.text.DateFormat.getAvailableLocales(), locales);
+        } else {
+            assertNotNull(locales);
+        }
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.setCalendar(Calendar)'
+     */
+    public final void testSetCalendar() {
+        Calendar cal = Calendar.getInstance();
+        cal.setTimeZone(TimeZone.getTimeZone("EST"));
+        DateFormat df = DateFormat.getTimeInstance(DateFormat.SHORT);
+        df.setCalendar(cal);
+        assertEquals("8:17 AM", df.format(aDate));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.getCalendar()'
+     */
+    public final void testGetCalendar() {
+        Calendar cal = Calendar.getInstance();
+        cal.setTimeZone(TimeZone.getTimeZone("EST"));
+        DateFormat df = DateFormat.getTimeInstance(DateFormat.SHORT);
+        df.setCalendar(cal);
+        assertEquals(cal, df.getCalendar());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.setNumberFormat(NumberFormat)'
+     */
+    public final void testSetNumberFormat() {
+        // no easy way to test effect of setting the number format
+        NumberFormat nf = NumberFormat.getInstance();
+        DateFormat df = DateFormat.getTimeInstance(DateFormat.SHORT);
+        df.setNumberFormat(nf);
+        // note, can't actually USE the dateformat since it changes the calendar
+        assertEquals(nf, df.getNumberFormat());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.getNumberFormat()'
+     */
+    public final void testGetNumberFormat() {
+        // see testSetNumberFormat
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.setTimeZone(TimeZone)'
+     */
+    public final void testSetTimeZone() {
+        DateFormat df = DateFormat.getTimeInstance(DateFormat.SHORT);
+        TimeZone tz = TimeZone.getTimeZone("EST");
+        df.setTimeZone(tz);
+        assertEquals("8:17 AM", df.format(aDate));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.getTimeZone()'
+     */
+    public final void testGetTimeZone() {
+        DateFormat df = DateFormat.getTimeInstance(DateFormat.SHORT);
+        TimeZone tz = TimeZone.getTimeZone("EST");
+        df.setTimeZone(tz);
+        assertEquals(tz, df.getTimeZone());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.setLenient(boolean)'
+     */
+    public final void testSetLenient() throws Exception {
+        DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT);
+        df.parse("2/31/90"); // succeeds, default is lenient
+        df.setLenient(false);
+        try {
+            df.parse("2/31/90");
+            throw new Exception("strict parse should have failed");
+        }
+        catch (ParseException e) {
+            // ok, this is what we expect
+        }
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.isLenient()'
+     */
+    public final void testIsLenient() {
+        DateFormat df = DateFormat.getInstance();
+        assertTrue(df.isLenient());
+        df.setLenient(false);
+        assertFalse(df.isLenient());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.getDateInstance(Calendar, int, Locale)'
+     */
+    public final void testGetDateInstanceCalendarIntLocale() {
+        assertEquals(aDateString, DateFormat.getDateInstance(aCal, DateFormat.MEDIUM, Locale.US).format(aDate));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.getDateInstance(Calendar, int, ULocale)'
+     */
+    public final void testGetDateInstanceCalendarIntULocale() {
+        assertEquals(aDateString, DateFormat.getDateInstance(aCal, DateFormat.MEDIUM, ULocale.US).format(aDate));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.getTimeInstance(Calendar, int, Locale)'
+     */
+    public final void testGetTimeInstanceCalendarIntLocale() {
+        assertEquals(anESTTimeString, DateFormat.getTimeInstance(anESTCal, DateFormat.MEDIUM, Locale.US).format(aDate));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.getTimeInstance(Calendar, int, ULocale)'
+     */
+    public final void testGetTimeInstanceCalendarIntULocale() {
+        assertEquals(anESTTimeString, DateFormat.getTimeInstance(anESTCal, DateFormat.MEDIUM, ULocale.US).format(aDate));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.getDateTimeInstance(Calendar, int, int, Locale)'
+     */
+    public final void testGetDateTimeInstanceCalendarIntIntLocale() {
+        assertEquals(aDefaultESTDateTimeString, DateFormat.getDateTimeInstance(anESTCal, DateFormat.MEDIUM, DateFormat.SHORT, Locale.US).format(aDate));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.getDateTimeInstance(Calendar, int, int, ULocale)'
+     */
+    public final void testGetDateTimeInstanceCalendarIntIntULocale() {
+        assertEquals(aDefaultESTDateTimeString, DateFormat.getDateTimeInstance(anESTCal, DateFormat.MEDIUM, DateFormat.SHORT, ULocale.US).format(aDate));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.getInstance(Calendar, Locale)'
+     */
+    public final void testGetInstanceCalendarLocale() {
+        assertEquals(aDefaultESTDateTimeString, DateFormat.getInstance(anESTCal, Locale.US).format(aDate));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.getInstance(Calendar, ULocale)'
+     */
+    public final void testGetInstanceCalendarULocale() {
+        assertEquals(aDefaultESTDateTimeString, DateFormat.getInstance(anESTCal, ULocale.US).format(aDate));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.getInstance(Calendar)'
+     */
+    public final void testGetInstanceCalendar() {
+        assertEquals(aDefaultESTDateTimeString, DateFormat.getInstance(anESTCal).format(aDate));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.getDateInstance(Calendar, int)'
+     */
+    public final void testGetDateInstanceCalendarInt() {
+        assertEquals(aDateString, DateFormat.getDateInstance(aCal, DateFormat.MEDIUM).format(aDate));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.getTimeInstance(Calendar, int)'
+     */
+    public final void testGetTimeInstanceCalendarInt() {
+        assertEquals(anESTTimeString, DateFormat.getTimeInstance(anESTCal, DateFormat.MEDIUM).format(aDate));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.getDateTimeInstance(Calendar, int, int)'
+     */
+    public final void testGetDateTimeInstanceCalendarIntInt() {
+        assertEquals(aDefaultESTDateTimeString, DateFormat.getDateTimeInstance(anESTCal, DateFormat.MEDIUM, DateFormat.SHORT).format(aDate));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.toString()'
+     */
+    public final void testToString() {
+        assertNotNull(aDF.toString());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.clone()'
+     */
+    public final void testClone() {
+        // see testHashCode
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DateFormat.equals(Object)'
+     */
+    public final void testEqualsObject() {
+        // see testHashCode
+    }
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/DecimalFormatSymbolsTest.java b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/DecimalFormatSymbolsTest.java
index 9cc7ce6..22779a5 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/DecimalFormatSymbolsTest.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/DecimalFormatSymbolsTest.java
@@ -1,344 +1,344 @@
-/*
- *******************************************************************************
- * Copyright (C) 2006-2011, International Business Machines Corporation and    *
- * others. All Rights Reserved.                                                *
- *******************************************************************************
- */
-
-package com.ibm.icu.tests;
-
-import java.util.Locale;
-
-import com.ibm.icu.text.DecimalFormatSymbols;
-import com.ibm.icu.util.ULocale;
-
-public class DecimalFormatSymbolsTest extends ICUTestCase {
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.hashCode()'
-     */
-    public void testHashCode() {
-        DecimalFormatSymbols dfs = new DecimalFormatSymbols(Locale.US);
-        DecimalFormatSymbols dfs2 = new DecimalFormatSymbols(ULocale.US);
-        DecimalFormatSymbols dfsn = new DecimalFormatSymbols(Locale.FRANCE);
-        testEHCS(dfs, dfs2, dfsn);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.DecimalFormatSymbols(DecimalFormatSymbols)'
-     */
-    public void testDecimalFormatSymbolsDecimalFormatSymbols() {
-        // implicitly tested everywhere
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.DecimalFormatSymbols()'
-     */
-    public void testDecimalFormatSymbols() {
-        DecimalFormatSymbols dfs = new DecimalFormatSymbols();
-        assertTrue(-1 != dfs.getDecimalSeparator());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.DecimalFormatSymbols(Locale)'
-     */
-    public void testDecimalFormatSymbolsLocale() {
-        DecimalFormatSymbols dfs = new DecimalFormatSymbols(Locale.US);
-        assertTrue(-1 != dfs.getDecimalSeparator());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.DecimalFormatSymbols(ULocale)'
-     */
-    public void testDecimalFormatSymbolsULocale() {
-        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
-        assertTrue(-1 != dfs.getDecimalSeparator());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.getZeroDigit()'
-     */
-    public void testGetZeroDigit() {
-        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
-        assertEquals('0', dfs.getZeroDigit());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.setZeroDigit(char)'
-     */
-    public void testSetZeroDigit() {
-        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
-        char value = dfs.getZeroDigit();
-        char value1 = (char)(value + 1);
-        dfs.setZeroDigit(value1);
-        char result = dfs.getZeroDigit();
-        assertNotEqual(value, result);
-        assertEquals(value1, result);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.getGroupingSeparator()'
-     */
-    public void testGetGroupingSeparator() {
-        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
-        assertEquals(',', dfs.getGroupingSeparator());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.setGroupingSeparator(char)'
-     */
-    public void testSetGroupingSeparator() {
-        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
-        char value = dfs.getGroupingSeparator();
-        char value1 = (char)(value + 1);
-        dfs.setGroupingSeparator(value1);
-        char result = dfs.getGroupingSeparator();
-        assertNotEqual(value, result);
-        assertEquals(value1, result);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.getDecimalSeparator()'
-     */
-    public void testGetDecimalSeparator() {
-        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
-        assertEquals('.', dfs.getDecimalSeparator());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.setDecimalSeparator(char)'
-     */
-    public void testSetDecimalSeparator() {
-        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
-        char value = dfs.getDecimalSeparator();
-        char value1 = (char)(value + 1);
-        dfs.setDecimalSeparator(value1);
-        char result = dfs.getDecimalSeparator();
-        assertNotEqual(value, result);
-        assertEquals(value1, result);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.getPerMill()'
-     */
-    public void testGetPerMill() {
-        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
-        assertEquals('\u2030', dfs.getPerMill());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.setPerMill(char)'
-     */
-    public void testSetPerMill() {
-        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
-        char value = dfs.getPerMill();
-        char value1 = (char)(value + 1);
-        dfs.setPerMill(value1);
-        char result = dfs.getPerMill();
-        assertNotEqual(value, result);
-        assertEquals(value1, result);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.getPercent()'
-     */
-    public void testGetPercent() {
-        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
-        assertEquals('%', dfs.getPercent());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.setPercent(char)'
-     */
-    public void testSetPercent() {
-        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
-        char value = dfs.getPercent();
-        char value1 = (char)(value + 1);
-        dfs.setPercent(value1);
-        char result = dfs.getPercent();
-        assertNotEqual(value, result);
-        assertEquals(value1, result);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.getDigit()'
-     */
-    public void testGetDigit() {
-        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
-        assertEquals('#', dfs.getDigit());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.setDigit(char)'
-     */
-    public void testSetDigit() {
-        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
-        char value = dfs.getDigit();
-        char value1 = (char)(value + 1);
-        dfs.setDigit(value1);
-        char result = dfs.getDigit();
-        assertNotEqual(value, result);
-        assertEquals(value1, result);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.getPatternSeparator()'
-     */
-    public void testGetPatternSeparator() {
-        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
-        assertEquals(';', dfs.getPatternSeparator());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.setPatternSeparator(char)'
-     */
-    public void testSetPatternSeparator() {
-        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
-        char value = dfs.getPatternSeparator();
-        char value1 = (char)(value + 1);
-        dfs.setPatternSeparator(value1);
-        char result = dfs.getPatternSeparator();
-        assertNotEqual(value, result);
-        assertEquals(value1, result);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.getInfinity()'
-     */
-    public void testGetInfinity() {
-        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
-        assertEquals("\u221e", dfs.getInfinity());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.setInfinity(String)'
-     */
-    public void testSetInfinity() {
-        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
-        String value = dfs.getInfinity();
-        String value1 = value + "!";
-        dfs.setInfinity(value1);
-        String result = dfs.getInfinity();
-        assertNotEqual(value, result);
-        assertEquals(value1, result);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.getNaN()'
-     */
-    public void testGetNaN() {
-        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
-        assertNotNull(dfs.getNaN()); // java returns missing character???
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.setNaN(String)'
-     */
-    public void testSetNaN() {
-        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
-        String value = dfs.getNaN();
-        String value1 = value + "!";
-        dfs.setNaN(value1);
-        String result = dfs.getNaN();
-        assertNotEqual(value, result);
-        assertEquals(value1, result);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.getMinusSign()'
-     */
-    public void testGetMinusSign() {
-        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
-        assertEquals('-', dfs.getMinusSign());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.setMinusSign(char)'
-     */
-    public void testSetMinusSign() {
-        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
-        char value = dfs.getMinusSign();
-        char value1 = (char)(value + 1);
-        dfs.setMinusSign(value1);
-        char result = dfs.getMinusSign();
-        assertNotEqual(value, result);
-        assertEquals(value1, result);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.getCurrencySymbol()'
-     */
-    public void testGetCurrencySymbol() {
-        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
-        assertEquals("$", dfs.getCurrencySymbol());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.setCurrencySymbol(String)'
-     */
-    public void testSetCurrencySymbol() {
-        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
-        String value = dfs.getCurrencySymbol();
-        String value1 = value + "!";
-        dfs.setCurrencySymbol(value1);
-        String result = dfs.getCurrencySymbol();
-        assertNotEqual(value, result);
-        assertEquals(value1, result);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.getInternationalCurrencySymbol()'
-     */
-    public void testGetInternationalCurrencySymbol() {
-        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
-        assertEquals("USD", dfs.getInternationalCurrencySymbol());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.setInternationalCurrencySymbol(String)'
-     */
-    public void testSetInternationalCurrencySymbol() {
-        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
-        String value = dfs.getInternationalCurrencySymbol();
-        String value1 = value + "!";
-        dfs.setInternationalCurrencySymbol(value1);
-        String result = dfs.getInternationalCurrencySymbol();
-        assertNotEqual(value, result);
-        assertEquals(value1, result);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.getMonetaryDecimalSeparator()'
-     */
-    public void testGetMonetaryDecimalSeparator() {
-        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
-        assertEquals('.', dfs.getMonetaryDecimalSeparator());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.setMonetaryDecimalSeparator(char)'
-     */
-    public void testSetMonetaryDecimalSeparator() {
-        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
-        char value = dfs.getMonetaryDecimalSeparator();
-        char value1 = (char)(value + 1);
-        dfs.setMonetaryDecimalSeparator(value1);
-        char result = dfs.getMonetaryDecimalSeparator();
-        assertNotEqual(value, result);
-        assertEquals(value1, result);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.clone()'
-     */
-    public void testClone() {
-        // tested in testHashcode
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.equals(Object)'
-     */
-    public void testEqualsObject() {
-        // tested in testHashcode
-    }
-}
+/*
+ *******************************************************************************
+ * Copyright (C) 2006-2011, International Business Machines Corporation and    *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+
+package com.ibm.icu.tests;
+
+import java.util.Locale;
+
+import com.ibm.icu.text.DecimalFormatSymbols;
+import com.ibm.icu.util.ULocale;
+
+public class DecimalFormatSymbolsTest extends ICUTestCase {
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.hashCode()'
+     */
+    public void testHashCode() {
+        DecimalFormatSymbols dfs = new DecimalFormatSymbols(Locale.US);
+        DecimalFormatSymbols dfs2 = new DecimalFormatSymbols(ULocale.US);
+        DecimalFormatSymbols dfsn = new DecimalFormatSymbols(Locale.FRANCE);
+        testEHCS(dfs, dfs2, dfsn);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.DecimalFormatSymbols(DecimalFormatSymbols)'
+     */
+    public void testDecimalFormatSymbolsDecimalFormatSymbols() {
+        // implicitly tested everywhere
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.DecimalFormatSymbols()'
+     */
+    public void testDecimalFormatSymbols() {
+        DecimalFormatSymbols dfs = new DecimalFormatSymbols();
+        assertTrue(-1 != dfs.getDecimalSeparator());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.DecimalFormatSymbols(Locale)'
+     */
+    public void testDecimalFormatSymbolsLocale() {
+        DecimalFormatSymbols dfs = new DecimalFormatSymbols(Locale.US);
+        assertTrue(-1 != dfs.getDecimalSeparator());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.DecimalFormatSymbols(ULocale)'
+     */
+    public void testDecimalFormatSymbolsULocale() {
+        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
+        assertTrue(-1 != dfs.getDecimalSeparator());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.getZeroDigit()'
+     */
+    public void testGetZeroDigit() {
+        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
+        assertEquals('0', dfs.getZeroDigit());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.setZeroDigit(char)'
+     */
+    public void testSetZeroDigit() {
+        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
+        char value = dfs.getZeroDigit();
+        char value1 = (char)(value + 1);
+        dfs.setZeroDigit(value1);
+        char result = dfs.getZeroDigit();
+        assertNotEqual(value, result);
+        assertEquals(value1, result);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.getGroupingSeparator()'
+     */
+    public void testGetGroupingSeparator() {
+        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
+        assertEquals(',', dfs.getGroupingSeparator());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.setGroupingSeparator(char)'
+     */
+    public void testSetGroupingSeparator() {
+        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
+        char value = dfs.getGroupingSeparator();
+        char value1 = (char)(value + 1);
+        dfs.setGroupingSeparator(value1);
+        char result = dfs.getGroupingSeparator();
+        assertNotEqual(value, result);
+        assertEquals(value1, result);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.getDecimalSeparator()'
+     */
+    public void testGetDecimalSeparator() {
+        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
+        assertEquals('.', dfs.getDecimalSeparator());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.setDecimalSeparator(char)'
+     */
+    public void testSetDecimalSeparator() {
+        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
+        char value = dfs.getDecimalSeparator();
+        char value1 = (char)(value + 1);
+        dfs.setDecimalSeparator(value1);
+        char result = dfs.getDecimalSeparator();
+        assertNotEqual(value, result);
+        assertEquals(value1, result);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.getPerMill()'
+     */
+    public void testGetPerMill() {
+        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
+        assertEquals('\u2030', dfs.getPerMill());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.setPerMill(char)'
+     */
+    public void testSetPerMill() {
+        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
+        char value = dfs.getPerMill();
+        char value1 = (char)(value + 1);
+        dfs.setPerMill(value1);
+        char result = dfs.getPerMill();
+        assertNotEqual(value, result);
+        assertEquals(value1, result);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.getPercent()'
+     */
+    public void testGetPercent() {
+        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
+        assertEquals('%', dfs.getPercent());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.setPercent(char)'
+     */
+    public void testSetPercent() {
+        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
+        char value = dfs.getPercent();
+        char value1 = (char)(value + 1);
+        dfs.setPercent(value1);
+        char result = dfs.getPercent();
+        assertNotEqual(value, result);
+        assertEquals(value1, result);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.getDigit()'
+     */
+    public void testGetDigit() {
+        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
+        assertEquals('#', dfs.getDigit());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.setDigit(char)'
+     */
+    public void testSetDigit() {
+        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
+        char value = dfs.getDigit();
+        char value1 = (char)(value + 1);
+        dfs.setDigit(value1);
+        char result = dfs.getDigit();
+        assertNotEqual(value, result);
+        assertEquals(value1, result);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.getPatternSeparator()'
+     */
+    public void testGetPatternSeparator() {
+        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
+        assertEquals(';', dfs.getPatternSeparator());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.setPatternSeparator(char)'
+     */
+    public void testSetPatternSeparator() {
+        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
+        char value = dfs.getPatternSeparator();
+        char value1 = (char)(value + 1);
+        dfs.setPatternSeparator(value1);
+        char result = dfs.getPatternSeparator();
+        assertNotEqual(value, result);
+        assertEquals(value1, result);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.getInfinity()'
+     */
+    public void testGetInfinity() {
+        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
+        assertEquals("\u221e", dfs.getInfinity());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.setInfinity(String)'
+     */
+    public void testSetInfinity() {
+        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
+        String value = dfs.getInfinity();
+        String value1 = value + "!";
+        dfs.setInfinity(value1);
+        String result = dfs.getInfinity();
+        assertNotEqual(value, result);
+        assertEquals(value1, result);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.getNaN()'
+     */
+    public void testGetNaN() {
+        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
+        assertNotNull(dfs.getNaN()); // java returns missing character???
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.setNaN(String)'
+     */
+    public void testSetNaN() {
+        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
+        String value = dfs.getNaN();
+        String value1 = value + "!";
+        dfs.setNaN(value1);
+        String result = dfs.getNaN();
+        assertNotEqual(value, result);
+        assertEquals(value1, result);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.getMinusSign()'
+     */
+    public void testGetMinusSign() {
+        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
+        assertEquals('-', dfs.getMinusSign());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.setMinusSign(char)'
+     */
+    public void testSetMinusSign() {
+        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
+        char value = dfs.getMinusSign();
+        char value1 = (char)(value + 1);
+        dfs.setMinusSign(value1);
+        char result = dfs.getMinusSign();
+        assertNotEqual(value, result);
+        assertEquals(value1, result);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.getCurrencySymbol()'
+     */
+    public void testGetCurrencySymbol() {
+        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
+        assertEquals("$", dfs.getCurrencySymbol());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.setCurrencySymbol(String)'
+     */
+    public void testSetCurrencySymbol() {
+        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
+        String value = dfs.getCurrencySymbol();
+        String value1 = value + "!";
+        dfs.setCurrencySymbol(value1);
+        String result = dfs.getCurrencySymbol();
+        assertNotEqual(value, result);
+        assertEquals(value1, result);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.getInternationalCurrencySymbol()'
+     */
+    public void testGetInternationalCurrencySymbol() {
+        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
+        assertEquals("USD", dfs.getInternationalCurrencySymbol());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.setInternationalCurrencySymbol(String)'
+     */
+    public void testSetInternationalCurrencySymbol() {
+        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
+        String value = dfs.getInternationalCurrencySymbol();
+        String value1 = value + "!";
+        dfs.setInternationalCurrencySymbol(value1);
+        String result = dfs.getInternationalCurrencySymbol();
+        assertNotEqual(value, result);
+        assertEquals(value1, result);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.getMonetaryDecimalSeparator()'
+     */
+    public void testGetMonetaryDecimalSeparator() {
+        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
+        assertEquals('.', dfs.getMonetaryDecimalSeparator());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.setMonetaryDecimalSeparator(char)'
+     */
+    public void testSetMonetaryDecimalSeparator() {
+        DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.US);
+        char value = dfs.getMonetaryDecimalSeparator();
+        char value1 = (char)(value + 1);
+        dfs.setMonetaryDecimalSeparator(value1);
+        char result = dfs.getMonetaryDecimalSeparator();
+        assertNotEqual(value, result);
+        assertEquals(value1, result);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.clone()'
+     */
+    public void testClone() {
+        // tested in testHashcode
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormatSymbols.equals(Object)'
+     */
+    public void testEqualsObject() {
+        // tested in testHashcode
+    }
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/DecimalFormatTest.java b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/DecimalFormatTest.java
index 23cc40d..b438e2f 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/DecimalFormatTest.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/DecimalFormatTest.java
@@ -1,242 +1,242 @@
-/*
- *******************************************************************************
- * Copyright (C) 2006-2011, International Business Machines Corporation and    *
- * others. All Rights Reserved.                                                *
- *******************************************************************************
- */
-
-package com.ibm.icu.tests;
-
-import java.util.Locale;
-
-import com.ibm.icu.text.DecimalFormat;
-import com.ibm.icu.text.DecimalFormatSymbols;
-
-public class DecimalFormatTest extends ICUTestCase {
-    private static final long lmax = Long.MAX_VALUE;
-    private static final double dsmall = 23.33;
-        
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormat.clone()'
-     */
-    public void testClone() {
-        DecimalFormat df = new DecimalFormat("#,#0.00");
-        DecimalFormat df2 = new DecimalFormat("#,#0.00");
-        DecimalFormat dfn = new DecimalFormat("#,#0.00");
-        dfn.setNegativePrefix(dfn.getNegativePrefix() + '!');
-        testEHCS(df, df2, dfn);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormat.DecimalFormat(DecimalFormat)'
-     */
-    public void testDecimalFormatDecimalFormat() {
-        // tested implicitly
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormat.DecimalFormat()'
-     */
-    public void testDecimalFormat() {
-        DecimalFormat df = new DecimalFormat();
-        assertEquals("9,223,372,036,854,775,807", df.format(lmax));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormat.DecimalFormat(String)'
-     */
-    public void testDecimalFormatString() {
-        DecimalFormat df = new DecimalFormat("#,##0.000");
-        assertEquals("23.330", df.format(dsmall));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormat.DecimalFormat(String, DecimalFormatSymbols)'
-     */
-    public void testDecimalFormatStringDecimalFormatSymbols() {
-        DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.FRANCE);
-        DecimalFormat df = new DecimalFormat("#,##0.000", sym);
-        assertEquals("23,330", df.format(dsmall));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormat.getDecimalFormatSymbols()'
-     */
-    public void testGetDecimalFormatSymbols() {
-        DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.FRANCE);
-        DecimalFormat df = new DecimalFormat("#,##0.000", sym);
-        assertEquals(sym, df.getDecimalFormatSymbols());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormat.setDecimalFormatSymbols(DecimalFormatSymbols)'
-     */
-    public void testSetDecimalFormatSymbols() {
-        DecimalFormat df = new DecimalFormat();
-        df.setDecimalFormatSymbols(new DecimalFormatSymbols(Locale.FRANCE));
-        assertEquals("23,33", df.format(dsmall));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormat.getPositivePrefix()'
-     */
-    public void testGetPositivePrefix() {
-        DecimalFormat df = new DecimalFormat("+#,##0.#;-#,##0.#");
-        assertEquals("+", df.getPositivePrefix());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormat.setPositivePrefix(String)'
-     */
-    public void testSetPositivePrefix() {
-        DecimalFormat df = new DecimalFormat("+#,##0.#;-#,##0.#");
-        df.setPositivePrefix("?");
-        assertEquals("?23.3", df.format(dsmall));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormat.getNegativePrefix()'
-     */
-    public void testGetNegativePrefix() {
-        DecimalFormat df = new DecimalFormat("+#,##0.#;-#,##0.#");
-        assertEquals("-", df.getNegativePrefix());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormat.setNegativePrefix(String)'
-     */
-    public void testSetNegativePrefix() {
-        DecimalFormat df = new DecimalFormat("+#,##0.#;-#,##0.#");
-        df.setNegativePrefix("~");
-        assertEquals("~23.3", df.format(-dsmall));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormat.getPositiveSuffix()'
-     */
-    public void testGetPositiveSuffix() {
-        DecimalFormat df = new DecimalFormat("+#,##0.#**;-#,##0.#~~");
-        assertEquals("**", df.getPositiveSuffix());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormat.setPositiveSuffix(String)'
-     */
-    public void testSetPositiveSuffix() {
-        DecimalFormat df = new DecimalFormat("+#,##0.#;-#,##0.#");
-        df.setPositiveSuffix("**");
-        assertEquals("+23.3**", df.format(dsmall));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormat.getNegativeSuffix()'
-     */
-    public void testGetNegativeSuffix() {
-        DecimalFormat df = new DecimalFormat("+#,##0.#**;-#,##0.#~~");
-        assertEquals("~~", df.getNegativeSuffix());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormat.setNegativeSuffix(String)'
-     */
-    public void testSetNegativeSuffix() {
-        DecimalFormat df = new DecimalFormat("+#,##0.#;-#,##0.#");
-        df.setNegativeSuffix("~~");
-        assertEquals("-23.3~~", df.format(-dsmall));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormat.getMultiplier()'
-     */
-    public void testGetMultiplier() {
-        DecimalFormat df = new DecimalFormat("%000");
-        df.setMultiplier(1000);
-        assertEquals(1000, df.getMultiplier());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormat.setMultiplier(int)'
-     */
-    public void testSetMultiplier() {
-        DecimalFormat df = new DecimalFormat("%000");
-        assertEquals("%012", df.format(.123));
-        df.setMultiplier(1000);
-        assertEquals("%123", df.format(.123));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormat.getGroupingSize()'
-     */
-    public void testGetGroupingSize() {
-        DecimalFormat df = new DecimalFormat("#,#0.#");
-        assertEquals(2, df.getGroupingSize());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormat.setGroupingSize(int)'
-     */
-    public void testSetGroupingSize() {
-        DecimalFormat df = new DecimalFormat("#,##0.##");
-        assertEquals("1,234,567.89", df.format(1234567.89));
-        df.setGroupingSize(2);
-        assertEquals("1,23,45,67.89", df.format(1234567.89));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormat.isDecimalSeparatorAlwaysShown()'
-     */
-    public void testIsDecimalSeparatorAlwaysShown() {
-        DecimalFormat df = new DecimalFormat("#.#");
-        df.setDecimalSeparatorAlwaysShown(false);
-        assertEquals("1", df.format(1));
-        assertEquals("1.2", df.format(1.2));
-        df.setDecimalSeparatorAlwaysShown(true);
-        assertEquals("1.", df.format(1));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormat.setDecimalSeparatorAlwaysShown(boolean)'
-     */
-    public void testSetDecimalSeparatorAlwaysShown() {
-        DecimalFormat df = new DecimalFormat("#.#");
-        df.setDecimalSeparatorAlwaysShown(false);
-        assertFalse(df.isDecimalSeparatorAlwaysShown());
-        df.setDecimalSeparatorAlwaysShown(true);
-        assertTrue(df.isDecimalSeparatorAlwaysShown());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormat.toPattern()'
-     */
-    public void testToPattern() {
-        DecimalFormat df = new DecimalFormat("#,##0.##");
-        assertEquals("#,##0.##", df.toPattern());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormat.toLocalizedPattern()'
-     */
-    public void testToLocalizedPattern() {
-        DecimalFormat df = new DecimalFormat("#,##0.##", new DecimalFormatSymbols(Locale.FRANCE));
-        assertEquals("#,##0.##", df.toPattern());
-        assertEquals("#\u00a0##0,##", df.toLocalizedPattern());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormat.applyPattern(String)'
-     */
-    public void testApplyPattern() {
-        DecimalFormat df = new DecimalFormat("#,##0.##");
-        df.applyPattern("#,0.#");
-        assertEquals("1,2,3.4", df.format(123.4));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.DecimalFormat.applyLocalizedPattern(String)'
-     */
-    public void testApplyLocalizedPattern() {
-        DecimalFormat df = new DecimalFormat("#,##0.##", new DecimalFormatSymbols(Locale.FRANCE));
-        df.applyLocalizedPattern("#\u00a00,#");
-        assertEquals("1\u00a02\u00a03,4", df.format(123.4));
-    }
-}
+/*
+ *******************************************************************************
+ * Copyright (C) 2006-2011, International Business Machines Corporation and    *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+
+package com.ibm.icu.tests;
+
+import java.util.Locale;
+
+import com.ibm.icu.text.DecimalFormat;
+import com.ibm.icu.text.DecimalFormatSymbols;
+
+public class DecimalFormatTest extends ICUTestCase {
+    private static final long lmax = Long.MAX_VALUE;
+    private static final double dsmall = 23.33;
+        
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormat.clone()'
+     */
+    public void testClone() {
+        DecimalFormat df = new DecimalFormat("#,#0.00");
+        DecimalFormat df2 = new DecimalFormat("#,#0.00");
+        DecimalFormat dfn = new DecimalFormat("#,#0.00");
+        dfn.setNegativePrefix(dfn.getNegativePrefix() + '!');
+        testEHCS(df, df2, dfn);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormat.DecimalFormat(DecimalFormat)'
+     */
+    public void testDecimalFormatDecimalFormat() {
+        // tested implicitly
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormat.DecimalFormat()'
+     */
+    public void testDecimalFormat() {
+        DecimalFormat df = new DecimalFormat();
+        assertEquals("9,223,372,036,854,775,807", df.format(lmax));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormat.DecimalFormat(String)'
+     */
+    public void testDecimalFormatString() {
+        DecimalFormat df = new DecimalFormat("#,##0.000");
+        assertEquals("23.330", df.format(dsmall));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormat.DecimalFormat(String, DecimalFormatSymbols)'
+     */
+    public void testDecimalFormatStringDecimalFormatSymbols() {
+        DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.FRANCE);
+        DecimalFormat df = new DecimalFormat("#,##0.000", sym);
+        assertEquals("23,330", df.format(dsmall));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormat.getDecimalFormatSymbols()'
+     */
+    public void testGetDecimalFormatSymbols() {
+        DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.FRANCE);
+        DecimalFormat df = new DecimalFormat("#,##0.000", sym);
+        assertEquals(sym, df.getDecimalFormatSymbols());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormat.setDecimalFormatSymbols(DecimalFormatSymbols)'
+     */
+    public void testSetDecimalFormatSymbols() {
+        DecimalFormat df = new DecimalFormat();
+        df.setDecimalFormatSymbols(new DecimalFormatSymbols(Locale.FRANCE));
+        assertEquals("23,33", df.format(dsmall));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormat.getPositivePrefix()'
+     */
+    public void testGetPositivePrefix() {
+        DecimalFormat df = new DecimalFormat("+#,##0.#;-#,##0.#");
+        assertEquals("+", df.getPositivePrefix());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormat.setPositivePrefix(String)'
+     */
+    public void testSetPositivePrefix() {
+        DecimalFormat df = new DecimalFormat("+#,##0.#;-#,##0.#");
+        df.setPositivePrefix("?");
+        assertEquals("?23.3", df.format(dsmall));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormat.getNegativePrefix()'
+     */
+    public void testGetNegativePrefix() {
+        DecimalFormat df = new DecimalFormat("+#,##0.#;-#,##0.#");
+        assertEquals("-", df.getNegativePrefix());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormat.setNegativePrefix(String)'
+     */
+    public void testSetNegativePrefix() {
+        DecimalFormat df = new DecimalFormat("+#,##0.#;-#,##0.#");
+        df.setNegativePrefix("~");
+        assertEquals("~23.3", df.format(-dsmall));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormat.getPositiveSuffix()'
+     */
+    public void testGetPositiveSuffix() {
+        DecimalFormat df = new DecimalFormat("+#,##0.#**;-#,##0.#~~");
+        assertEquals("**", df.getPositiveSuffix());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormat.setPositiveSuffix(String)'
+     */
+    public void testSetPositiveSuffix() {
+        DecimalFormat df = new DecimalFormat("+#,##0.#;-#,##0.#");
+        df.setPositiveSuffix("**");
+        assertEquals("+23.3**", df.format(dsmall));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormat.getNegativeSuffix()'
+     */
+    public void testGetNegativeSuffix() {
+        DecimalFormat df = new DecimalFormat("+#,##0.#**;-#,##0.#~~");
+        assertEquals("~~", df.getNegativeSuffix());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormat.setNegativeSuffix(String)'
+     */
+    public void testSetNegativeSuffix() {
+        DecimalFormat df = new DecimalFormat("+#,##0.#;-#,##0.#");
+        df.setNegativeSuffix("~~");
+        assertEquals("-23.3~~", df.format(-dsmall));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormat.getMultiplier()'
+     */
+    public void testGetMultiplier() {
+        DecimalFormat df = new DecimalFormat("%000");
+        df.setMultiplier(1000);
+        assertEquals(1000, df.getMultiplier());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormat.setMultiplier(int)'
+     */
+    public void testSetMultiplier() {
+        DecimalFormat df = new DecimalFormat("%000");
+        assertEquals("%012", df.format(.123));
+        df.setMultiplier(1000);
+        assertEquals("%123", df.format(.123));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormat.getGroupingSize()'
+     */
+    public void testGetGroupingSize() {
+        DecimalFormat df = new DecimalFormat("#,#0.#");
+        assertEquals(2, df.getGroupingSize());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormat.setGroupingSize(int)'
+     */
+    public void testSetGroupingSize() {
+        DecimalFormat df = new DecimalFormat("#,##0.##");
+        assertEquals("1,234,567.89", df.format(1234567.89));
+        df.setGroupingSize(2);
+        assertEquals("1,23,45,67.89", df.format(1234567.89));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormat.isDecimalSeparatorAlwaysShown()'
+     */
+    public void testIsDecimalSeparatorAlwaysShown() {
+        DecimalFormat df = new DecimalFormat("#.#");
+        df.setDecimalSeparatorAlwaysShown(false);
+        assertEquals("1", df.format(1));
+        assertEquals("1.2", df.format(1.2));
+        df.setDecimalSeparatorAlwaysShown(true);
+        assertEquals("1.", df.format(1));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormat.setDecimalSeparatorAlwaysShown(boolean)'
+     */
+    public void testSetDecimalSeparatorAlwaysShown() {
+        DecimalFormat df = new DecimalFormat("#.#");
+        df.setDecimalSeparatorAlwaysShown(false);
+        assertFalse(df.isDecimalSeparatorAlwaysShown());
+        df.setDecimalSeparatorAlwaysShown(true);
+        assertTrue(df.isDecimalSeparatorAlwaysShown());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormat.toPattern()'
+     */
+    public void testToPattern() {
+        DecimalFormat df = new DecimalFormat("#,##0.##");
+        assertEquals("#,##0.##", df.toPattern());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormat.toLocalizedPattern()'
+     */
+    public void testToLocalizedPattern() {
+        DecimalFormat df = new DecimalFormat("#,##0.##", new DecimalFormatSymbols(Locale.FRANCE));
+        assertEquals("#,##0.##", df.toPattern());
+        assertEquals("#\u00a0##0,##", df.toLocalizedPattern());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormat.applyPattern(String)'
+     */
+    public void testApplyPattern() {
+        DecimalFormat df = new DecimalFormat("#,##0.##");
+        df.applyPattern("#,0.#");
+        assertEquals("1,2,3.4", df.format(123.4));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.DecimalFormat.applyLocalizedPattern(String)'
+     */
+    public void testApplyLocalizedPattern() {
+        DecimalFormat df = new DecimalFormat("#,##0.##", new DecimalFormatSymbols(Locale.FRANCE));
+        df.applyLocalizedPattern("#\u00a00,#");
+        assertEquals("1\u00a02\u00a03,4", df.format(123.4));
+    }
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/ICUTestCase.java b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/ICUTestCase.java
index 2e3de90..617fc14 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/ICUTestCase.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/ICUTestCase.java
@@ -1,286 +1,286 @@
-/*
- *******************************************************************************
- * Copyright (C) 2006-2011, International Business Machines Corporation and    *
- * others. All Rights Reserved.                                                *
- *******************************************************************************
- */
-
-package com.ibm.icu.tests;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.Externalizable;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.Serializable;
-import java.lang.reflect.Array;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.Locale;
-
-import com.ibm.icu.util.TimeZone;
-import com.ibm.icu.util.ULocale;
-
-import junit.framework.TestCase;
-
-/**
- * Implement boilerplate tests.
- * Currently there is only one method, testEHCS, which tests equals, hashCode, 
- * clone, and serialization.
- */
-public abstract class ICUTestCase extends TestCase {
-    private static final Object[] EMPTY_ARGS = {};
-	private static final Class<?>[] EMPTY_CLASSES = {};
-        
-    private static final Locale oldLocale = Locale.getDefault();
-    private static final ULocale oldULocale = ULocale.getDefault();
-    private static final java.util.TimeZone oldJTimeZone = java.util.TimeZone.getDefault();
-    private static final TimeZone oldITimeZone = TimeZone.getDefault();
-                
-    // TODO: what's the best way to check this?
-    public static final boolean testingWrapper = true;
-
-    protected void setUp() throws Exception {
-        super.setUp();
-        Locale.setDefault(Locale.US);
-        ULocale.setDefault(ULocale.US);
-        java.util.TimeZone.setDefault(java.util.TimeZone.getTimeZone("PST"));
-        TimeZone.setDefault(TimeZone.getTimeZone("PST"));
-    }
-        
-    protected void tearDown() throws Exception {
-        ULocale.setDefault(oldULocale);
-        Locale.setDefault(oldLocale);
-        TimeZone.setDefault(oldITimeZone);
-        java.util.TimeZone.setDefault(oldJTimeZone);
-        super.tearDown();
-    }
-
-    private static final Object test = new Object();
-        
-    /**
-     * Assert that two objects are _not_ equal.  Curiously missing from Assert.
-     * @param lhs an object to test, may be null
-     * @param rhs an object to test, may be null
-     */
-    public static void assertNotEqual(Object lhs, Object rhs) {
-        if (lhs == null) {
-            if (rhs == null) fail("null equals null");
-        } else {
-            if (lhs.equals(rhs)) {
-                fail(lhs.toString() + " equals " + rhs);
-            }
-        }
-    }
-        
-    public static void assertNotEqual(long lhs, long rhs) {
-        if (lhs == rhs) {
-            fail("values are equal: " + lhs);
-        }
-    }
-        
-    /**
-     * Test whether equality, hashCode, clone, and serialization work as expected.  
-     * Equals(Object) is assumed to return false (not throw an exception) if passed 
-     * null or an object of an incompatible class.
-     * Hashcodes must be equal iff the two objects compare equal.  No attempt is made to
-     * evaluate the quality of the hashcode distribution, so (in particular) degenerate 
-     * hashcode implementations will pass this test.
-     * Clone will be tested if the method "clone" is public on the class of obj.  
-     * It is assumed to return an object that compares equal to obj.
-     * Serialization will be tested if object implements Serializable or Externalizable.
-     * It is assumed the serialized/deserialized object compares equal to obj.
-     * @param obj the object to test
-     * @param eq an object that should compare equal to, but is not the same as, obj.  
-     *     it should be assignable to the class of obj.
-     * @param neq a non-null object that should not compare equal to obj.  
-     *     it should be assignable to the class of obj.
-     */
-	public static void testEHCS(Object obj, Object eq, Object neq) {
-        if (obj == null || eq == null || neq == null) {
-            throw new NullPointerException();
-        }
-        Class<? extends Object> cls = obj.getClass();
-        if (!(cls.isAssignableFrom(eq.getClass()) && cls.isAssignableFrom(neq.getClass()))) {
-            throw new IllegalArgumentException("unassignable classes");
-        }
-                
-        // reflexive
-        assertEquals(obj, obj);
-                
-        // should return false, not throw exception
-        assertNotEqual(obj, test);
-        assertNotEqual(obj, null);
-                
-        // commutative
-        assertEquals(obj, eq);
-        assertEquals(eq, obj);
-                
-        assertNotEqual(obj, neq);
-        assertNotEqual(neq, obj);
-                
-        // equal objects MUST have equal hashes, unequal objects MAY have equal hashes
-        assertEquals(obj.hashCode(), eq.hashCode());
-                
-        Object clone = null;
-        try {
-            // look for public clone method and call it if available
-            Method method_clone = cls.getMethod("clone", EMPTY_CLASSES);
-            clone = method_clone.invoke(obj, EMPTY_ARGS);
-            assertNotNull(clone);
-        }
-        catch(NoSuchMethodException e) {
-            // ok
-        }
-        catch(InvocationTargetException e) {
-            // ok
-        }
-        catch(IllegalAccessException e) {
-            // ok
-        }
-                
-        if (clone != null) {
-            assertEquals(obj, clone);
-            assertEquals(clone, obj);
-        }
-                
-        if (obj instanceof Serializable || obj instanceof Externalizable) {
-            Object ser = null;
-            try {
-                ByteArrayOutputStream bos = new ByteArrayOutputStream();
-                ObjectOutputStream oos = new ObjectOutputStream(bos);
-                oos.writeObject(clone);
-                oos.close();
-                                
-                ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
-                ObjectInputStream ois = new ObjectInputStream(bis);
-                ser = ois.readObject();
-                ois.close();
-            }
-            catch(IOException e) {
-                System.err.println(e.getMessage());
-                throw new RuntimeException(e);
-            }
-            catch(ClassNotFoundException e) {
-                System.err.println(e.getMessage());
-                throw new RuntimeException(e);
-            }
-                        
-            if (ser != null) {
-                assertEquals(obj, ser);
-                assertEquals(ser, obj);
-                assertEquals(obj.hashCode(), ser.hashCode());
-            }
-        }
-    }
-
-    /**
-     * Fail if the arrays are not equal.  To be equal, the arrays must
-     * be the same length, and each element in the left array must compare
-     * equal to the corresponding element of the right array.
-     * Also fails if one of the objects is not an array.
-     * @param lhs the left array
-     * @param rhs the right array
-     */
-    public static void assertArraysEqual(Object lhs, Object rhs) {
-        Class<? extends Object> lcls = lhs.getClass();
-        Class<? extends Object> rcls = rhs.getClass();
-        if (!(lcls.isArray() && rcls.isArray())) {
-            fail("objects are not arrays");
-        }
-        String result = arraysAreEqual(lhs, rhs);
-        if (result != null) {
-            fail(result);
-        }
-    }
-
-    /**
-     * Fail if the arrays are equal.  Also fails if one or the other 
-     * argument is not an array.
-     * @param lhs the left array
-     * @param rhs the right array
-     */
-    public static void assertArraysNotEqual(Object lhs, Object rhs) {
-        Class<? extends Object> lcls = lhs.getClass();
-        Class<? extends Object> rcls = rhs.getClass();
-        if (!(lcls.isArray() && rcls.isArray())) {
-            fail("objects are not arrays");
-        }
-        String result = arraysAreEqual(lhs, rhs);
-        if (result == null) {
-            fail("arrays are equal");
-        }
-    }
-        
-    // slow but general
-    private static String arraysAreEqual(Object lhsa, Object rhsa) {
-        int lhsl = Array.getLength(lhsa);
-        int rhsl = Array.getLength(rhsa);
-        if (lhsl != rhsl) {
-            return "length " + lhsl + " != " + rhsl;
-        }
-        boolean lhsaA = lhsa.getClass().getComponentType().isArray();
-        boolean rhsaA = rhsa.getClass().getComponentType().isArray();
-        if (lhsaA != rhsaA) {
-            return (lhsaA ? "" : "non-") + "array != " + (rhsaA ? "" : "non-") + "array";
-        }
-        for (int i = 0; i < lhsl; ++i) {
-            Object lhse = Array.get(lhsa, i);
-            Object rhse = Array.get(rhsa, i);
-            if (lhse == null) {
-                if (rhse != null) {
-                    return "null != " + rhse;
-                }
-            } else {
-                if (lhsaA) {
-                    String result = arraysAreEqual(lhse, rhse);
-                    if (result != null) {
-                        if (result.charAt(0) != '[') {
-                            result = " " + result;
-                        }
-                        return "[" + i + "]" + result;
-                    }
-                } else {
-                    if (!lhse.equals(rhse)) {
-                        return lhse.toString() + " != " + rhse;
-                    }
-                }
-            }
-        }
-        return null;
-    }
-        
-    // much more painful and slow than it should be... partly because of the
-    // oddness of clone, partly because arrays don't provide a Method for 
-    // 'clone' despite the fact that they implement it and make it public.
-    public static Object cloneComplex(Object obj) {
-        Object result = null;
-        if (obj != null) {
-            Class<? extends Object> cls = obj.getClass();
-            if (cls.isArray()) {
-                int len = Array.getLength(obj);
-                Class<?> typ = cls.getComponentType();
-                result = Array.newInstance(typ, len);
-                boolean prim = typ.isPrimitive();
-                for (int i = 0; i < len; ++i) {
-                    Object elem = Array.get(obj, i);
-                    Array.set(result, i, prim ? elem : cloneComplex(elem));
-                }
-            } else {
-                result = obj; // default
-                try {
-                    Method cloneM = cls.getMethod("clone", EMPTY_CLASSES);
-                    result = cloneM.invoke(obj, EMPTY_ARGS);
-                }
-                catch (NoSuchMethodException e) {
-                }
-                catch (IllegalAccessException e) {
-                }
-                catch (InvocationTargetException e) {
-                }
-            }
-        }
-        return result;
-    }
-}
+/*
+ *******************************************************************************
+ * Copyright (C) 2006-2011, International Business Machines Corporation and    *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+
+package com.ibm.icu.tests;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.lang.reflect.Array;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Locale;
+
+import com.ibm.icu.util.TimeZone;
+import com.ibm.icu.util.ULocale;
+
+import junit.framework.TestCase;
+
+/**
+ * Implement boilerplate tests.
+ * Currently there is only one method, testEHCS, which tests equals, hashCode, 
+ * clone, and serialization.
+ */
+public abstract class ICUTestCase extends TestCase {
+    private static final Object[] EMPTY_ARGS = {};
+	private static final Class<?>[] EMPTY_CLASSES = {};
+        
+    private static final Locale oldLocale = Locale.getDefault();
+    private static final ULocale oldULocale = ULocale.getDefault();
+    private static final java.util.TimeZone oldJTimeZone = java.util.TimeZone.getDefault();
+    private static final TimeZone oldITimeZone = TimeZone.getDefault();
+                
+    // TODO: what's the best way to check this?
+    public static final boolean testingWrapper = true;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        Locale.setDefault(Locale.US);
+        ULocale.setDefault(ULocale.US);
+        java.util.TimeZone.setDefault(java.util.TimeZone.getTimeZone("PST"));
+        TimeZone.setDefault(TimeZone.getTimeZone("PST"));
+    }
+        
+    protected void tearDown() throws Exception {
+        ULocale.setDefault(oldULocale);
+        Locale.setDefault(oldLocale);
+        TimeZone.setDefault(oldITimeZone);
+        java.util.TimeZone.setDefault(oldJTimeZone);
+        super.tearDown();
+    }
+
+    private static final Object test = new Object();
+        
+    /**
+     * Assert that two objects are _not_ equal.  Curiously missing from Assert.
+     * @param lhs an object to test, may be null
+     * @param rhs an object to test, may be null
+     */
+    public static void assertNotEqual(Object lhs, Object rhs) {
+        if (lhs == null) {
+            if (rhs == null) fail("null equals null");
+        } else {
+            if (lhs.equals(rhs)) {
+                fail(lhs.toString() + " equals " + rhs);
+            }
+        }
+    }
+        
+    public static void assertNotEqual(long lhs, long rhs) {
+        if (lhs == rhs) {
+            fail("values are equal: " + lhs);
+        }
+    }
+        
+    /**
+     * Test whether equality, hashCode, clone, and serialization work as expected.  
+     * Equals(Object) is assumed to return false (not throw an exception) if passed 
+     * null or an object of an incompatible class.
+     * Hashcodes must be equal iff the two objects compare equal.  No attempt is made to
+     * evaluate the quality of the hashcode distribution, so (in particular) degenerate 
+     * hashcode implementations will pass this test.
+     * Clone will be tested if the method "clone" is public on the class of obj.  
+     * It is assumed to return an object that compares equal to obj.
+     * Serialization will be tested if object implements Serializable or Externalizable.
+     * It is assumed the serialized/deserialized object compares equal to obj.
+     * @param obj the object to test
+     * @param eq an object that should compare equal to, but is not the same as, obj.  
+     *     it should be assignable to the class of obj.
+     * @param neq a non-null object that should not compare equal to obj.  
+     *     it should be assignable to the class of obj.
+     */
+	public static void testEHCS(Object obj, Object eq, Object neq) {
+        if (obj == null || eq == null || neq == null) {
+            throw new NullPointerException();
+        }
+        Class<? extends Object> cls = obj.getClass();
+        if (!(cls.isAssignableFrom(eq.getClass()) && cls.isAssignableFrom(neq.getClass()))) {
+            throw new IllegalArgumentException("unassignable classes");
+        }
+                
+        // reflexive
+        assertEquals(obj, obj);
+                
+        // should return false, not throw exception
+        assertNotEqual(obj, test);
+        assertNotEqual(obj, null);
+                
+        // commutative
+        assertEquals(obj, eq);
+        assertEquals(eq, obj);
+                
+        assertNotEqual(obj, neq);
+        assertNotEqual(neq, obj);
+                
+        // equal objects MUST have equal hashes, unequal objects MAY have equal hashes
+        assertEquals(obj.hashCode(), eq.hashCode());
+                
+        Object clone = null;
+        try {
+            // look for public clone method and call it if available
+            Method method_clone = cls.getMethod("clone", EMPTY_CLASSES);
+            clone = method_clone.invoke(obj, EMPTY_ARGS);
+            assertNotNull(clone);
+        }
+        catch(NoSuchMethodException e) {
+            // ok
+        }
+        catch(InvocationTargetException e) {
+            // ok
+        }
+        catch(IllegalAccessException e) {
+            // ok
+        }
+                
+        if (clone != null) {
+            assertEquals(obj, clone);
+            assertEquals(clone, obj);
+        }
+                
+        if (obj instanceof Serializable || obj instanceof Externalizable) {
+            Object ser = null;
+            try {
+                ByteArrayOutputStream bos = new ByteArrayOutputStream();
+                ObjectOutputStream oos = new ObjectOutputStream(bos);
+                oos.writeObject(clone);
+                oos.close();
+                                
+                ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
+                ObjectInputStream ois = new ObjectInputStream(bis);
+                ser = ois.readObject();
+                ois.close();
+            }
+            catch(IOException e) {
+                System.err.println(e.getMessage());
+                throw new RuntimeException(e);
+            }
+            catch(ClassNotFoundException e) {
+                System.err.println(e.getMessage());
+                throw new RuntimeException(e);
+            }
+                        
+            if (ser != null) {
+                assertEquals(obj, ser);
+                assertEquals(ser, obj);
+                assertEquals(obj.hashCode(), ser.hashCode());
+            }
+        }
+    }
+
+    /**
+     * Fail if the arrays are not equal.  To be equal, the arrays must
+     * be the same length, and each element in the left array must compare
+     * equal to the corresponding element of the right array.
+     * Also fails if one of the objects is not an array.
+     * @param lhs the left array
+     * @param rhs the right array
+     */
+    public static void assertArraysEqual(Object lhs, Object rhs) {
+        Class<? extends Object> lcls = lhs.getClass();
+        Class<? extends Object> rcls = rhs.getClass();
+        if (!(lcls.isArray() && rcls.isArray())) {
+            fail("objects are not arrays");
+        }
+        String result = arraysAreEqual(lhs, rhs);
+        if (result != null) {
+            fail(result);
+        }
+    }
+
+    /**
+     * Fail if the arrays are equal.  Also fails if one or the other 
+     * argument is not an array.
+     * @param lhs the left array
+     * @param rhs the right array
+     */
+    public static void assertArraysNotEqual(Object lhs, Object rhs) {
+        Class<? extends Object> lcls = lhs.getClass();
+        Class<? extends Object> rcls = rhs.getClass();
+        if (!(lcls.isArray() && rcls.isArray())) {
+            fail("objects are not arrays");
+        }
+        String result = arraysAreEqual(lhs, rhs);
+        if (result == null) {
+            fail("arrays are equal");
+        }
+    }
+        
+    // slow but general
+    private static String arraysAreEqual(Object lhsa, Object rhsa) {
+        int lhsl = Array.getLength(lhsa);
+        int rhsl = Array.getLength(rhsa);
+        if (lhsl != rhsl) {
+            return "length " + lhsl + " != " + rhsl;
+        }
+        boolean lhsaA = lhsa.getClass().getComponentType().isArray();
+        boolean rhsaA = rhsa.getClass().getComponentType().isArray();
+        if (lhsaA != rhsaA) {
+            return (lhsaA ? "" : "non-") + "array != " + (rhsaA ? "" : "non-") + "array";
+        }
+        for (int i = 0; i < lhsl; ++i) {
+            Object lhse = Array.get(lhsa, i);
+            Object rhse = Array.get(rhsa, i);
+            if (lhse == null) {
+                if (rhse != null) {
+                    return "null != " + rhse;
+                }
+            } else {
+                if (lhsaA) {
+                    String result = arraysAreEqual(lhse, rhse);
+                    if (result != null) {
+                        if (result.charAt(0) != '[') {
+                            result = " " + result;
+                        }
+                        return "[" + i + "]" + result;
+                    }
+                } else {
+                    if (!lhse.equals(rhse)) {
+                        return lhse.toString() + " != " + rhse;
+                    }
+                }
+            }
+        }
+        return null;
+    }
+        
+    // much more painful and slow than it should be... partly because of the
+    // oddness of clone, partly because arrays don't provide a Method for 
+    // 'clone' despite the fact that they implement it and make it public.
+    public static Object cloneComplex(Object obj) {
+        Object result = null;
+        if (obj != null) {
+            Class<? extends Object> cls = obj.getClass();
+            if (cls.isArray()) {
+                int len = Array.getLength(obj);
+                Class<?> typ = cls.getComponentType();
+                result = Array.newInstance(typ, len);
+                boolean prim = typ.isPrimitive();
+                for (int i = 0; i < len; ++i) {
+                    Object elem = Array.get(obj, i);
+                    Array.set(result, i, prim ? elem : cloneComplex(elem));
+                }
+            } else {
+                result = obj; // default
+                try {
+                    Method cloneM = cls.getMethod("clone", EMPTY_CLASSES);
+                    result = cloneM.invoke(obj, EMPTY_ARGS);
+                }
+                catch (NoSuchMethodException e) {
+                }
+                catch (IllegalAccessException e) {
+                }
+                catch (InvocationTargetException e) {
+                }
+            }
+        }
+        return result;
+    }
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/MessageFormatTest.java b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/MessageFormatTest.java
index 7f269fa..9947214 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/MessageFormatTest.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/MessageFormatTest.java
@@ -1,307 +1,307 @@
-/*
- *******************************************************************************
- * Copyright (C) 2006-2011, International Business Machines Corporation and    *
- * others. All Rights Reserved.                                                *
- *******************************************************************************
- */
-package com.ibm.icu.tests;
-
-import java.text.FieldPosition;
-import java.text.Format;
-import java.text.ParseException;
-import java.text.ParsePosition;
-import java.util.Date;
-import java.util.Locale;
-
-import com.ibm.icu.text.DateFormat;
-import com.ibm.icu.text.MessageFormat;
-import com.ibm.icu.text.NumberFormat;
-import com.ibm.icu.util.ULocale;
-
-public class MessageFormatTest extends ICUTestCase {
-    private final String pattern = "Deleted {0,number} files at {1,time,short} on {1,date}.";
-    private final String altPattern = "Deleted {0,  number } files at {1, time, short} on {1, date}.";
-    private final Date date = new Date(716698890835L);
-    private final Number num = new Long(3456);
-    private final Object[] args = { num, date };
-    private final Date dateOnly = new Date(716626800000L);
-    private final String englishTarget = "Deleted 3,456 files at 8:01 PM on Sep 16, 1992.";
-    private final String germanTarget = "Deleted 3.456 files at 20:01 on 16.09.1992.";
-    private final String modifiedTarget = "Deleted 3,456 files at 8:01:30 PM PDT on Sep 16, 1992.";
-    
-    /*
-     * Test method for 'com.ibm.icu.text.MessageFormat.hashCode()'
-     */
-    public void testHashCode() {
-        MessageFormat mf = new MessageFormat(pattern);
-        MessageFormat eq = new MessageFormat(altPattern);
-        MessageFormat ne = new MessageFormat("Deleted (0, number, currency} files at {1, time} on {1, date}.");
-        testEHCS(mf, eq, ne);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.MessageFormat.MessageFormat(MessageFormat)'
-     */
-    public void testMessageFormatMessageFormat() {
-        // implicitly tested everywhere
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.MessageFormat.MessageFormat(String)'
-     */
-    public void testMessageFormatString() {
-        MessageFormat mf = new MessageFormat(pattern);
-        assertEquals(englishTarget, mf.format(args));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.MessageFormat.MessageFormat(String, Locale)'
-     */
-    public void testMessageFormatStringLocale() {
-        MessageFormat mf = new MessageFormat(pattern, Locale.US);
-        assertEquals(englishTarget, mf.format(args));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.MessageFormat.MessageFormat(String, ULocale)'
-     */
-    public void testMessageFormatStringULocale() {
-        MessageFormat mf = new MessageFormat(pattern, ULocale.US);
-        assertEquals(englishTarget, mf.format(args));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.MessageFormat.setLocale(Locale)'
-     */
-    public void testSetLocaleLocale() {
-        MessageFormat mf = new MessageFormat(pattern, Locale.US);
-        mf.setLocale(Locale.GERMANY);
-        mf.applyPattern(pattern);
-        assertEquals(germanTarget, mf.format(args));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.MessageFormat.setLocale(ULocale)'
-     */
-    public void testSetLocaleULocale() {
-        MessageFormat mf = new MessageFormat(pattern, Locale.US);
-        mf.setLocale(ULocale.GERMANY);
-        mf.applyPattern(pattern);
-        assertEquals(germanTarget, mf.format(args));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.MessageFormat.getLocale()'
-     */
-    public void testGetLocale() {
-        MessageFormat mf = new MessageFormat(pattern, Locale.US);
-        mf.setLocale(Locale.GERMANY);
-        assertEquals(Locale.GERMANY, mf.getLocale());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.MessageFormat.getULocale()'
-     */
-    public void testGetULocale() {
-        MessageFormat mf = new MessageFormat(pattern, Locale.US);
-        mf.setLocale(ULocale.GERMANY);
-        assertEquals(ULocale.GERMANY, mf.getULocale());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.MessageFormat.applyPattern(String)'
-     */
-    public void testApplyPattern() {
-        MessageFormat mf = new MessageFormat("foo");
-        mf.applyPattern(pattern);
-        assertEquals(englishTarget, mf.format(args));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.MessageFormat.toPattern()'
-     */
-    public void testToPattern() {
-        MessageFormat mf = new MessageFormat(altPattern);
-        assertEquals(pattern, mf.toPattern());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.MessageFormat.setFormatsByArgumentIndex(Format[])'
-    public void testSetFormatsByArgumentIndex() {
-        // this api is broken.  if the same argument is used twice with two different
-        // formats, this can't be used, since it sets only one format per argument.
-        MessageFormat mf = new MessageFormat(pattern, Locale.US);
-        Format[] formats = {
-            NumberFormat.getIntegerInstance(),
-            DateFormat.getTimeInstance(DateFormat.SHORT),
-            DateFormat.getDateInstance(),
-        };
-        mf.setFormatsByArgumentIndex(formats);
-        assertEquals(brokenButConformantTarget, mf.format(args));
-    }
-     */
-
-    /*
-     * Test method for 'com.ibm.icu.text.MessageFormat.setFormats(Format[])'
-     */
-    public void testSetFormats() {
-        // this api, while it has the problem that the order of formats depends
-        // on the order in the string, at least lets you set all the formats.
-        
-        MessageFormat mf = new MessageFormat(pattern, Locale.US);
-        Format[] formats = {
-            NumberFormat.getIntegerInstance(),
-            DateFormat.getTimeInstance(DateFormat.SHORT),
-            DateFormat.getDateInstance(),
-        };
-        mf.setFormats(formats);
-        assertEquals(englishTarget, mf.format(args));
-   }
-
-    /*
-     * Test method for 'com.ibm.icu.text.MessageFormat.setFormatByArgumentIndex(int, Format)'
-     public void testSetFormatByArgumentIndex() {
-        // same problem, once you set a format for an argument, you've set all of them
-        
-        MessageFormat mf = new MessageFormat(pattern, Locale.US);
-        mf.setFormatByArgumentIndex(1, DateFormat.getTimeInstance(DateFormat.SHORT));
-        assertEquals(brokenButConformantTarget, mf.format(args));
-
-    }
-    */
-
-    /*
-     * Test method for 'com.ibm.icu.text.MessageFormat.setFormat(int, Format)'
-     */
-    public void testSetFormat() {
-        // and ok again        
-        MessageFormat mf = new MessageFormat(pattern, Locale.US);
-        mf.setFormat(1, DateFormat.getTimeInstance(DateFormat.LONG));
-        assertEquals(modifiedTarget, mf.format(args));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.MessageFormat.getFormatsByArgumentIndex()'
-    public void testGetFormatsByArgumentIndex() {
-        MessageFormat mf = new MessageFormat(pattern, Locale.US);
-        Format[] formats = mf.getFormatsByArgumentIndex();
-        NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
-        assertEquals(formats[0], nf);
-        DateFormat df = DateFormat.getDateInstance(DateFormat.DEFAULT, Locale.US);
-        assertEquals(formats[1], df);
-    }
-     */
-
-    /*
-     * Test method for 'com.ibm.icu.text.MessageFormat.getFormats()'
-     */
-    public void testGetFormats() {
-        MessageFormat mf = new MessageFormat(pattern, Locale.US);
-        Format[] formats = mf.getFormats();
-        NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
-        assertEquals(formats[0], nf);
-        DateFormat tf = DateFormat.getTimeInstance(DateFormat.SHORT, Locale.US);
-        assertEquals(formats[1], tf);
-        DateFormat df = DateFormat.getDateInstance(DateFormat.DEFAULT, Locale.US);
-        assertEquals(formats[2], df);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.MessageFormat.format(Object[], StringBuffer, FieldPosition)'
-     */
-    public void testFormatObjectArrayStringBufferFieldPosition() {
-        MessageFormat mf = new MessageFormat(pattern, Locale.US);
-        StringBuffer buf = new StringBuffer();
-        FieldPosition fp = new FieldPosition(0);
-        mf.format(args, buf, fp);
-        assertEquals(englishTarget, buf.toString());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.MessageFormat.format(String, Object[])'
-     */
-    public void testFormatStringObjectArray() {
-        assertEquals(englishTarget, MessageFormat.format(pattern, args));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.MessageFormat.format(Object, StringBuffer, FieldPosition)'
-     */
-    public void testFormatObjectStringBufferFieldPosition() {
-        MessageFormat mf = new MessageFormat(pattern, Locale.US);
-        StringBuffer buf = new StringBuffer();
-        FieldPosition fp = new FieldPosition(0);
-        mf.format((Object)args, buf, fp);
-        assertEquals(englishTarget, buf.toString());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.MessageFormat.parse(String, ParsePosition)'
-     */
-    public void testParseStringParsePosition() {
-        MessageFormat mf = new MessageFormat(pattern, Locale.US);
-        ParsePosition pp = new ParsePosition(1);
-        Object[] result = mf.parse("!" + englishTarget, pp);
-        assertEquals(num, result[0]);
-        assertEquals(dateOnly, result[1]);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.MessageFormat.parse(String)'
-     */
-    public void testParseString() {
-        MessageFormat mf = new MessageFormat(pattern, Locale.US);
-        try {
-            Object[] result = mf.parse(englishTarget);
-            assertEquals(num, result[0]);
-            assertEquals(dateOnly, result[1]);
-        }
-        catch (ParseException e) {
-            fail(e.getMessage());
-        }
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.MessageFormat.parseObject(String, ParsePosition)'
-     */
-    public void testParseObjectStringParsePosition() {
-        MessageFormat mf = new MessageFormat(pattern, Locale.US);
-        ParsePosition pp = new ParsePosition(0);
-        Object result = mf.parseObject(englishTarget, pp);
-        assertEquals(num, ((Object[])result)[0]);
-        assertEquals(dateOnly, ((Object[])result)[1]);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.MessageFormat.autoQuoteApostrophe(String)'
-     */
-    public void testAutoQuoteApostrophe() {
-        String str = "Let's meet at {1,time,h 'o'' clock'} at l'Orange Bleue";
-        String pat = MessageFormat.autoQuoteApostrophe(str);
-        MessageFormat mf = new MessageFormat(pat, Locale.US);
-        String result = mf.format(args);
-        assertEquals("Let's meet at 8 o' clock at l'Orange Bleue", result);
-        assertEquals("Let''s meet at {1,time,h 'o'' clock'} at l''Orange Bleue", pat);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.MessageFormat.clone()'
-     */
-    public void testClone() {
-        // tested already in testHashcode
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.MessageFormat.equals(Object)'
-     */
-    public void testEqualsObject() {
-        // tested already in testHashcode
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.MessageFormat.toString()'
-     */
-    public void testToString() {
-        // no need to test
-    }
-}
+/*
+ *******************************************************************************
+ * Copyright (C) 2006-2011, International Business Machines Corporation and    *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+package com.ibm.icu.tests;
+
+import java.text.FieldPosition;
+import java.text.Format;
+import java.text.ParseException;
+import java.text.ParsePosition;
+import java.util.Date;
+import java.util.Locale;
+
+import com.ibm.icu.text.DateFormat;
+import com.ibm.icu.text.MessageFormat;
+import com.ibm.icu.text.NumberFormat;
+import com.ibm.icu.util.ULocale;
+
+public class MessageFormatTest extends ICUTestCase {
+    private final String pattern = "Deleted {0,number} files at {1,time,short} on {1,date}.";
+    private final String altPattern = "Deleted {0,  number } files at {1, time, short} on {1, date}.";
+    private final Date date = new Date(716698890835L);
+    private final Number num = new Long(3456);
+    private final Object[] args = { num, date };
+    private final Date dateOnly = new Date(716626800000L);
+    private final String englishTarget = "Deleted 3,456 files at 8:01 PM on Sep 16, 1992.";
+    private final String germanTarget = "Deleted 3.456 files at 20:01 on 16.09.1992.";
+    private final String modifiedTarget = "Deleted 3,456 files at 8:01:30 PM PDT on Sep 16, 1992.";
+    
+    /*
+     * Test method for 'com.ibm.icu.text.MessageFormat.hashCode()'
+     */
+    public void testHashCode() {
+        MessageFormat mf = new MessageFormat(pattern);
+        MessageFormat eq = new MessageFormat(altPattern);
+        MessageFormat ne = new MessageFormat("Deleted (0, number, currency} files at {1, time} on {1, date}.");
+        testEHCS(mf, eq, ne);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.MessageFormat.MessageFormat(MessageFormat)'
+     */
+    public void testMessageFormatMessageFormat() {
+        // implicitly tested everywhere
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.MessageFormat.MessageFormat(String)'
+     */
+    public void testMessageFormatString() {
+        MessageFormat mf = new MessageFormat(pattern);
+        assertEquals(englishTarget, mf.format(args));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.MessageFormat.MessageFormat(String, Locale)'
+     */
+    public void testMessageFormatStringLocale() {
+        MessageFormat mf = new MessageFormat(pattern, Locale.US);
+        assertEquals(englishTarget, mf.format(args));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.MessageFormat.MessageFormat(String, ULocale)'
+     */
+    public void testMessageFormatStringULocale() {
+        MessageFormat mf = new MessageFormat(pattern, ULocale.US);
+        assertEquals(englishTarget, mf.format(args));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.MessageFormat.setLocale(Locale)'
+     */
+    public void testSetLocaleLocale() {
+        MessageFormat mf = new MessageFormat(pattern, Locale.US);
+        mf.setLocale(Locale.GERMANY);
+        mf.applyPattern(pattern);
+        assertEquals(germanTarget, mf.format(args));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.MessageFormat.setLocale(ULocale)'
+     */
+    public void testSetLocaleULocale() {
+        MessageFormat mf = new MessageFormat(pattern, Locale.US);
+        mf.setLocale(ULocale.GERMANY);
+        mf.applyPattern(pattern);
+        assertEquals(germanTarget, mf.format(args));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.MessageFormat.getLocale()'
+     */
+    public void testGetLocale() {
+        MessageFormat mf = new MessageFormat(pattern, Locale.US);
+        mf.setLocale(Locale.GERMANY);
+        assertEquals(Locale.GERMANY, mf.getLocale());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.MessageFormat.getULocale()'
+     */
+    public void testGetULocale() {
+        MessageFormat mf = new MessageFormat(pattern, Locale.US);
+        mf.setLocale(ULocale.GERMANY);
+        assertEquals(ULocale.GERMANY, mf.getULocale());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.MessageFormat.applyPattern(String)'
+     */
+    public void testApplyPattern() {
+        MessageFormat mf = new MessageFormat("foo");
+        mf.applyPattern(pattern);
+        assertEquals(englishTarget, mf.format(args));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.MessageFormat.toPattern()'
+     */
+    public void testToPattern() {
+        MessageFormat mf = new MessageFormat(altPattern);
+        assertEquals(pattern, mf.toPattern());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.MessageFormat.setFormatsByArgumentIndex(Format[])'
+    public void testSetFormatsByArgumentIndex() {
+        // this api is broken.  if the same argument is used twice with two different
+        // formats, this can't be used, since it sets only one format per argument.
+        MessageFormat mf = new MessageFormat(pattern, Locale.US);
+        Format[] formats = {
+            NumberFormat.getIntegerInstance(),
+            DateFormat.getTimeInstance(DateFormat.SHORT),
+            DateFormat.getDateInstance(),
+        };
+        mf.setFormatsByArgumentIndex(formats);
+        assertEquals(brokenButConformantTarget, mf.format(args));
+    }
+     */
+
+    /*
+     * Test method for 'com.ibm.icu.text.MessageFormat.setFormats(Format[])'
+     */
+    public void testSetFormats() {
+        // this api, while it has the problem that the order of formats depends
+        // on the order in the string, at least lets you set all the formats.
+        
+        MessageFormat mf = new MessageFormat(pattern, Locale.US);
+        Format[] formats = {
+            NumberFormat.getIntegerInstance(),
+            DateFormat.getTimeInstance(DateFormat.SHORT),
+            DateFormat.getDateInstance(),
+        };
+        mf.setFormats(formats);
+        assertEquals(englishTarget, mf.format(args));
+   }
+
+    /*
+     * Test method for 'com.ibm.icu.text.MessageFormat.setFormatByArgumentIndex(int, Format)'
+     public void testSetFormatByArgumentIndex() {
+        // same problem, once you set a format for an argument, you've set all of them
+        
+        MessageFormat mf = new MessageFormat(pattern, Locale.US);
+        mf.setFormatByArgumentIndex(1, DateFormat.getTimeInstance(DateFormat.SHORT));
+        assertEquals(brokenButConformantTarget, mf.format(args));
+
+    }
+    */
+
+    /*
+     * Test method for 'com.ibm.icu.text.MessageFormat.setFormat(int, Format)'
+     */
+    public void testSetFormat() {
+        // and ok again        
+        MessageFormat mf = new MessageFormat(pattern, Locale.US);
+        mf.setFormat(1, DateFormat.getTimeInstance(DateFormat.LONG));
+        assertEquals(modifiedTarget, mf.format(args));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.MessageFormat.getFormatsByArgumentIndex()'
+    public void testGetFormatsByArgumentIndex() {
+        MessageFormat mf = new MessageFormat(pattern, Locale.US);
+        Format[] formats = mf.getFormatsByArgumentIndex();
+        NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
+        assertEquals(formats[0], nf);
+        DateFormat df = DateFormat.getDateInstance(DateFormat.DEFAULT, Locale.US);
+        assertEquals(formats[1], df);
+    }
+     */
+
+    /*
+     * Test method for 'com.ibm.icu.text.MessageFormat.getFormats()'
+     */
+    public void testGetFormats() {
+        MessageFormat mf = new MessageFormat(pattern, Locale.US);
+        Format[] formats = mf.getFormats();
+        NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
+        assertEquals(formats[0], nf);
+        DateFormat tf = DateFormat.getTimeInstance(DateFormat.SHORT, Locale.US);
+        assertEquals(formats[1], tf);
+        DateFormat df = DateFormat.getDateInstance(DateFormat.DEFAULT, Locale.US);
+        assertEquals(formats[2], df);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.MessageFormat.format(Object[], StringBuffer, FieldPosition)'
+     */
+    public void testFormatObjectArrayStringBufferFieldPosition() {
+        MessageFormat mf = new MessageFormat(pattern, Locale.US);
+        StringBuffer buf = new StringBuffer();
+        FieldPosition fp = new FieldPosition(0);
+        mf.format(args, buf, fp);
+        assertEquals(englishTarget, buf.toString());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.MessageFormat.format(String, Object[])'
+     */
+    public void testFormatStringObjectArray() {
+        assertEquals(englishTarget, MessageFormat.format(pattern, args));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.MessageFormat.format(Object, StringBuffer, FieldPosition)'
+     */
+    public void testFormatObjectStringBufferFieldPosition() {
+        MessageFormat mf = new MessageFormat(pattern, Locale.US);
+        StringBuffer buf = new StringBuffer();
+        FieldPosition fp = new FieldPosition(0);
+        mf.format((Object)args, buf, fp);
+        assertEquals(englishTarget, buf.toString());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.MessageFormat.parse(String, ParsePosition)'
+     */
+    public void testParseStringParsePosition() {
+        MessageFormat mf = new MessageFormat(pattern, Locale.US);
+        ParsePosition pp = new ParsePosition(1);
+        Object[] result = mf.parse("!" + englishTarget, pp);
+        assertEquals(num, result[0]);
+        assertEquals(dateOnly, result[1]);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.MessageFormat.parse(String)'
+     */
+    public void testParseString() {
+        MessageFormat mf = new MessageFormat(pattern, Locale.US);
+        try {
+            Object[] result = mf.parse(englishTarget);
+            assertEquals(num, result[0]);
+            assertEquals(dateOnly, result[1]);
+        }
+        catch (ParseException e) {
+            fail(e.getMessage());
+        }
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.MessageFormat.parseObject(String, ParsePosition)'
+     */
+    public void testParseObjectStringParsePosition() {
+        MessageFormat mf = new MessageFormat(pattern, Locale.US);
+        ParsePosition pp = new ParsePosition(0);
+        Object result = mf.parseObject(englishTarget, pp);
+        assertEquals(num, ((Object[])result)[0]);
+        assertEquals(dateOnly, ((Object[])result)[1]);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.MessageFormat.autoQuoteApostrophe(String)'
+     */
+    public void testAutoQuoteApostrophe() {
+        String str = "Let's meet at {1,time,h 'o'' clock'} at l'Orange Bleue";
+        String pat = MessageFormat.autoQuoteApostrophe(str);
+        MessageFormat mf = new MessageFormat(pat, Locale.US);
+        String result = mf.format(args);
+        assertEquals("Let's meet at 8 o' clock at l'Orange Bleue", result);
+        assertEquals("Let''s meet at {1,time,h 'o'' clock'} at l''Orange Bleue", pat);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.MessageFormat.clone()'
+     */
+    public void testClone() {
+        // tested already in testHashcode
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.MessageFormat.equals(Object)'
+     */
+    public void testEqualsObject() {
+        // tested already in testHashcode
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.MessageFormat.toString()'
+     */
+    public void testToString() {
+        // no need to test
+    }
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/NumberFormatTest.java b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/NumberFormatTest.java
index 3c7b7dd..ec7188f 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/NumberFormatTest.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/NumberFormatTest.java
@@ -1,447 +1,447 @@
-/*
- *******************************************************************************
- * Copyright (C) 2007-2011, International Business Machines Corporation and    *
- * others. All Rights Reserved.                                                *
- *******************************************************************************
- */
-
-package com.ibm.icu.tests;
-
-import java.math.BigInteger;
-import java.text.FieldPosition;
-import java.text.ParseException;
-import java.text.ParsePosition;
-import java.util.Locale;
-
-import com.ibm.icu.text.NumberFormat;
-import com.ibm.icu.util.ULocale;
-
-public class NumberFormatTest extends ICUTestCase {
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.NumberFormat(NumberFormat)'
-     */
-    public void testNumberFormat() {
-        NumberFormat nf = new NumberFormat(java.text.NumberFormat.getInstance());
-        assertEquals(nf, NumberFormat.getInstance());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.format(Object, StringBuffer, FieldPosition)'
-     */
-    public void testFormatObjectStringBufferFieldPosition() {
-        Number num = new Long(1234L);
-        StringBuffer buf = new StringBuffer();
-        FieldPosition fp = new FieldPosition(NumberFormat.INTEGER_FIELD);
-        NumberFormat.getInstance().format(num, buf, fp);
-        assertEquals("1,234", buf.toString());
-        assertEquals(0, fp.getBeginIndex());
-        assertEquals(5, fp.getEndIndex());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.parseObject(String, ParsePosition)'
-     */
-    public void testParseObjectStringParsePosition() {
-        ParsePosition pp = new ParsePosition(0);
-        Object result = NumberFormat.getInstance().parse("1,234", pp);
-        assertEquals(result, new Long(1234));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.format(double)'
-     */
-    public void testFormatDouble() {
-        assertEquals("1,234.567", NumberFormat.getInstance().format(1234.567));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.format(long)'
-     */
-    public void testFormatLong() {
-        assertEquals("1,234", NumberFormat.getInstance().format(1234L));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.format(BigInteger)'
-     */
-    public void testFormatBigInteger() {
-        // note, java doesn't handle biginteger with full precision.
-        BigInteger bi = new BigInteger("123456");
-        assertEquals("123,456", java.text.NumberFormat.getInstance().format(bi));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.format(double, StringBuffer, FieldPosition)'
-     */
-    public void testFormatDoubleStringBufferFieldPosition() {
-        StringBuffer buf = new StringBuffer();
-        FieldPosition fp = new FieldPosition(NumberFormat.FRACTION_FIELD);
-        assertEquals("123,456.789", NumberFormat.getInstance().format(123456.789, buf, fp).toString());
-        assertEquals(8, fp.getBeginIndex());
-        assertEquals(11, fp.getEndIndex());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.format(long, StringBuffer, FieldPosition)'
-     */
-    public void testFormatLongStringBufferFieldPosition() {
-        StringBuffer buf = new StringBuffer();
-        FieldPosition fp = new FieldPosition(NumberFormat.Field.GROUPING_SEPARATOR);
-        assertEquals("123,456", NumberFormat.getInstance().format(123456L, buf, fp).toString());
-        assertEquals(3, fp.getBeginIndex());
-        assertEquals(4, fp.getEndIndex());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.format(BigInteger, StringBuffer, FieldPosition)'
-     */
-    public void testFormatBigIntegerStringBufferFieldPosition() {
-        // note, java doesn't handle biginteger with full precision.
-        StringBuffer buf = new StringBuffer();
-        FieldPosition fp = new FieldPosition(0);
-        BigInteger bi = new BigInteger("123456");
-        assertEquals("123,456", java.text.NumberFormat.getInstance().format(bi, buf, fp).toString());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.parse(String, ParsePosition)'
-     */
-    public void testParseStringParsePosition() {
-        ParsePosition pp = new ParsePosition(3);
-        assertEquals(new Long(123456), NumberFormat.getInstance().parse("xxx123,456yyy", pp));
-        assertEquals(10, pp.getIndex());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.parse(String)'
-     */
-    public void testParseString() throws ParseException {
-        Number result = NumberFormat.getInstance().parse("123,456,yyy");
-        assertEquals(new Long(123456), result);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.isParseIntegerOnly()'
-     */
-    public void testIsParseIntegerOnly() {
-        NumberFormat nf = NumberFormat.getInstance();
-        nf.setParseIntegerOnly(true);
-        assertTrue(nf.isParseIntegerOnly());
-        nf.setParseIntegerOnly(false);
-        assertFalse(nf.isParseIntegerOnly());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.setParseIntegerOnly(boolean)'
-     */
-    public void testSetParseIntegerOnly() throws ParseException {
-        String str = "123.456,yyy";
-        NumberFormat nf = NumberFormat.getInstance();
-        assertEquals(new Double(123.456), nf.parse(str));
-        nf.setParseIntegerOnly(true);
-        assertEquals(new Long(123), nf.parse(str));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.getInstance()'
-     */
-    public void testGetInstance() {
-        // used everywhere, no need to test
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.getInstance(Locale)'
-     */
-    public void testGetInstanceLocale() {
-        NumberFormat nf = NumberFormat.getInstance(Locale.GERMANY);
-        assertEquals("123,456", nf.format(123.456));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.getInstance(ULocale)'
-     */
-    public void testGetInstanceULocale() {
-        NumberFormat nf = NumberFormat.getInstance(ULocale.GERMANY);
-        assertEquals("123,456", nf.format(123.456));            
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.getNumberInstance()'
-     */
-    public void testGetNumberInstance() {
-        NumberFormat nf = NumberFormat.getNumberInstance();
-        assertEquals("123,456.789", nf.format(123456.789));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.getNumberInstance(Locale)'
-     */
-    public void testGetNumberInstanceLocale() {
-        NumberFormat nf = NumberFormat.getNumberInstance(Locale.GERMANY);
-        assertEquals("123.456,789", nf.format(123456.789));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.getNumberInstance(ULocale)'
-     */
-    public void testGetNumberInstanceULocale() {
-        NumberFormat nf = NumberFormat.getNumberInstance(ULocale.GERMANY);
-        assertEquals("123.456,789", nf.format(123456.789));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.getIntegerInstance()'
-     */
-    public void testGetIntegerInstance() {
-        NumberFormat nf = NumberFormat.getIntegerInstance();
-        assertEquals("123,457", nf.format(123456.789)); // rounds
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.getIntegerInstance(Locale)'
-     */
-    public void testGetIntegerInstanceLocale() {
-        NumberFormat nf = NumberFormat.getIntegerInstance(Locale.GERMANY);
-        assertEquals("123.457", nf.format(123456.789)); // rounds
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.getIntegerInstance(ULocale)'
-     */
-    public void testGetIntegerInstanceULocale() {
-        NumberFormat nf = NumberFormat.getIntegerInstance(ULocale.GERMANY);
-        assertEquals("123.457", nf.format(123456.789)); // rounds
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.getCurrencyInstance()'
-     */
-    public void testGetCurrencyInstance() {
-        NumberFormat nf = NumberFormat.getCurrencyInstance();
-        assertEquals("$123,456.99", nf.format(123456.99));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.getCurrencyInstance(Locale)'
-     */
-    public void testGetCurrencyInstanceLocale() {
-        NumberFormat nf = NumberFormat.getCurrencyInstance(Locale.GERMANY);
-        assertEquals("123.456,99 \u20AC", nf.format(123456.99));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.getCurrencyInstance(ULocale)'
-     */
-    public void testGetCurrencyInstanceULocale() {
-        NumberFormat nf = NumberFormat.getCurrencyInstance(ULocale.GERMANY);
-        assertEquals("123.456,99 \u20AC", nf.format(123456.99));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.getPercentInstance()'
-     */
-    public void testGetPercentInstance() {
-        NumberFormat nf = NumberFormat.getPercentInstance();
-        assertEquals("123,456%", nf.format(1234.56));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.getPercentInstance(Locale)'
-     */
-    public void testGetPercentInstanceLocale() {
-        NumberFormat nf = NumberFormat.getPercentInstance(Locale.GERMANY);
-        assertEquals("123.456%", nf.format(1234.56));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.getPercentInstance(ULocale)'
-     */
-    public void testGetPercentInstanceULocale() {
-        NumberFormat nf = NumberFormat.getPercentInstance(ULocale.GERMANY);
-        assertEquals("123.456%", nf.format(1234.56));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.getScientificInstance()'
-     */
-    public void testGetScientificInstance() {
-        NumberFormat nf = NumberFormat.getScientificInstance();
-        assertEquals(".123456E4", nf.format(1234.56));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.getScientificInstance(Locale)'
-     */
-    public void testGetScientificInstanceLocale() {
-        NumberFormat nf = NumberFormat.getScientificInstance(Locale.GERMANY);
-        assertEquals(",123456E4", nf.format(1234.56));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.getScientificInstance(ULocale)'
-     */
-    public void testGetScientificInstanceULocale() {
-        NumberFormat nf = NumberFormat.getScientificInstance(ULocale.GERMANY);
-        assertEquals(",123456E4", nf.format(1234.56));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.getAvailableLocales()'
-     */
-    public void testGetAvailableLocales() {
-        Locale[] ilocales = NumberFormat.getAvailableLocales();
-        if (ICUTestCase.testingWrapper) {
-            Locale[] jlocales = java.text.NumberFormat.getAvailableLocales();
-            for (int i = 0; i < ilocales.length; ++i) {
-                assertEquals(jlocales[i], ilocales[i]);
-            }
-        }
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.getAvailableULocales()'
-     */
-    public void testGetAvailableULocales() {
-        ULocale[] ulocales = NumberFormat.getAvailableULocales();
-        if (ICUTestCase.testingWrapper) {
-            Locale[] jlocales = java.text.NumberFormat.getAvailableLocales();
-            for (int i = 0; i < ulocales.length; ++i) {
-                assertEquals(jlocales[i], ulocales[i].toLocale());
-            }
-        }
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.isGroupingUsed()'
-     */
-    public void testIsGroupingUsed() {
-        NumberFormat nf = NumberFormat.getInstance();
-        nf.setGroupingUsed(true);
-        assertTrue(nf.isGroupingUsed());
-        nf.setGroupingUsed(false);
-        assertFalse(nf.isGroupingUsed());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.setGroupingUsed(boolean)'
-     */
-    public void testSetGroupingUsed() {
-        NumberFormat nf = NumberFormat.getInstance();
-        assertEquals("123,456,789", nf.format(123456789));
-        nf.setGroupingUsed(false);
-        assertEquals("123456789", nf.format(123456789));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.getMaximumIntegerDigits()'
-     */
-    public void testGetMaximumIntegerDigits() {
-        NumberFormat nf = NumberFormat.getInstance();
-        nf.setMaximumIntegerDigits(4);
-        assertEquals(4, nf.getMaximumIntegerDigits());
-        nf.setMaximumIntegerDigits(6);
-        assertEquals(6, nf.getMaximumIntegerDigits());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.setMaximumIntegerDigits(int)'
-     */
-    public void testSetMaximumIntegerDigits() {
-        NumberFormat nf = NumberFormat.getInstance();
-        nf.setMaximumIntegerDigits(4);
-        assertEquals("3,456", nf.format(123456)); // high digits truncated
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.getMinimumIntegerDigits()'
-     */
-    public void testGetMinimumIntegerDigits() {
-        NumberFormat nf = NumberFormat.getInstance();
-        nf.setMinimumIntegerDigits(4);
-        assertEquals(4, nf.getMinimumIntegerDigits());
-        nf.setMinimumIntegerDigits(6);
-        assertEquals(6, nf.getMinimumIntegerDigits());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.setMinimumIntegerDigits(int)'
-     */
-    public void testSetMinimumIntegerDigits() {
-        NumberFormat nf = NumberFormat.getInstance();
-        nf.setMinimumIntegerDigits(4);
-        assertEquals("0,012", nf.format(12)); // pad out with zero, grouping still used
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.getMaximumFractionDigits()'
-     */
-    public void testGetMaximumFractionDigits() {
-        NumberFormat nf = NumberFormat.getInstance();
-        nf.setMaximumFractionDigits(4);
-        assertEquals(4, nf.getMaximumFractionDigits());
-        nf.setMaximumFractionDigits(6);
-        assertEquals(6, nf.getMaximumFractionDigits());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.setMaximumFractionDigits(int)'
-     */
-    public void testSetMaximumFractionDigits() {
-        NumberFormat nf = NumberFormat.getInstance();
-        nf.setMaximumFractionDigits(4);
-        assertEquals("1.2346", nf.format(1.2345678)); // low digits rounded
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.getMinimumFractionDigits()'
-     */
-    public void testGetMinimumFractionDigits() {
-        NumberFormat nf = NumberFormat.getInstance();
-        nf.setMinimumFractionDigits(4);
-        assertEquals(4, nf.getMinimumFractionDigits());
-        nf.setMinimumFractionDigits(6);
-        assertEquals(6, nf.getMinimumFractionDigits());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.setMinimumFractionDigits(int)'
-     */
-    public void testSetMinimumFractionDigits() {
-        NumberFormat nf = NumberFormat.getInstance();
-        nf.setMinimumFractionDigits(4);
-        assertEquals("1.2000", nf.format(1.2));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.toString()'
-     */
-    public void testToString() {
-        assertNotNull(NumberFormat.getInstance().toString());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.hashCode()'
-     */
-    public void testHashCode() {
-        NumberFormat nf = NumberFormat.getInstance();
-        NumberFormat eq = NumberFormat.getInstance(Locale.US);
-        NumberFormat neq = NumberFormat.getInstance(Locale.GERMANY);
-                
-        ICUTestCase.testEHCS(nf, eq, neq);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.clone()'
-     */
-    public void testClone() {
-        // see testHashCode
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.text.NumberFormat.equals(Object)'
-     */
-    public void testEqualsObject() {
-        // see testHashCode
-    }
-}
+/*
+ *******************************************************************************
+ * Copyright (C) 2007-2011, International Business Machines Corporation and    *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+
+package com.ibm.icu.tests;
+
+import java.math.BigInteger;
+import java.text.FieldPosition;
+import java.text.ParseException;
+import java.text.ParsePosition;
+import java.util.Locale;
+
+import com.ibm.icu.text.NumberFormat;
+import com.ibm.icu.util.ULocale;
+
+public class NumberFormatTest extends ICUTestCase {
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.NumberFormat(NumberFormat)'
+     */
+    public void testNumberFormat() {
+        NumberFormat nf = new NumberFormat(java.text.NumberFormat.getInstance());
+        assertEquals(nf, NumberFormat.getInstance());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.format(Object, StringBuffer, FieldPosition)'
+     */
+    public void testFormatObjectStringBufferFieldPosition() {
+        Number num = new Long(1234L);
+        StringBuffer buf = new StringBuffer();
+        FieldPosition fp = new FieldPosition(NumberFormat.INTEGER_FIELD);
+        NumberFormat.getInstance().format(num, buf, fp);
+        assertEquals("1,234", buf.toString());
+        assertEquals(0, fp.getBeginIndex());
+        assertEquals(5, fp.getEndIndex());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.parseObject(String, ParsePosition)'
+     */
+    public void testParseObjectStringParsePosition() {
+        ParsePosition pp = new ParsePosition(0);
+        Object result = NumberFormat.getInstance().parse("1,234", pp);
+        assertEquals(result, new Long(1234));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.format(double)'
+     */
+    public void testFormatDouble() {
+        assertEquals("1,234.567", NumberFormat.getInstance().format(1234.567));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.format(long)'
+     */
+    public void testFormatLong() {
+        assertEquals("1,234", NumberFormat.getInstance().format(1234L));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.format(BigInteger)'
+     */
+    public void testFormatBigInteger() {
+        // note, java doesn't handle biginteger with full precision.
+        BigInteger bi = new BigInteger("123456");
+        assertEquals("123,456", java.text.NumberFormat.getInstance().format(bi));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.format(double, StringBuffer, FieldPosition)'
+     */
+    public void testFormatDoubleStringBufferFieldPosition() {
+        StringBuffer buf = new StringBuffer();
+        FieldPosition fp = new FieldPosition(NumberFormat.FRACTION_FIELD);
+        assertEquals("123,456.789", NumberFormat.getInstance().format(123456.789, buf, fp).toString());
+        assertEquals(8, fp.getBeginIndex());
+        assertEquals(11, fp.getEndIndex());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.format(long, StringBuffer, FieldPosition)'
+     */
+    public void testFormatLongStringBufferFieldPosition() {
+        StringBuffer buf = new StringBuffer();
+        FieldPosition fp = new FieldPosition(NumberFormat.Field.GROUPING_SEPARATOR);
+        assertEquals("123,456", NumberFormat.getInstance().format(123456L, buf, fp).toString());
+        assertEquals(3, fp.getBeginIndex());
+        assertEquals(4, fp.getEndIndex());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.format(BigInteger, StringBuffer, FieldPosition)'
+     */
+    public void testFormatBigIntegerStringBufferFieldPosition() {
+        // note, java doesn't handle biginteger with full precision.
+        StringBuffer buf = new StringBuffer();
+        FieldPosition fp = new FieldPosition(0);
+        BigInteger bi = new BigInteger("123456");
+        assertEquals("123,456", java.text.NumberFormat.getInstance().format(bi, buf, fp).toString());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.parse(String, ParsePosition)'
+     */
+    public void testParseStringParsePosition() {
+        ParsePosition pp = new ParsePosition(3);
+        assertEquals(new Long(123456), NumberFormat.getInstance().parse("xxx123,456yyy", pp));
+        assertEquals(10, pp.getIndex());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.parse(String)'
+     */
+    public void testParseString() throws ParseException {
+        Number result = NumberFormat.getInstance().parse("123,456,yyy");
+        assertEquals(new Long(123456), result);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.isParseIntegerOnly()'
+     */
+    public void testIsParseIntegerOnly() {
+        NumberFormat nf = NumberFormat.getInstance();
+        nf.setParseIntegerOnly(true);
+        assertTrue(nf.isParseIntegerOnly());
+        nf.setParseIntegerOnly(false);
+        assertFalse(nf.isParseIntegerOnly());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.setParseIntegerOnly(boolean)'
+     */
+    public void testSetParseIntegerOnly() throws ParseException {
+        String str = "123.456,yyy";
+        NumberFormat nf = NumberFormat.getInstance();
+        assertEquals(new Double(123.456), nf.parse(str));
+        nf.setParseIntegerOnly(true);
+        assertEquals(new Long(123), nf.parse(str));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.getInstance()'
+     */
+    public void testGetInstance() {
+        // used everywhere, no need to test
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.getInstance(Locale)'
+     */
+    public void testGetInstanceLocale() {
+        NumberFormat nf = NumberFormat.getInstance(Locale.GERMANY);
+        assertEquals("123,456", nf.format(123.456));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.getInstance(ULocale)'
+     */
+    public void testGetInstanceULocale() {
+        NumberFormat nf = NumberFormat.getInstance(ULocale.GERMANY);
+        assertEquals("123,456", nf.format(123.456));            
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.getNumberInstance()'
+     */
+    public void testGetNumberInstance() {
+        NumberFormat nf = NumberFormat.getNumberInstance();
+        assertEquals("123,456.789", nf.format(123456.789));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.getNumberInstance(Locale)'
+     */
+    public void testGetNumberInstanceLocale() {
+        NumberFormat nf = NumberFormat.getNumberInstance(Locale.GERMANY);
+        assertEquals("123.456,789", nf.format(123456.789));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.getNumberInstance(ULocale)'
+     */
+    public void testGetNumberInstanceULocale() {
+        NumberFormat nf = NumberFormat.getNumberInstance(ULocale.GERMANY);
+        assertEquals("123.456,789", nf.format(123456.789));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.getIntegerInstance()'
+     */
+    public void testGetIntegerInstance() {
+        NumberFormat nf = NumberFormat.getIntegerInstance();
+        assertEquals("123,457", nf.format(123456.789)); // rounds
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.getIntegerInstance(Locale)'
+     */
+    public void testGetIntegerInstanceLocale() {
+        NumberFormat nf = NumberFormat.getIntegerInstance(Locale.GERMANY);
+        assertEquals("123.457", nf.format(123456.789)); // rounds
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.getIntegerInstance(ULocale)'
+     */
+    public void testGetIntegerInstanceULocale() {
+        NumberFormat nf = NumberFormat.getIntegerInstance(ULocale.GERMANY);
+        assertEquals("123.457", nf.format(123456.789)); // rounds
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.getCurrencyInstance()'
+     */
+    public void testGetCurrencyInstance() {
+        NumberFormat nf = NumberFormat.getCurrencyInstance();
+        assertEquals("$123,456.99", nf.format(123456.99));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.getCurrencyInstance(Locale)'
+     */
+    public void testGetCurrencyInstanceLocale() {
+        NumberFormat nf = NumberFormat.getCurrencyInstance(Locale.GERMANY);
+        assertEquals("123.456,99 \u20AC", nf.format(123456.99));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.getCurrencyInstance(ULocale)'
+     */
+    public void testGetCurrencyInstanceULocale() {
+        NumberFormat nf = NumberFormat.getCurrencyInstance(ULocale.GERMANY);
+        assertEquals("123.456,99 \u20AC", nf.format(123456.99));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.getPercentInstance()'
+     */
+    public void testGetPercentInstance() {
+        NumberFormat nf = NumberFormat.getPercentInstance();
+        assertEquals("123,456%", nf.format(1234.56));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.getPercentInstance(Locale)'
+     */
+    public void testGetPercentInstanceLocale() {
+        NumberFormat nf = NumberFormat.getPercentInstance(Locale.GERMANY);
+        assertEquals("123.456%", nf.format(1234.56));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.getPercentInstance(ULocale)'
+     */
+    public void testGetPercentInstanceULocale() {
+        NumberFormat nf = NumberFormat.getPercentInstance(ULocale.GERMANY);
+        assertEquals("123.456%", nf.format(1234.56));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.getScientificInstance()'
+     */
+    public void testGetScientificInstance() {
+        NumberFormat nf = NumberFormat.getScientificInstance();
+        assertEquals(".123456E4", nf.format(1234.56));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.getScientificInstance(Locale)'
+     */
+    public void testGetScientificInstanceLocale() {
+        NumberFormat nf = NumberFormat.getScientificInstance(Locale.GERMANY);
+        assertEquals(",123456E4", nf.format(1234.56));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.getScientificInstance(ULocale)'
+     */
+    public void testGetScientificInstanceULocale() {
+        NumberFormat nf = NumberFormat.getScientificInstance(ULocale.GERMANY);
+        assertEquals(",123456E4", nf.format(1234.56));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.getAvailableLocales()'
+     */
+    public void testGetAvailableLocales() {
+        Locale[] ilocales = NumberFormat.getAvailableLocales();
+        if (ICUTestCase.testingWrapper) {
+            Locale[] jlocales = java.text.NumberFormat.getAvailableLocales();
+            for (int i = 0; i < ilocales.length; ++i) {
+                assertEquals(jlocales[i], ilocales[i]);
+            }
+        }
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.getAvailableULocales()'
+     */
+    public void testGetAvailableULocales() {
+        ULocale[] ulocales = NumberFormat.getAvailableULocales();
+        if (ICUTestCase.testingWrapper) {
+            Locale[] jlocales = java.text.NumberFormat.getAvailableLocales();
+            for (int i = 0; i < ulocales.length; ++i) {
+                assertEquals(jlocales[i], ulocales[i].toLocale());
+            }
+        }
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.isGroupingUsed()'
+     */
+    public void testIsGroupingUsed() {
+        NumberFormat nf = NumberFormat.getInstance();
+        nf.setGroupingUsed(true);
+        assertTrue(nf.isGroupingUsed());
+        nf.setGroupingUsed(false);
+        assertFalse(nf.isGroupingUsed());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.setGroupingUsed(boolean)'
+     */
+    public void testSetGroupingUsed() {
+        NumberFormat nf = NumberFormat.getInstance();
+        assertEquals("123,456,789", nf.format(123456789));
+        nf.setGroupingUsed(false);
+        assertEquals("123456789", nf.format(123456789));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.getMaximumIntegerDigits()'
+     */
+    public void testGetMaximumIntegerDigits() {
+        NumberFormat nf = NumberFormat.getInstance();
+        nf.setMaximumIntegerDigits(4);
+        assertEquals(4, nf.getMaximumIntegerDigits());
+        nf.setMaximumIntegerDigits(6);
+        assertEquals(6, nf.getMaximumIntegerDigits());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.setMaximumIntegerDigits(int)'
+     */
+    public void testSetMaximumIntegerDigits() {
+        NumberFormat nf = NumberFormat.getInstance();
+        nf.setMaximumIntegerDigits(4);
+        assertEquals("3,456", nf.format(123456)); // high digits truncated
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.getMinimumIntegerDigits()'
+     */
+    public void testGetMinimumIntegerDigits() {
+        NumberFormat nf = NumberFormat.getInstance();
+        nf.setMinimumIntegerDigits(4);
+        assertEquals(4, nf.getMinimumIntegerDigits());
+        nf.setMinimumIntegerDigits(6);
+        assertEquals(6, nf.getMinimumIntegerDigits());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.setMinimumIntegerDigits(int)'
+     */
+    public void testSetMinimumIntegerDigits() {
+        NumberFormat nf = NumberFormat.getInstance();
+        nf.setMinimumIntegerDigits(4);
+        assertEquals("0,012", nf.format(12)); // pad out with zero, grouping still used
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.getMaximumFractionDigits()'
+     */
+    public void testGetMaximumFractionDigits() {
+        NumberFormat nf = NumberFormat.getInstance();
+        nf.setMaximumFractionDigits(4);
+        assertEquals(4, nf.getMaximumFractionDigits());
+        nf.setMaximumFractionDigits(6);
+        assertEquals(6, nf.getMaximumFractionDigits());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.setMaximumFractionDigits(int)'
+     */
+    public void testSetMaximumFractionDigits() {
+        NumberFormat nf = NumberFormat.getInstance();
+        nf.setMaximumFractionDigits(4);
+        assertEquals("1.2346", nf.format(1.2345678)); // low digits rounded
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.getMinimumFractionDigits()'
+     */
+    public void testGetMinimumFractionDigits() {
+        NumberFormat nf = NumberFormat.getInstance();
+        nf.setMinimumFractionDigits(4);
+        assertEquals(4, nf.getMinimumFractionDigits());
+        nf.setMinimumFractionDigits(6);
+        assertEquals(6, nf.getMinimumFractionDigits());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.setMinimumFractionDigits(int)'
+     */
+    public void testSetMinimumFractionDigits() {
+        NumberFormat nf = NumberFormat.getInstance();
+        nf.setMinimumFractionDigits(4);
+        assertEquals("1.2000", nf.format(1.2));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.toString()'
+     */
+    public void testToString() {
+        assertNotNull(NumberFormat.getInstance().toString());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.hashCode()'
+     */
+    public void testHashCode() {
+        NumberFormat nf = NumberFormat.getInstance();
+        NumberFormat eq = NumberFormat.getInstance(Locale.US);
+        NumberFormat neq = NumberFormat.getInstance(Locale.GERMANY);
+                
+        ICUTestCase.testEHCS(nf, eq, neq);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.clone()'
+     */
+    public void testClone() {
+        // see testHashCode
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.text.NumberFormat.equals(Object)'
+     */
+    public void testEqualsObject() {
+        // see testHashCode
+    }
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/SimpleDateFormatTest.java b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/SimpleDateFormatTest.java
index 2bf3623..0136a82 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/SimpleDateFormatTest.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/SimpleDateFormatTest.java
@@ -1,202 +1,202 @@
-/*
- *******************************************************************************
- * Copyright (C) 2006-2011, International Business Machines Corporation and    *
- * others. All Rights Reserved.                                                *
- *******************************************************************************
- */
-
-package com.ibm.icu.tests;
-
-import java.text.FieldPosition;
-import java.text.ParseException;
-import java.text.ParsePosition;
-import java.util.Date;
-import java.util.Locale;
-
-import com.ibm.icu.text.DateFormatSymbols;
-import com.ibm.icu.text.SimpleDateFormat;
-import com.ibm.icu.util.Calendar;
-import com.ibm.icu.util.TimeZone;
-import com.ibm.icu.util.ULocale;
-
-public class SimpleDateFormatTest extends ICUTestCase {
-    private static final String mdy = "MMM dd yyyy";
-    private static final String md2 = "MMM dd yy";
-    private static final String hmz = "'The time is' HH:mm:ss zzz";
-    private static final String hmzmdy = hmz + " 'on' " + mdy;
-    private static final String hmzmdyStr = "The time is 15:05:20 CST on Jan 10 2006";
-        
-    private static final TimeZone tzc = TimeZone.getTimeZone("CST");
-    private static final TimeZone tzp = TimeZone.getTimeZone("PST");
-    private static final Calendar cal = Calendar.getInstance(tzc);
-    private static final Date date;
-    static {
-        cal.clear();
-        cal.set(2006, 0, 10, 15, 5, 20); // arrgh, doesn't clear millis
-        date = cal.getTime();
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.SimpleDateFormat.format(Calendar, StringBuffer, FieldPosition)'
-     */
-    public void testFormatCalendarStringBufferFieldPosition() {
-        StringBuffer buf = new StringBuffer();
-        FieldPosition fp = new FieldPosition(0);
-        SimpleDateFormat sdf = new SimpleDateFormat(hmzmdy);
-        sdf.format(cal, buf, fp);
-        assertEquals(hmzmdyStr, buf.toString());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.SimpleDateFormat.parse(String, Calendar, ParsePosition)'
-     */
-    public void testParseStringCalendarParsePosition() {
-        Calendar cal = Calendar.getInstance(tzp);
-        cal.clear();
-        ParsePosition pp = new ParsePosition(0);
-        SimpleDateFormat sdf = new SimpleDateFormat(hmzmdy);
-        sdf.parse(hmzmdyStr, cal, pp);
-        assertEquals(date, cal.getTime());
-        // note: java doesn't return the parsed time zone
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.SimpleDateFormat.clone()'
-     */
-    public void testClone() {
-
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.SimpleDateFormat.SimpleDateFormat()'
-     */
-    public void testSimpleDateFormat() {
-        SimpleDateFormat sdf = new SimpleDateFormat();
-        java.text.SimpleDateFormat jsdf = new java.text.SimpleDateFormat();
-        assertEquals(jsdf.format(date), sdf.format(date));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.SimpleDateFormat.SimpleDateFormat(String)'
-     */
-    public void testSimpleDateFormatString() {
-        SimpleDateFormat sdf = new SimpleDateFormat(mdy);
-        java.text.SimpleDateFormat jsdf = new java.text.SimpleDateFormat(mdy);
-        assertEquals(jsdf.format(date), sdf.format(date));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.SimpleDateFormat.SimpleDateFormat(String, Locale)'
-     */
-    public void testSimpleDateFormatStringLocale() {
-        Locale l = Locale.JAPAN;
-        SimpleDateFormat sdf = new SimpleDateFormat(mdy, l);
-        java.text.SimpleDateFormat jsdf = new java.text.SimpleDateFormat(mdy, l);
-        assertEquals(jsdf.format(date), sdf.format(date));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.SimpleDateFormat.SimpleDateFormat(String, ULocale)'
-     */
-    public void testSimpleDateFormatStringULocale() {
-        ULocale l = ULocale.JAPAN;
-        SimpleDateFormat sdf = new SimpleDateFormat(mdy, l);
-        java.text.SimpleDateFormat jsdf = new java.text.SimpleDateFormat(mdy, l.toLocale());
-        assertEquals(jsdf.format(date), sdf.format(date));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.SimpleDateFormat.SimpleDateFormat(String, DateFormatSymbols)'
-     */
-    public void testSimpleDateFormatStringDateFormatSymbols() {
-        Locale l = Locale.US;
-        DateFormatSymbols dfs = new DateFormatSymbols(l);
-        java.text.DateFormatSymbols jdfs = new java.text.DateFormatSymbols(l);
-        SimpleDateFormat sdf = new SimpleDateFormat(mdy, dfs);
-        java.text.SimpleDateFormat jsdf = new java.text.SimpleDateFormat(mdy, jdfs);
-        assertEquals(jsdf.format(date), sdf.format(date));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.SimpleDateFormat.set2DigitYearStart(Date)'
-     */
-    public void testSet2DigitYearStart() {
-        SimpleDateFormat sdf = new SimpleDateFormat(md2);
-        sdf.set2DigitYearStart(date);
-        try {
-            Date d = sdf.parse("Jan 15 04");
-            assertNotEqual(-1, d.toString().indexOf("2104"));
-        }
-        catch (ParseException pe) {
-            fail(pe.getMessage());
-        }
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.SimpleDateFormat.get2DigitYearStart()'
-     */
-    public void testGet2DigitYearStart() {
-        SimpleDateFormat sdf = new SimpleDateFormat(md2);
-        sdf.set2DigitYearStart(date);
-        assertEquals(date, sdf.get2DigitYearStart());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.SimpleDateFormat.toPattern()'
-     */
-    public void testToPattern() {
-        SimpleDateFormat sdf = new SimpleDateFormat(mdy);
-        assertEquals(mdy, sdf.toPattern());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.SimpleDateFormat.toLocalizedPattern()'
-     */
-    public void testToLocalizedPattern() {
-        Locale l = Locale.getDefault();
-        Locale.setDefault(Locale.US);
-        SimpleDateFormat sdf = new SimpleDateFormat(mdy);
-        assertEquals(mdy, sdf.toLocalizedPattern());
-        Locale.setDefault(l);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.SimpleDateFormat.applyPattern(String)'
-     */
-    public void testApplyPattern() {
-        SimpleDateFormat sdf = new SimpleDateFormat();
-        sdf.setTimeZone(tzc);
-        sdf.applyPattern(hmzmdy);
-        assertEquals(hmzmdyStr, sdf.format(date));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.SimpleDateFormat.applyLocalizedPattern(String)'
-     */
-    public void testApplyLocalizedPattern() {
-        SimpleDateFormat sdf = new SimpleDateFormat();
-        sdf.setTimeZone(tzc);
-        sdf.applyLocalizedPattern(hmzmdy);
-        assertEquals(hmzmdyStr, sdf.format(date));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.SimpleDateFormat.getDateFormatSymbols()'
-     */
-    public void testGetDateFormatSymbols() {
-        DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
-        SimpleDateFormat sdf = new SimpleDateFormat(mdy, dfs);
-        assertEquals(dfs, sdf.getDateFormatSymbols());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.text.SimpleDateFormat.setDateFormatSymbols(DateFormatSymbols)'
-     */
-    public void testSetDateFormatSymbols() {
-        DateFormatSymbols dfs = new DateFormatSymbols(Locale.JAPAN);
-        SimpleDateFormat sdf = new SimpleDateFormat(hmzmdy);
-        sdf.setDateFormatSymbols(dfs);
-        // assumes Japanese symbols do not have gregorian month names
-        assertEquals(-1, sdf.format(date).indexOf("Jan"));
-    }
-}
+/*
+ *******************************************************************************
+ * Copyright (C) 2006-2011, International Business Machines Corporation and    *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+
+package com.ibm.icu.tests;
+
+import java.text.FieldPosition;
+import java.text.ParseException;
+import java.text.ParsePosition;
+import java.util.Date;
+import java.util.Locale;
+
+import com.ibm.icu.text.DateFormatSymbols;
+import com.ibm.icu.text.SimpleDateFormat;
+import com.ibm.icu.util.Calendar;
+import com.ibm.icu.util.TimeZone;
+import com.ibm.icu.util.ULocale;
+
+public class SimpleDateFormatTest extends ICUTestCase {
+    private static final String mdy = "MMM dd yyyy";
+    private static final String md2 = "MMM dd yy";
+    private static final String hmz = "'The time is' HH:mm:ss zzz";
+    private static final String hmzmdy = hmz + " 'on' " + mdy;
+    private static final String hmzmdyStr = "The time is 15:05:20 CST on Jan 10 2006";
+        
+    private static final TimeZone tzc = TimeZone.getTimeZone("CST");
+    private static final TimeZone tzp = TimeZone.getTimeZone("PST");
+    private static final Calendar cal = Calendar.getInstance(tzc);
+    private static final Date date;
+    static {
+        cal.clear();
+        cal.set(2006, 0, 10, 15, 5, 20); // arrgh, doesn't clear millis
+        date = cal.getTime();
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.SimpleDateFormat.format(Calendar, StringBuffer, FieldPosition)'
+     */
+    public void testFormatCalendarStringBufferFieldPosition() {
+        StringBuffer buf = new StringBuffer();
+        FieldPosition fp = new FieldPosition(0);
+        SimpleDateFormat sdf = new SimpleDateFormat(hmzmdy);
+        sdf.format(cal, buf, fp);
+        assertEquals(hmzmdyStr, buf.toString());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.SimpleDateFormat.parse(String, Calendar, ParsePosition)'
+     */
+    public void testParseStringCalendarParsePosition() {
+        Calendar cal = Calendar.getInstance(tzp);
+        cal.clear();
+        ParsePosition pp = new ParsePosition(0);
+        SimpleDateFormat sdf = new SimpleDateFormat(hmzmdy);
+        sdf.parse(hmzmdyStr, cal, pp);
+        assertEquals(date, cal.getTime());
+        // note: java doesn't return the parsed time zone
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.SimpleDateFormat.clone()'
+     */
+    public void testClone() {
+
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.SimpleDateFormat.SimpleDateFormat()'
+     */
+    public void testSimpleDateFormat() {
+        SimpleDateFormat sdf = new SimpleDateFormat();
+        java.text.SimpleDateFormat jsdf = new java.text.SimpleDateFormat();
+        assertEquals(jsdf.format(date), sdf.format(date));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.SimpleDateFormat.SimpleDateFormat(String)'
+     */
+    public void testSimpleDateFormatString() {
+        SimpleDateFormat sdf = new SimpleDateFormat(mdy);
+        java.text.SimpleDateFormat jsdf = new java.text.SimpleDateFormat(mdy);
+        assertEquals(jsdf.format(date), sdf.format(date));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.SimpleDateFormat.SimpleDateFormat(String, Locale)'
+     */
+    public void testSimpleDateFormatStringLocale() {
+        Locale l = Locale.JAPAN;
+        SimpleDateFormat sdf = new SimpleDateFormat(mdy, l);
+        java.text.SimpleDateFormat jsdf = new java.text.SimpleDateFormat(mdy, l);
+        assertEquals(jsdf.format(date), sdf.format(date));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.SimpleDateFormat.SimpleDateFormat(String, ULocale)'
+     */
+    public void testSimpleDateFormatStringULocale() {
+        ULocale l = ULocale.JAPAN;
+        SimpleDateFormat sdf = new SimpleDateFormat(mdy, l);
+        java.text.SimpleDateFormat jsdf = new java.text.SimpleDateFormat(mdy, l.toLocale());
+        assertEquals(jsdf.format(date), sdf.format(date));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.SimpleDateFormat.SimpleDateFormat(String, DateFormatSymbols)'
+     */
+    public void testSimpleDateFormatStringDateFormatSymbols() {
+        Locale l = Locale.US;
+        DateFormatSymbols dfs = new DateFormatSymbols(l);
+        java.text.DateFormatSymbols jdfs = new java.text.DateFormatSymbols(l);
+        SimpleDateFormat sdf = new SimpleDateFormat(mdy, dfs);
+        java.text.SimpleDateFormat jsdf = new java.text.SimpleDateFormat(mdy, jdfs);
+        assertEquals(jsdf.format(date), sdf.format(date));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.SimpleDateFormat.set2DigitYearStart(Date)'
+     */
+    public void testSet2DigitYearStart() {
+        SimpleDateFormat sdf = new SimpleDateFormat(md2);
+        sdf.set2DigitYearStart(date);
+        try {
+            Date d = sdf.parse("Jan 15 04");
+            assertNotEqual(-1, d.toString().indexOf("2104"));
+        }
+        catch (ParseException pe) {
+            fail(pe.getMessage());
+        }
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.SimpleDateFormat.get2DigitYearStart()'
+     */
+    public void testGet2DigitYearStart() {
+        SimpleDateFormat sdf = new SimpleDateFormat(md2);
+        sdf.set2DigitYearStart(date);
+        assertEquals(date, sdf.get2DigitYearStart());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.SimpleDateFormat.toPattern()'
+     */
+    public void testToPattern() {
+        SimpleDateFormat sdf = new SimpleDateFormat(mdy);
+        assertEquals(mdy, sdf.toPattern());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.SimpleDateFormat.toLocalizedPattern()'
+     */
+    public void testToLocalizedPattern() {
+        Locale l = Locale.getDefault();
+        Locale.setDefault(Locale.US);
+        SimpleDateFormat sdf = new SimpleDateFormat(mdy);
+        assertEquals(mdy, sdf.toLocalizedPattern());
+        Locale.setDefault(l);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.SimpleDateFormat.applyPattern(String)'
+     */
+    public void testApplyPattern() {
+        SimpleDateFormat sdf = new SimpleDateFormat();
+        sdf.setTimeZone(tzc);
+        sdf.applyPattern(hmzmdy);
+        assertEquals(hmzmdyStr, sdf.format(date));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.SimpleDateFormat.applyLocalizedPattern(String)'
+     */
+    public void testApplyLocalizedPattern() {
+        SimpleDateFormat sdf = new SimpleDateFormat();
+        sdf.setTimeZone(tzc);
+        sdf.applyLocalizedPattern(hmzmdy);
+        assertEquals(hmzmdyStr, sdf.format(date));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.SimpleDateFormat.getDateFormatSymbols()'
+     */
+    public void testGetDateFormatSymbols() {
+        DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
+        SimpleDateFormat sdf = new SimpleDateFormat(mdy, dfs);
+        assertEquals(dfs, sdf.getDateFormatSymbols());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.text.SimpleDateFormat.setDateFormatSymbols(DateFormatSymbols)'
+     */
+    public void testSetDateFormatSymbols() {
+        DateFormatSymbols dfs = new DateFormatSymbols(Locale.JAPAN);
+        SimpleDateFormat sdf = new SimpleDateFormat(hmzmdy);
+        sdf.setDateFormatSymbols(dfs);
+        // assumes Japanese symbols do not have gregorian month names
+        assertEquals(-1, sdf.format(date).indexOf("Jan"));
+    }
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/TimeZoneTest.java b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/TimeZoneTest.java
index d85d0a2..f8a2fe1 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/TimeZoneTest.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/TimeZoneTest.java
@@ -1,235 +1,235 @@
-/*
- *******************************************************************************
- * Copyright (C) 2006-2011, International Business Machines Corporation and    *
- * others. All Rights Reserved.                                                *
- *******************************************************************************
- */
-
-package com.ibm.icu.tests;
-
-import java.util.Date;
-import java.util.Locale;
-
-import com.ibm.icu.util.Calendar;
-import com.ibm.icu.util.TimeZone;
-import com.ibm.icu.util.ULocale;
-
-public class TimeZoneTest extends ICUTestCase {
-
-    /*
-     * Test method for 'com.ibm.icu.util.TimeZone.hashCode()'
-     */
-    public void testHashCode() {
-        TimeZone tz1 = TimeZone.getTimeZone("PST");
-        TimeZone tz2 = TimeZone.getTimeZone("PST");
-        TimeZone tzn = TimeZone.getTimeZone("CST");
-        testEHCS(tz1, tz2, tzn);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.TimeZone.TimeZone(TimeZone)'
-     */
-    public void testTimeZone() {
-        // implicitly tested everywhere
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.TimeZone.getOffset(int, int, int, int, int, int)'
-     */
-    public void testGetOffset() {
-        TimeZone tz = TimeZone.getTimeZone("PST");
-        int offset = tz.getOffset(1, 2004, 0, 01, 1, 0);
-        assertEquals(-28800000, offset);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.TimeZone.setRawOffset(int)'
-     */
-    public void testSetRawOffset() {
-        TimeZone tz = TimeZone.getTimeZone("PST");
-        int value = tz.getRawOffset();
-        int value1 = value + 100000;
-        tz.setRawOffset(value1);
-        int result = tz.getRawOffset();
-        assertNotEqual(value, result);
-        assertEquals(value1, result);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.TimeZone.getRawOffset()'
-     */
-    public void testGetRawOffset() {
-        TimeZone tz = TimeZone.getTimeZone("PST");
-        int offset = tz.getRawOffset();
-        assertEquals(-28800000, offset);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.TimeZone.getID()'
-     */
-    public void testGetID() {
-        TimeZone tz = TimeZone.getTimeZone("PST");
-        assertEquals("PST", tz.getID());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.TimeZone.setID(String)'
-     */
-    public void testSetID() {
-        TimeZone tz = TimeZone.getTimeZone("PST");
-        String value1 = tz.getID();
-        String value2 = value1 + "!";
-        tz.setID(value2);
-        String result = tz.getID();
-        assertNotEqual(value1, result);
-        assertEquals(value2, result);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.TimeZone.getDisplayName()'
-     */
-    public void testGetDisplayName() {
-        TimeZone tz = TimeZone.getTimeZone("PST");
-        assertEquals("Pacific Standard Time", tz.getDisplayName());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.TimeZone.getDisplayName(Locale)'
-     */
-    public void testGetDisplayNameLocale() {
-        TimeZone tz = TimeZone.getTimeZone("PST");
-        assertEquals("Pacific Standard Time", tz.getDisplayName(Locale.US));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.TimeZone.getDisplayName(ULocale)'
-     */
-    public void testGetDisplayNameULocale() {
-        TimeZone tz = TimeZone.getTimeZone("PST");
-        assertEquals("Pacific Standard Time", tz.getDisplayName(ULocale.US));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.TimeZone.getDisplayName(boolean, int)'
-     */
-    public void testGetDisplayNameBooleanInt() {
-        TimeZone tz = TimeZone.getTimeZone("PST");
-        assertEquals("PDT", tz.getDisplayName(true, TimeZone.SHORT));
-        assertEquals("Pacific Daylight Time", tz.getDisplayName(true, TimeZone.LONG));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.TimeZone.getDisplayName(boolean, int, Locale)'
-     */
-    public void testGetDisplayNameBooleanIntLocale() {
-        TimeZone tz = TimeZone.getTimeZone("PST");
-        assertEquals("PDT", tz.getDisplayName(true, TimeZone.SHORT, Locale.US));
-        assertEquals("Pacific Daylight Time", tz.getDisplayName(true, TimeZone.LONG, Locale.US));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.TimeZone.getDisplayName(boolean, int, ULocale)'
-     */
-    public void testGetDisplayNameBooleanIntULocale() {
-        TimeZone tz = TimeZone.getTimeZone("PST");
-        assertEquals("PDT", tz.getDisplayName(true, TimeZone.SHORT, ULocale.US));
-        assertEquals("Pacific Daylight Time", tz.getDisplayName(true, TimeZone.LONG, ULocale.US));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.TimeZone.getDSTSavings()'
-     */
-    public void testGetDSTSavings() {
-        TimeZone tz = TimeZone.getTimeZone("PST");
-        assertEquals(3600000, tz.getDSTSavings());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.TimeZone.useDaylightTime()'
-     */
-    public void testUseDaylightTime() {
-        TimeZone tz = TimeZone.getTimeZone("PST");
-        assertTrue(tz.useDaylightTime());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.TimeZone.inDaylightTime(Date)'
-     */
-    public void testInDaylightTime() {
-        TimeZone tz = TimeZone.getTimeZone("PST");
-        Calendar cal = Calendar.getInstance();
-        cal.set(2005, 0, 17);
-        Date date = cal.getTime();
-        assertFalse(tz.inDaylightTime(date));
-        cal.set(2005, 6, 17);
-        date = cal.getTime();
-        assertTrue(tz.inDaylightTime(date));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.TimeZone.getTimeZone(String)'
-     */
-    public void testGetTimeZone() {
-        // implicitly tested everywhere
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.TimeZone.getAvailableIDs(int)'
-     */
-    public void testGetAvailableIDsInt() {
-        String[] ids = TimeZone.getAvailableIDs(-28800000);
-        assertNotNull(ids);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.TimeZone.getAvailableIDs()'
-     */
-    public void testGetAvailableIDs() {
-        String[] ids = TimeZone.getAvailableIDs();
-        assertNotNull(ids);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.TimeZone.getDefault()'
-     */
-    public void testGetDefault() {
-        TimeZone tz = TimeZone.getDefault();
-        assertNotNull(tz);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.TimeZone.setDefault(TimeZone)'
-     */
-    public void testSetDefault() {
-        TimeZone tz1 = TimeZone.getDefault();
-        String newCode = "PDT".equals(tz1.getID()) ? "CST" : "PDT";
-        TimeZone tz2 = TimeZone.getTimeZone(newCode);
-        TimeZone.setDefault(tz2);
-        TimeZone result = TimeZone.getDefault();
-        assertNotEqual(tz1, result);
-        assertEquals(tz2, result);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.TimeZone.hasSameRules(TimeZone)'
-     */
-    public void testHasSameRules() {
-        TimeZone tz1 = TimeZone.getTimeZone("PST");
-        TimeZone tz2 = TimeZone.getTimeZone("America/Los_Angeles");
-        assertTrue(tz1.hasSameRules(tz2));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.TimeZone.clone()'
-     */
-    public void testClone() {
-        // tested by testHashCode
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.util.TimeZone.equals(Object)'
-     */
-    public void testEqualsObject() {
-        // tested by testHashCode
-    }
-}
+/*
+ *******************************************************************************
+ * Copyright (C) 2006-2011, International Business Machines Corporation and    *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+
+package com.ibm.icu.tests;
+
+import java.util.Date;
+import java.util.Locale;
+
+import com.ibm.icu.util.Calendar;
+import com.ibm.icu.util.TimeZone;
+import com.ibm.icu.util.ULocale;
+
+public class TimeZoneTest extends ICUTestCase {
+
+    /*
+     * Test method for 'com.ibm.icu.util.TimeZone.hashCode()'
+     */
+    public void testHashCode() {
+        TimeZone tz1 = TimeZone.getTimeZone("PST");
+        TimeZone tz2 = TimeZone.getTimeZone("PST");
+        TimeZone tzn = TimeZone.getTimeZone("CST");
+        testEHCS(tz1, tz2, tzn);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.TimeZone.TimeZone(TimeZone)'
+     */
+    public void testTimeZone() {
+        // implicitly tested everywhere
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.TimeZone.getOffset(int, int, int, int, int, int)'
+     */
+    public void testGetOffset() {
+        TimeZone tz = TimeZone.getTimeZone("PST");
+        int offset = tz.getOffset(1, 2004, 0, 01, 1, 0);
+        assertEquals(-28800000, offset);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.TimeZone.setRawOffset(int)'
+     */
+    public void testSetRawOffset() {
+        TimeZone tz = TimeZone.getTimeZone("PST");
+        int value = tz.getRawOffset();
+        int value1 = value + 100000;
+        tz.setRawOffset(value1);
+        int result = tz.getRawOffset();
+        assertNotEqual(value, result);
+        assertEquals(value1, result);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.TimeZone.getRawOffset()'
+     */
+    public void testGetRawOffset() {
+        TimeZone tz = TimeZone.getTimeZone("PST");
+        int offset = tz.getRawOffset();
+        assertEquals(-28800000, offset);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.TimeZone.getID()'
+     */
+    public void testGetID() {
+        TimeZone tz = TimeZone.getTimeZone("PST");
+        assertEquals("PST", tz.getID());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.TimeZone.setID(String)'
+     */
+    public void testSetID() {
+        TimeZone tz = TimeZone.getTimeZone("PST");
+        String value1 = tz.getID();
+        String value2 = value1 + "!";
+        tz.setID(value2);
+        String result = tz.getID();
+        assertNotEqual(value1, result);
+        assertEquals(value2, result);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.TimeZone.getDisplayName()'
+     */
+    public void testGetDisplayName() {
+        TimeZone tz = TimeZone.getTimeZone("PST");
+        assertEquals("Pacific Standard Time", tz.getDisplayName());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.TimeZone.getDisplayName(Locale)'
+     */
+    public void testGetDisplayNameLocale() {
+        TimeZone tz = TimeZone.getTimeZone("PST");
+        assertEquals("Pacific Standard Time", tz.getDisplayName(Locale.US));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.TimeZone.getDisplayName(ULocale)'
+     */
+    public void testGetDisplayNameULocale() {
+        TimeZone tz = TimeZone.getTimeZone("PST");
+        assertEquals("Pacific Standard Time", tz.getDisplayName(ULocale.US));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.TimeZone.getDisplayName(boolean, int)'
+     */
+    public void testGetDisplayNameBooleanInt() {
+        TimeZone tz = TimeZone.getTimeZone("PST");
+        assertEquals("PDT", tz.getDisplayName(true, TimeZone.SHORT));
+        assertEquals("Pacific Daylight Time", tz.getDisplayName(true, TimeZone.LONG));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.TimeZone.getDisplayName(boolean, int, Locale)'
+     */
+    public void testGetDisplayNameBooleanIntLocale() {
+        TimeZone tz = TimeZone.getTimeZone("PST");
+        assertEquals("PDT", tz.getDisplayName(true, TimeZone.SHORT, Locale.US));
+        assertEquals("Pacific Daylight Time", tz.getDisplayName(true, TimeZone.LONG, Locale.US));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.TimeZone.getDisplayName(boolean, int, ULocale)'
+     */
+    public void testGetDisplayNameBooleanIntULocale() {
+        TimeZone tz = TimeZone.getTimeZone("PST");
+        assertEquals("PDT", tz.getDisplayName(true, TimeZone.SHORT, ULocale.US));
+        assertEquals("Pacific Daylight Time", tz.getDisplayName(true, TimeZone.LONG, ULocale.US));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.TimeZone.getDSTSavings()'
+     */
+    public void testGetDSTSavings() {
+        TimeZone tz = TimeZone.getTimeZone("PST");
+        assertEquals(3600000, tz.getDSTSavings());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.TimeZone.useDaylightTime()'
+     */
+    public void testUseDaylightTime() {
+        TimeZone tz = TimeZone.getTimeZone("PST");
+        assertTrue(tz.useDaylightTime());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.TimeZone.inDaylightTime(Date)'
+     */
+    public void testInDaylightTime() {
+        TimeZone tz = TimeZone.getTimeZone("PST");
+        Calendar cal = Calendar.getInstance();
+        cal.set(2005, 0, 17);
+        Date date = cal.getTime();
+        assertFalse(tz.inDaylightTime(date));
+        cal.set(2005, 6, 17);
+        date = cal.getTime();
+        assertTrue(tz.inDaylightTime(date));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.TimeZone.getTimeZone(String)'
+     */
+    public void testGetTimeZone() {
+        // implicitly tested everywhere
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.TimeZone.getAvailableIDs(int)'
+     */
+    public void testGetAvailableIDsInt() {
+        String[] ids = TimeZone.getAvailableIDs(-28800000);
+        assertNotNull(ids);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.TimeZone.getAvailableIDs()'
+     */
+    public void testGetAvailableIDs() {
+        String[] ids = TimeZone.getAvailableIDs();
+        assertNotNull(ids);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.TimeZone.getDefault()'
+     */
+    public void testGetDefault() {
+        TimeZone tz = TimeZone.getDefault();
+        assertNotNull(tz);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.TimeZone.setDefault(TimeZone)'
+     */
+    public void testSetDefault() {
+        TimeZone tz1 = TimeZone.getDefault();
+        String newCode = "PDT".equals(tz1.getID()) ? "CST" : "PDT";
+        TimeZone tz2 = TimeZone.getTimeZone(newCode);
+        TimeZone.setDefault(tz2);
+        TimeZone result = TimeZone.getDefault();
+        assertNotEqual(tz1, result);
+        assertEquals(tz2, result);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.TimeZone.hasSameRules(TimeZone)'
+     */
+    public void testHasSameRules() {
+        TimeZone tz1 = TimeZone.getTimeZone("PST");
+        TimeZone tz2 = TimeZone.getTimeZone("America/Los_Angeles");
+        assertTrue(tz1.hasSameRules(tz2));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.TimeZone.clone()'
+     */
+    public void testClone() {
+        // tested by testHashCode
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.util.TimeZone.equals(Object)'
+     */
+    public void testEqualsObject() {
+        // tested by testHashCode
+    }
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/ULocaleTest.java b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/ULocaleTest.java
index 21cf50b..5523115 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/ULocaleTest.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/ULocaleTest.java
@@ -1,748 +1,847 @@
-/*
- *******************************************************************************
- * Copyright (C) 2006-2011, International Business Machines Corporation and    *
- * others. All Rights Reserved.                                                *
- *******************************************************************************
- */
-
-package com.ibm.icu.tests;
-
-import java.util.Iterator;
-import java.util.Locale;
-
-import com.ibm.icu.util.ULocale;
-
-public class ULocaleTest extends ICUTestCase {
-    private String sampleName;
-    private String longULocaleName;
-    private String longULocaleBasename;
-    private String nonNormalizedName;
-    private ULocale longULocale;
-    private Locale sampleLocale;
-        
-    /**
-     * @Override
-     */
-    protected void setUp() throws Exception {
-        super.setUp();
-                
-        sampleName = "ll_CC_VVVV";
-        longULocaleName = "ll_Ssss_CC_VVVV@collation=phonebook;key=value";
-        longULocaleBasename = longULocaleName.substring(0, longULocaleName.indexOf('@'));
-        nonNormalizedName = "LL_ssss_cc_VVVV@ Key = value ; Collation = phonebook ; ";
-        longULocale = new ULocale(longULocaleName);
-        sampleLocale = new ULocale(sampleName).toLocale();
-    }
-        
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.hashCode()'
-     */
-    public void testHashCode() {
-        ULocale obj = ULocale.GERMANY;
-        ULocale eq = new ULocale("de_DE");
-        ULocale neq = new ULocale("de_DE_FRENCH");
-                
-        ICUTestCase.testEHCS(obj, eq, neq);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.forLocale(Locale)'
-     */
-    public void testForLocale() {
-        assertEquals(ULocale.GERMANY, ULocale.forLocale(Locale.GERMANY));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.ULocale(String)'
-     */
-    public void testULocaleString() {
-        assertEquals(ULocale.GERMAN, new ULocale("de"));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.ULocale(String, String)'
-     */
-    public void testULocaleStringString() {
-        assertEquals(ULocale.GERMANY, new ULocale("de", "DE"));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.ULocale(String, String, String)'
-     */
-    public void testULocaleStringStringString() {
-        assertEquals(sampleLocale, new ULocale("ll", "cc", "VVVV").toLocale());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.createCanonical(String)'
-     */
-    public void testCreateCanonical() {
-        ULocale result = ULocale.createCanonical("de__PHONEBOOK");
-        assertEquals(new ULocale("de@collation=phonebook"), result);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.toLocale()'
-     */
-    public void testToLocale() {
-        assertEquals(sampleLocale, new ULocale("ll", "cc", "VVVV").toLocale());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getDefault()'
-     */
-    public void testGetDefault() {
-        assertEquals(Locale.getDefault(), ULocale.getDefault().toLocale());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.setDefault(ULocale)'
-     */
-    public void testSetDefault() {
-        Locale oldLocale = Locale.getDefault();
-        ULocale oldULocale = ULocale.getDefault();
-        try {
-            ULocale.setDefault(longULocale);
-            ICUTestCase.assertNotEqual(Locale.getDefault(), oldLocale);
-            ICUTestCase.assertNotEqual(ULocale.getDefault(), oldULocale);
-            assertEquals(longULocale, ULocale.getDefault());
-            assertEquals(sampleLocale, Locale.getDefault());
-        }
-        finally {
-            ULocale.setDefault(oldULocale);
-            Locale.setDefault(oldLocale); // in case of some error
-        }
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.clone()'
-     */
-    public void testClone() {
-        // see testHashcode
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.equals(Object)'
-     */
-    public void testEqualsObject() {
-        // see testHashcode
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getAvailableLocales()'
-     */
-    public void testGetAvailableLocales() {
-        ULocale[] ulocales = ULocale.getAvailableLocales();
-        if (ICUTestCase.testingWrapper) {
-            Locale[] locales = Locale.getAvailableLocales();
-            for (int i = 0; i < ulocales.length; ++i) {
-                assertEquals(ulocales[i].toLocale(), locales[i]);
-            }
-        }
-        // else nothing to test except that the function returned.
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getISOCountries()'
-     */
-    public void testGetISOCountries() {
-        String[] ucountries = ULocale.getISOCountries();
-        assertNotNull(ucountries);
-        if (ICUTestCase.testingWrapper) {
-            // keep our own data for now
-            // our data doesn't match java's so this test would fail
-            // TODO: enable if we decide to use java's data
-            // String[] countries = Locale.getISOCountries();
-            // TestBoilerplate.assertArraysEqual(ucountries, countries);
-        }
-        // else nothing to test except that the function returned.
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getISOLanguages()'
-     */
-    public void testGetISOLanguages() {
-        String[] ulanguages = ULocale.getISOLanguages();
-        assertNotNull(ulanguages);
-        if (ICUTestCase.testingWrapper) {
-            // keep our own data for now
-            // our data doesn't match java's so this test would fail
-            // TODO: enable if we decide to use java's data
-            // String[] languages = Locale.getISOLanguages();
-            // TestBoilerplate.assertArraysEqual(ulanguages, languages);
-        }
-        // else nothing to test except that the function returned.
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getLanguage()'
-     */
-    public void testGetLanguage() {
-        assertEquals("ll", longULocale.getLanguage());
-        assertEquals("ll", longULocale.toLocale().getLanguage());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getLanguage(String)'
-     */
-    public void testGetLanguageString() {
-        assertEquals("ll", ULocale.getLanguage(longULocale.getName()));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getScript()'
-     */
-    public void testGetScript() {
-        assertEquals("Ssss", longULocale.getScript());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getScript(String)'
-     */
-    public void testGetScriptString() {
-        assertEquals("Ssss", ULocale.getScript(longULocale.getName()));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getCountry()'
-     */
-    public void testGetCountry() {
-        assertEquals("CC", longULocale.getCountry());
-        assertEquals("CC", longULocale.toLocale().getCountry());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getCountry(String)'
-     */
-    public void testGetCountryString() {
-        assertEquals("CC", ULocale.getCountry(longULocale.getName()));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getVariant()'
-     */
-    public void testGetVariant() {
-        assertEquals("VVVV", longULocale.getVariant());
-        assertEquals("VVVV", longULocale.toLocale().getVariant());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getVariant(String)'
-     */
-    public void testGetVariantString() {
-        assertEquals("VVVV", ULocale.getVariant(longULocale.getName()));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getFallback(String)'
-     */
-    public void testGetFallbackString() {
-        assertEquals(ULocale.GERMAN, ULocale.getFallback(ULocale.GERMANY.getName()));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getFallback()'
-     */
-    public void testGetFallback() {
-        assertEquals(ULocale.GERMAN, ULocale.GERMANY.getFallback());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getBaseName()'
-     */
-    public void testGetBaseName() {
-        assertEquals(longULocaleBasename, longULocale.getBaseName());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getBaseName(String)'
-     */
-    public void testGetBaseNameString() {
-        assertEquals(longULocaleBasename, longULocale.getBaseName());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getName()'
-     */
-    public void testGetName() {
-        assertEquals(longULocaleName, longULocale.getName());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getName(String)'
-     */
-    public void testGetNameString() {
-        assertEquals(longULocaleName, ULocale.getName(nonNormalizedName));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.toString()'
-     */
-    public void testToString() {
-        assertEquals(longULocaleName, longULocale.toString());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getKeywords()'
-     */
-    public void testGetKeywords() {
-        Iterator<String> iter = longULocale.getKeywords();
-        assertEquals(iter.next(), "collation");
-        assertEquals(iter.next(), "key");
-        assertFalse(iter.hasNext());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getKeywords(String)'
-     */
-    public void testGetKeywordsString() {
-        Iterator<String> iter = ULocale.getKeywords(nonNormalizedName);
-        assertEquals(iter.next(), "collation");
-        assertEquals(iter.next(), "key");
-        assertFalse(iter.hasNext());
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getKeywordValue(String)'
-     */
-    public void testGetKeywordValueString() {
-        assertEquals("value", longULocale.getKeywordValue("key"));
-        assertEquals("phonebook", longULocale.getKeywordValue("collation"));
-        assertNull(longULocale.getKeywordValue("zzyzx"));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getKeywordValue(String, String)'
-     */
-    public void testGetKeywordValueStringString() {
-        assertEquals("value", ULocale.getKeywordValue(longULocaleName, "key"));
-        assertEquals("phonebook", ULocale.getKeywordValue(longULocaleName, "collation"));
-        assertNull(ULocale.getKeywordValue(longULocaleName, "zzyzx"));
-
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.canonicalize(String)'
-     */
-    public void testCanonicalize() {
-        assertEquals("de@collation=phonebook", ULocale.canonicalize("de__PHONEBOOK"));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.setKeywordValue(String, String)'
-     */
-    public void testSetKeywordValueStringString() {
-        ULocale munged = longULocale.setKeywordValue("key", "C#");
-        assertEquals("C#", munged.getKeywordValue("key"));
-        munged = munged.setKeywordValue("zzyzx", "grue");
-        assertEquals("grue", munged.getKeywordValue("zzyzx"));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.setKeywordValue(String, String, String)'
-     */
-    public void testSetKeywordValueStringStringString() {
-        String munged = ULocale.setKeywordValue(longULocaleName, "key", "C#");
-        assertEquals("C#", ULocale.getKeywordValue(munged, "key"));
-        munged = ULocale.setKeywordValue(munged, "zzyzx", "grue");
-        assertEquals("grue", ULocale.getKeywordValue(munged, "zzyzx"));
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getISO3Language()'
-     */
-    public void testGetISO3Language() {
-        String il = ULocale.GERMANY.getISO3Language();
-        String jl = Locale.GERMANY.getISO3Language();
-        assertEquals(il, jl);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getISO3Language(String)'
-     */
-    public void testGetISO3LanguageString() {
-        String il = ULocale.getISO3Language(ULocale.GERMANY.getName());
-        String jl = Locale.GERMANY.getISO3Language();
-        assertEquals(il, jl);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getISO3Country()'
-     */
-    public void testGetISO3Country() {
-        String ic = ULocale.GERMANY.getISO3Country();
-        String jc = Locale.GERMANY.getISO3Country();
-        assertEquals(ic, jc);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getISO3Country(String)'
-     */
-    public void testGetISO3CountryString() {
-        String ic = ULocale.getISO3Country(ULocale.GERMANY.getName());
-        String jc = Locale.GERMANY.getISO3Country();
-        assertEquals(ic, jc);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayLanguage()'
-     */
-    public void testGetDisplayLanguage() {
-        String idl = ULocale.GERMANY.getDisplayLanguage();
-        String jdl = Locale.GERMANY.getDisplayLanguage();
-        assertEquals(idl, jdl);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayLanguage(ULocale)'
-     */
-    public void testGetDisplayLanguageULocale() {
-        String idl = ULocale.GERMANY.getDisplayLanguage(ULocale.GERMANY);
-        String jdl = Locale.GERMANY.getDisplayLanguage(Locale.GERMANY);
-        assertEquals(idl, jdl);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayLanguage(String, String)'
-     */
-    public void testGetDisplayLanguageStringString() {
-        String idl = ULocale.getDisplayLanguage(ULocale.GERMANY.getName(), "de_DE");
-        String jdl = Locale.GERMANY.getDisplayLanguage(Locale.GERMANY);
-        assertEquals(idl, jdl);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayLanguage(String, ULocale)'
-     */
-    public void testGetDisplayLanguageStringULocale() {
-        String idl = ULocale.getDisplayLanguage(ULocale.GERMANY.getName(), ULocale.GERMANY);
-        String jdl = Locale.GERMANY.getDisplayLanguage(Locale.GERMANY);
-        assertEquals(idl, jdl);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayScript()'
-     */
-    public void testGetDisplayScript() {
-        String is = ULocale.TRADITIONAL_CHINESE.getDisplayScript();
-        if (ICUTestCase.testingWrapper) {
-            assertEquals("Hant", is);
-        } else {
-            assertEquals("Traditional Chinese", is);
-        }
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayScript(ULocale)'
-     */
-    public void testGetDisplayScriptULocale() {
-        String is = ULocale.TRADITIONAL_CHINESE.getDisplayScript(ULocale.GERMANY);
-        if (ICUTestCase.testingWrapper) {
-            assertEquals("Hant", is);
-        } else {
-            // TODO: look up expected value
-            assertEquals("Hant", is);
-        }
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayScript(String, String)'
-     */
-    public void testGetDisplayScriptStringString() {
-        String is = ULocale.getDisplayScript("zh_Hant", "de_DE");
-        if (ICUTestCase.testingWrapper) {
-            assertEquals("Hant", is);
-        } else {
-            // TODO: look up expected value
-            assertEquals("Hant", is);
-        }
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayScript(String, ULocale)'
-     */
-    public void testGetDisplayScriptStringULocale() {
-        String is = ULocale.getDisplayScript("zh_Hant", ULocale.GERMANY);
-        if (ICUTestCase.testingWrapper) {
-            assertEquals("Hant", is);
-        } else {
-            // TODO: look up expected value
-            assertEquals("Hant", is);
-        }
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayCountry()'
-     */
-    public void testGetDisplayCountry() {
-        String idc = ULocale.GERMANY.getDisplayCountry();
-        String jdc = Locale.GERMANY.getDisplayCountry();
-        assertEquals(idc, jdc);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayCountry(ULocale)'
-     */
-    public void testGetDisplayCountryULocale() {
-        String idc = ULocale.GERMANY.getDisplayCountry(ULocale.GERMANY);
-        String jdc = Locale.GERMANY.getDisplayCountry(Locale.GERMANY);
-        assertEquals(idc, jdc);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayCountry(String, String)'
-     */
-    public void testGetDisplayCountryStringString() {
-        String idc = ULocale.getDisplayCountry("de_DE", "de_DE");
-        String jdc = Locale.GERMANY.getDisplayCountry(Locale.GERMANY);
-        assertEquals(idc, jdc);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayCountry(String, ULocale)'
-     */
-    public void testGetDisplayCountryStringULocale() {
-        String idc = ULocale.getDisplayCountry("de_DE", ULocale.GERMANY);
-        String jdc = Locale.GERMANY.getDisplayCountry(Locale.GERMANY);
-        assertEquals(idc, jdc);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayVariant()'
-     */
-    public void testGetDisplayVariant() {
-        String idv = new ULocale("de_DE_PHONEBOOK").getDisplayVariant();
-        String jdv = new Locale("de", "DE", "PHONEBOOK").getDisplayVariant();
-        assertEquals(jdv, idv);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayVariant(ULocale)'
-     */
-    public void testGetDisplayVariantULocale() {
-        String idv = new ULocale("de_DE_PHONEBOOK").getDisplayVariant(ULocale.GERMANY);
-        String jdv = new Locale("de", "DE", "PHONEBOOK").getDisplayVariant(Locale.GERMANY);
-        assertEquals(jdv, idv);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayVariant(String, String)'
-     */
-    public void testGetDisplayVariantStringString() {
-        String idv = ULocale.getDisplayVariant("de_DE_PHONEBOOK", "de_DE");
-        String jdv = new Locale("de", "DE", "PHONEBOOK").getDisplayVariant(Locale.GERMANY);
-        assertEquals(jdv, idv);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayVariant(String, ULocale)'
-     */
-    public void testGetDisplayVariantStringULocale() {
-        String idv = ULocale.getDisplayVariant("de_DE_PHONEBOOK", ULocale.GERMANY);
-        String jdv = new Locale("de", "DE", "PHONEBOOK").getDisplayVariant(Locale.GERMANY);
-        assertEquals(jdv, idv);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayKeyword(String)'
-     */
-    public void testGetDisplayKeywordString() {
-        String idk = ULocale.getDisplayKeyword("collation");
-        assertEquals("collation", idk);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayKeyword(String, String)'
-     */
-    public void testGetDisplayKeywordStringString() {
-        String idk = ULocale.getDisplayKeyword("collation", "de_DE");
-        if (ICUTestCase.testingWrapper) {
-            assertEquals("collation", idk);
-        } else {
-            // TODO: find real value
-            assertEquals("collation", idk);
-        }
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayKeyword(String, ULocale)'
-     */
-    public void testGetDisplayKeywordStringULocale() {
-        String idk = ULocale.getDisplayKeyword("collation", ULocale.GERMANY);
-        if (ICUTestCase.testingWrapper) {
-            assertEquals("collation", idk);
-        } else {
-            // TODO: find real value
-            assertEquals("collation", idk);
-        }
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayKeywordValue(String)'
-     */
-    public void testGetDisplayKeywordValueString() {
-        ULocale ul = new ULocale("de_DE@collation=phonebook");
-        String idk = ul.getDisplayKeywordValue("collation");
-        if (ICUTestCase.testingWrapper) {
-            assertEquals("phonebook", idk);
-        } else {
-            // TODO: find real value
-            assertEquals("phonebook", idk);
-        }
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayKeywordValue(String, ULocale)'
-     */
-    public void testGetDisplayKeywordValueStringULocale() {
-        ULocale ul = new ULocale("de_DE@collation=phonebook");
-        String idk = ul.getDisplayKeywordValue("collation", ULocale.GERMANY);
-        if (ICUTestCase.testingWrapper) {
-            assertEquals("phonebook", idk);
-        } else {
-            // TODO: find real value
-            assertEquals("phonebook", idk);
-        }
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayKeywordValue(String, String, String)'
-     */
-    public void testGetDisplayKeywordValueStringStringString() {
-        String idk = ULocale.getDisplayKeywordValue("de_DE@collation=phonebook", "collation", "de_DE");
-        if (ICUTestCase.testingWrapper) {
-            assertEquals("phonebook", idk);
-        } else {
-            // TODO: find real value
-            assertEquals("phonebook", idk);
-        }
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayKeywordValue(String, String, ULocale)'
-     */
-    public void testGetDisplayKeywordValueStringStringULocale() {
-        String idk = ULocale.getDisplayKeywordValue("de_DE@collation=phonebook", "collation", ULocale.GERMANY);
-        if (ICUTestCase.testingWrapper) {
-            assertEquals("phonebook", idk);
-        } else {
-            // TODO: find real value
-            assertEquals("phonebook", idk);
-        }
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayName()'
-     */
-    public void testGetDisplayName() {
-        String idn = ULocale.GERMANY.getDisplayName();
-        String jdn = Locale.GERMANY.getDisplayName();
-        assertEquals(idn, jdn);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayName(ULocale)'
-     */
-    public void testGetDisplayNameULocale() {
-        String idn = ULocale.GERMANY.getDisplayName(ULocale.GERMANY);
-        String jdn = Locale.GERMANY.getDisplayName(Locale.GERMANY);
-        assertEquals(idn, jdn);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayName(String, String)'
-     */
-    public void testGetDisplayNameStringString() {
-        String idn = ULocale.getDisplayName("de_DE", "de_DE");
-        String jdn = Locale.GERMANY.getDisplayName(Locale.GERMANY);
-        assertEquals(idn, jdn);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayName(String, ULocale)'
-     */
-    public void testGetDisplayNameStringULocale() {
-        String idn = ULocale.getDisplayName("de_DE", ULocale.GERMANY);
-        String jdn = Locale.GERMANY.getDisplayName(Locale.GERMANY);
-        assertEquals(idn, jdn);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.acceptLanguage(String, ULocale[], boolean[])'
-     */
-    public void testAcceptLanguageStringULocaleArrayBooleanArray() {
-        boolean[] fallback = new boolean[1];
-        ULocale[] locales = { 
-            new ULocale("en_CA"), 
-            new ULocale("es_US"), 
-        };
-        ULocale result = ULocale.acceptLanguage("en-US, en-GB, en-CA, es-US", locales, fallback);
-        assertEquals(new ULocale("en_CA"), result);
-        assertFalse(fallback[0]);
-        result = ULocale.acceptLanguage("en-US, en-GB, es-US-NEWMEXICO", locales, fallback);
-        assertEquals(new ULocale("es_US"), result);
-        assertTrue(fallback[0]);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.acceptLanguage(ULocale[], ULocale[], boolean[])'
-     */
-    public void testAcceptLanguageULocaleArrayULocaleArrayBooleanArray() {
-        boolean[] fallback = new boolean[1];
-        ULocale[] locales = { 
-            new ULocale("en_CA"), 
-            new ULocale("es_US"), 
-        };
-        ULocale[] accept_locales = {
-            new ULocale("en_US"),
-            new ULocale("en_GB"),
-            new ULocale("en_CA"),
-            new ULocale("es_US"),
-        };
-        ULocale[] accept_locales2 = {
-            new ULocale("en_US"),
-            new ULocale("en_GB"),
-            new ULocale("es_US_NEWMEXICO"),
-        };
-        ULocale result = ULocale.acceptLanguage(accept_locales, locales, fallback);
-        assertEquals(new ULocale("en_CA"), result);
-        assertFalse(fallback[0]);
-        result = ULocale.acceptLanguage(accept_locales2, locales, fallback);
-        assertEquals(new ULocale("es_US"), result);
-        assertTrue(fallback[0]);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.acceptLanguage(String, boolean[])'
-     */
-    public void testAcceptLanguageStringBooleanArray() {
-        boolean[] fallback = new boolean[1];
-        ULocale result = ULocale.acceptLanguage("en-CA, en-GB, es-US", fallback);
-        assertEquals(new ULocale("en_CA"), result);
-        assertFalse(fallback[0]);
-        result = ULocale.acceptLanguage("es-US-NEWMEXICO", fallback);
-        assertNotNull(result); // actual result depends on jdk
-        assertTrue(fallback[0]);
-    }
-
-    /*
-     * Test method for 'com.ibm.icu.x.util.ULocale.acceptLanguage(ULocale[], boolean[])'
-     */
-    public void testAcceptLanguageULocaleArrayBooleanArray() {
-        boolean[] fallback = new boolean[1];
-        ULocale[] accept_locales = {
-            new ULocale("en_CA"),
-            new ULocale("en_GB"),
-            new ULocale("es_US"),
-        };
-        ULocale[] accept_locales2 = {
-            new ULocale("es_US_NEWMEXICO"),
-        };
-        ULocale result = ULocale.acceptLanguage(accept_locales, fallback);
-        assertEquals(new ULocale("en_CA"), result);
-        assertFalse(fallback[0]);
-        result = ULocale.acceptLanguage(accept_locales2, fallback);
-        assertNotNull(result); // actual result depends on jdk
-        assertTrue(fallback[0]);
-    }
-}
+/*
+ *******************************************************************************
+ * Copyright (C) 2006-2011, International Business Machines Corporation and    *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+
+package com.ibm.icu.tests;
+
+import java.util.Iterator;
+import java.util.Locale;
+
+import com.ibm.icu.util.ULocale;
+import com.ibm.icu.util.ULocale.Category;
+
+public class ULocaleTest extends ICUTestCase {
+    private String sampleName;
+    private String longULocaleName;
+    private String longULocaleBasename;
+    private String nonNormalizedName;
+    private ULocale longULocale;
+    private Locale sampleLocale;
+        
+    /**
+     * @Override
+     */
+    protected void setUp() throws Exception {
+        super.setUp();
+                
+        sampleName = "ll_CC_VVVV";
+        longULocaleName = "ll_Ssss_CC_VVVV@collation=phonebook;key=value";
+        longULocaleBasename = longULocaleName.substring(0, longULocaleName.indexOf('@'));
+        nonNormalizedName = "LL_ssss_cc_VVVV@ Key = value ; Collation = phonebook ; ";
+        longULocale = new ULocale(longULocaleName);
+        sampleLocale = new ULocale(sampleName).toLocale();
+    }
+        
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.hashCode()'
+     */
+    public void testHashCode() {
+        ULocale obj = ULocale.GERMANY;
+        ULocale eq = new ULocale("de_DE");
+        ULocale neq = new ULocale("de_DE_FRENCH");
+                
+        ICUTestCase.testEHCS(obj, eq, neq);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.forLocale(Locale)'
+     */
+    public void testForLocale() {
+        assertEquals(ULocale.GERMANY, ULocale.forLocale(Locale.GERMANY));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.ULocale(String)'
+     */
+    public void testULocaleString() {
+        assertEquals(ULocale.GERMAN, new ULocale("de"));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.ULocale(String, String)'
+     */
+    public void testULocaleStringString() {
+        assertEquals(ULocale.GERMANY, new ULocale("de", "DE"));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.ULocale(String, String, String)'
+     */
+    public void testULocaleStringStringString() {
+        assertEquals(sampleLocale, new ULocale("ll", "cc", "VVVV").toLocale());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.createCanonical(String)'
+     */
+    public void testCreateCanonical() {
+        ULocale result = ULocale.createCanonical("de__PHONEBOOK");
+        assertEquals(new ULocale("de@collation=phonebook"), result);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.toLocale()'
+     */
+    public void testToLocale() {
+        assertEquals(sampleLocale, new ULocale("ll", "cc", "VVVV").toLocale());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getDefault()'
+     */
+    public void testGetDefault() {
+        assertEquals(Locale.getDefault(), ULocale.getDefault().toLocale());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.setDefault(ULocale)'
+     */
+    public void testSetDefault() {
+        Locale oldLocale = Locale.getDefault();
+        ULocale oldULocale = ULocale.getDefault();
+        try {
+            ULocale.setDefault(longULocale);
+            ICUTestCase.assertNotEqual(Locale.getDefault(), oldLocale);
+            ICUTestCase.assertNotEqual(ULocale.getDefault(), oldULocale);
+            assertEquals(longULocale, ULocale.getDefault());
+            assertEquals(sampleLocale, Locale.getDefault());
+        }
+        finally {
+            ULocale.setDefault(oldULocale);
+            Locale.setDefault(oldLocale); // in case of some error
+        }
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.clone()'
+     */
+    public void testClone() {
+        // see testHashcode
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.equals(Object)'
+     */
+    public void testEqualsObject() {
+        // see testHashcode
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getAvailableLocales()'
+     */
+    public void testGetAvailableLocales() {
+        ULocale[] ulocales = ULocale.getAvailableLocales();
+        if (ICUTestCase.testingWrapper) {
+            Locale[] locales = Locale.getAvailableLocales();
+            for (int i = 0; i < ulocales.length; ++i) {
+                assertEquals(ulocales[i].toLocale(), locales[i]);
+            }
+        }
+        // else nothing to test except that the function returned.
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getISOCountries()'
+     */
+    public void testGetISOCountries() {
+        String[] ucountries = ULocale.getISOCountries();
+        assertNotNull(ucountries);
+        if (ICUTestCase.testingWrapper) {
+            // keep our own data for now
+            // our data doesn't match java's so this test would fail
+            // TODO: enable if we decide to use java's data
+            // String[] countries = Locale.getISOCountries();
+            // TestBoilerplate.assertArraysEqual(ucountries, countries);
+        }
+        // else nothing to test except that the function returned.
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getISOLanguages()'
+     */
+    public void testGetISOLanguages() {
+        String[] ulanguages = ULocale.getISOLanguages();
+        assertNotNull(ulanguages);
+        if (ICUTestCase.testingWrapper) {
+            // keep our own data for now
+            // our data doesn't match java's so this test would fail
+            // TODO: enable if we decide to use java's data
+            // String[] languages = Locale.getISOLanguages();
+            // TestBoilerplate.assertArraysEqual(ulanguages, languages);
+        }
+        // else nothing to test except that the function returned.
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getLanguage()'
+     */
+    public void testGetLanguage() {
+        assertEquals("ll", longULocale.getLanguage());
+        assertEquals("ll", longULocale.toLocale().getLanguage());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getLanguage(String)'
+     */
+    public void testGetLanguageString() {
+        assertEquals("ll", ULocale.getLanguage(longULocale.getName()));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getScript()'
+     */
+    public void testGetScript() {
+        assertEquals("Ssss", longULocale.getScript());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getScript(String)'
+     */
+    public void testGetScriptString() {
+        assertEquals("Ssss", ULocale.getScript(longULocale.getName()));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getCountry()'
+     */
+    public void testGetCountry() {
+        assertEquals("CC", longULocale.getCountry());
+        assertEquals("CC", longULocale.toLocale().getCountry());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getCountry(String)'
+     */
+    public void testGetCountryString() {
+        assertEquals("CC", ULocale.getCountry(longULocale.getName()));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getVariant()'
+     */
+    public void testGetVariant() {
+        assertEquals("VVVV", longULocale.getVariant());
+        assertEquals("VVVV", longULocale.toLocale().getVariant());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getVariant(String)'
+     */
+    public void testGetVariantString() {
+        assertEquals("VVVV", ULocale.getVariant(longULocale.getName()));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getFallback(String)'
+     */
+    public void testGetFallbackString() {
+        assertEquals(ULocale.GERMAN, ULocale.getFallback(ULocale.GERMANY.getName()));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getFallback()'
+     */
+    public void testGetFallback() {
+        assertEquals(ULocale.GERMAN, ULocale.GERMANY.getFallback());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getBaseName()'
+     */
+    public void testGetBaseName() {
+        assertEquals(longULocaleBasename, longULocale.getBaseName());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getBaseName(String)'
+     */
+    public void testGetBaseNameString() {
+        assertEquals(longULocaleBasename, longULocale.getBaseName());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getName()'
+     */
+    public void testGetName() {
+        assertEquals(longULocaleName, longULocale.getName());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getName(String)'
+     */
+    public void testGetNameString() {
+        assertEquals(longULocaleName, ULocale.getName(nonNormalizedName));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.toString()'
+     */
+    public void testToString() {
+        assertEquals(longULocaleName, longULocale.toString());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getKeywords()'
+     */
+    public void testGetKeywords() {
+        Iterator<String> iter = longULocale.getKeywords();
+        assertEquals(iter.next(), "collation");
+        assertEquals(iter.next(), "key");
+        assertFalse(iter.hasNext());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getKeywords(String)'
+     */
+    public void testGetKeywordsString() {
+        Iterator<String> iter = ULocale.getKeywords(nonNormalizedName);
+        assertEquals(iter.next(), "collation");
+        assertEquals(iter.next(), "key");
+        assertFalse(iter.hasNext());
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getKeywordValue(String)'
+     */
+    public void testGetKeywordValueString() {
+        assertEquals("value", longULocale.getKeywordValue("key"));
+        assertEquals("phonebook", longULocale.getKeywordValue("collation"));
+        assertNull(longULocale.getKeywordValue("zzyzx"));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getKeywordValue(String, String)'
+     */
+    public void testGetKeywordValueStringString() {
+        assertEquals("value", ULocale.getKeywordValue(longULocaleName, "key"));
+        assertEquals("phonebook", ULocale.getKeywordValue(longULocaleName, "collation"));
+        assertNull(ULocale.getKeywordValue(longULocaleName, "zzyzx"));
+
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.canonicalize(String)'
+     */
+    public void testCanonicalize() {
+        assertEquals("de@collation=phonebook", ULocale.canonicalize("de__PHONEBOOK"));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.setKeywordValue(String, String)'
+     */
+    public void testSetKeywordValueStringString() {
+        ULocale munged = longULocale.setKeywordValue("key", "C#");
+        assertEquals("C#", munged.getKeywordValue("key"));
+        munged = munged.setKeywordValue("zzyzx", "grue");
+        assertEquals("grue", munged.getKeywordValue("zzyzx"));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.setKeywordValue(String, String, String)'
+     */
+    public void testSetKeywordValueStringStringString() {
+        String munged = ULocale.setKeywordValue(longULocaleName, "key", "C#");
+        assertEquals("C#", ULocale.getKeywordValue(munged, "key"));
+        munged = ULocale.setKeywordValue(munged, "zzyzx", "grue");
+        assertEquals("grue", ULocale.getKeywordValue(munged, "zzyzx"));
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getISO3Language()'
+     */
+    public void testGetISO3Language() {
+        String il = ULocale.GERMANY.getISO3Language();
+        String jl = Locale.GERMANY.getISO3Language();
+        assertEquals(il, jl);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getISO3Language(String)'
+     */
+    public void testGetISO3LanguageString() {
+        String il = ULocale.getISO3Language(ULocale.GERMANY.getName());
+        String jl = Locale.GERMANY.getISO3Language();
+        assertEquals(il, jl);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getISO3Country()'
+     */
+    public void testGetISO3Country() {
+        String ic = ULocale.GERMANY.getISO3Country();
+        String jc = Locale.GERMANY.getISO3Country();
+        assertEquals(ic, jc);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getISO3Country(String)'
+     */
+    public void testGetISO3CountryString() {
+        String ic = ULocale.getISO3Country(ULocale.GERMANY.getName());
+        String jc = Locale.GERMANY.getISO3Country();
+        assertEquals(ic, jc);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayLanguage()'
+     */
+    public void testGetDisplayLanguage() {
+        String idl = ULocale.GERMANY.getDisplayLanguage();
+        String jdl = Locale.GERMANY.getDisplayLanguage();
+        assertEquals(idl, jdl);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayLanguage(ULocale)'
+     */
+    public void testGetDisplayLanguageULocale() {
+        String idl = ULocale.GERMANY.getDisplayLanguage(ULocale.GERMANY);
+        String jdl = Locale.GERMANY.getDisplayLanguage(Locale.GERMANY);
+        assertEquals(idl, jdl);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayLanguage(String, String)'
+     */
+    public void testGetDisplayLanguageStringString() {
+        String idl = ULocale.getDisplayLanguage(ULocale.GERMANY.getName(), "de_DE");
+        String jdl = Locale.GERMANY.getDisplayLanguage(Locale.GERMANY);
+        assertEquals(idl, jdl);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayLanguage(String, ULocale)'
+     */
+    public void testGetDisplayLanguageStringULocale() {
+        String idl = ULocale.getDisplayLanguage(ULocale.GERMANY.getName(), ULocale.GERMANY);
+        String jdl = Locale.GERMANY.getDisplayLanguage(Locale.GERMANY);
+        assertEquals(idl, jdl);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayScript()'
+     */
+    public void testGetDisplayScript() {
+        String is = ULocale.TRADITIONAL_CHINESE.getDisplayScript();
+        if (ICUTestCase.testingWrapper) {
+            assertEquals("Hant", is);
+        } else {
+            assertEquals("Traditional Chinese", is);
+        }
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayScript(ULocale)'
+     */
+    public void testGetDisplayScriptULocale() {
+        String is = ULocale.TRADITIONAL_CHINESE.getDisplayScript(ULocale.GERMANY);
+        if (ICUTestCase.testingWrapper) {
+            assertEquals("Hant", is);
+        } else {
+            // TODO: look up expected value
+            assertEquals("Hant", is);
+        }
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayScript(String, String)'
+     */
+    public void testGetDisplayScriptStringString() {
+        String is = ULocale.getDisplayScript("zh_Hant", "de_DE");
+        if (ICUTestCase.testingWrapper) {
+            assertEquals("Hant", is);
+        } else {
+            // TODO: look up expected value
+            assertEquals("Hant", is);
+        }
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayScript(String, ULocale)'
+     */
+    public void testGetDisplayScriptStringULocale() {
+        String is = ULocale.getDisplayScript("zh_Hant", ULocale.GERMANY);
+        if (ICUTestCase.testingWrapper) {
+            assertEquals("Hant", is);
+        } else {
+            // TODO: look up expected value
+            assertEquals("Hant", is);
+        }
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayCountry()'
+     */
+    public void testGetDisplayCountry() {
+        String idc = ULocale.GERMANY.getDisplayCountry();
+        String jdc = Locale.GERMANY.getDisplayCountry();
+        assertEquals(idc, jdc);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayCountry(ULocale)'
+     */
+    public void testGetDisplayCountryULocale() {
+        String idc = ULocale.GERMANY.getDisplayCountry(ULocale.GERMANY);
+        String jdc = Locale.GERMANY.getDisplayCountry(Locale.GERMANY);
+        assertEquals(idc, jdc);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayCountry(String, String)'
+     */
+    public void testGetDisplayCountryStringString() {
+        String idc = ULocale.getDisplayCountry("de_DE", "de_DE");
+        String jdc = Locale.GERMANY.getDisplayCountry(Locale.GERMANY);
+        assertEquals(idc, jdc);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayCountry(String, ULocale)'
+     */
+    public void testGetDisplayCountryStringULocale() {
+        String idc = ULocale.getDisplayCountry("de_DE", ULocale.GERMANY);
+        String jdc = Locale.GERMANY.getDisplayCountry(Locale.GERMANY);
+        assertEquals(idc, jdc);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayVariant()'
+     */
+    public void testGetDisplayVariant() {
+        String idv = new ULocale("de_DE_PHONEBOOK").getDisplayVariant();
+        String jdv = new Locale("de", "DE", "PHONEBOOK").getDisplayVariant();
+        assertEquals(jdv, idv);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayVariant(ULocale)'
+     */
+    public void testGetDisplayVariantULocale() {
+        String idv = new ULocale("de_DE_PHONEBOOK").getDisplayVariant(ULocale.GERMANY);
+        String jdv = new Locale("de", "DE", "PHONEBOOK").getDisplayVariant(Locale.GERMANY);
+        assertEquals(jdv, idv);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayVariant(String, String)'
+     */
+    public void testGetDisplayVariantStringString() {
+        String idv = ULocale.getDisplayVariant("de_DE_PHONEBOOK", "de_DE");
+        String jdv = new Locale("de", "DE", "PHONEBOOK").getDisplayVariant(Locale.GERMANY);
+        assertEquals(jdv, idv);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayVariant(String, ULocale)'
+     */
+    public void testGetDisplayVariantStringULocale() {
+        String idv = ULocale.getDisplayVariant("de_DE_PHONEBOOK", ULocale.GERMANY);
+        String jdv = new Locale("de", "DE", "PHONEBOOK").getDisplayVariant(Locale.GERMANY);
+        assertEquals(jdv, idv);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayKeyword(String)'
+     */
+    public void testGetDisplayKeywordString() {
+        String idk = ULocale.getDisplayKeyword("collation");
+        assertEquals("collation", idk);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayKeyword(String, String)'
+     */
+    public void testGetDisplayKeywordStringString() {
+        String idk = ULocale.getDisplayKeyword("collation", "de_DE");
+        if (ICUTestCase.testingWrapper) {
+            assertEquals("collation", idk);
+        } else {
+            // TODO: find real value
+            assertEquals("collation", idk);
+        }
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayKeyword(String, ULocale)'
+     */
+    public void testGetDisplayKeywordStringULocale() {
+        String idk = ULocale.getDisplayKeyword("collation", ULocale.GERMANY);
+        if (ICUTestCase.testingWrapper) {
+            assertEquals("collation", idk);
+        } else {
+            // TODO: find real value
+            assertEquals("collation", idk);
+        }
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayKeywordValue(String)'
+     */
+    public void testGetDisplayKeywordValueString() {
+        ULocale ul = new ULocale("de_DE@collation=phonebook");
+        String idk = ul.getDisplayKeywordValue("collation");
+        if (ICUTestCase.testingWrapper) {
+            assertEquals("phonebook", idk);
+        } else {
+            // TODO: find real value
+            assertEquals("phonebook", idk);
+        }
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayKeywordValue(String, ULocale)'
+     */
+    public void testGetDisplayKeywordValueStringULocale() {
+        ULocale ul = new ULocale("de_DE@collation=phonebook");
+        String idk = ul.getDisplayKeywordValue("collation", ULocale.GERMANY);
+        if (ICUTestCase.testingWrapper) {
+            assertEquals("phonebook", idk);
+        } else {
+            // TODO: find real value
+            assertEquals("phonebook", idk);
+        }
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayKeywordValue(String, String, String)'
+     */
+    public void testGetDisplayKeywordValueStringStringString() {
+        String idk = ULocale.getDisplayKeywordValue("de_DE@collation=phonebook", "collation", "de_DE");
+        if (ICUTestCase.testingWrapper) {
+            assertEquals("phonebook", idk);
+        } else {
+            // TODO: find real value
+            assertEquals("phonebook", idk);
+        }
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayKeywordValue(String, String, ULocale)'
+     */
+    public void testGetDisplayKeywordValueStringStringULocale() {
+        String idk = ULocale.getDisplayKeywordValue("de_DE@collation=phonebook", "collation", ULocale.GERMANY);
+        if (ICUTestCase.testingWrapper) {
+            assertEquals("phonebook", idk);
+        } else {
+            // TODO: find real value
+            assertEquals("phonebook", idk);
+        }
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayName()'
+     */
+    public void testGetDisplayName() {
+        String idn = ULocale.GERMANY.getDisplayName();
+        String jdn = Locale.GERMANY.getDisplayName();
+        assertEquals(idn, jdn);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayName(ULocale)'
+     */
+    public void testGetDisplayNameULocale() {
+        String idn = ULocale.GERMANY.getDisplayName(ULocale.GERMANY);
+        String jdn = Locale.GERMANY.getDisplayName(Locale.GERMANY);
+        assertEquals(idn, jdn);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayName(String, String)'
+     */
+    public void testGetDisplayNameStringString() {
+        String idn = ULocale.getDisplayName("de_DE", "de_DE");
+        String jdn = Locale.GERMANY.getDisplayName(Locale.GERMANY);
+        assertEquals(idn, jdn);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getDisplayName(String, ULocale)'
+     */
+    public void testGetDisplayNameStringULocale() {
+        String idn = ULocale.getDisplayName("de_DE", ULocale.GERMANY);
+        String jdn = Locale.GERMANY.getDisplayName(Locale.GERMANY);
+        assertEquals(idn, jdn);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.acceptLanguage(String, ULocale[], boolean[])'
+     */
+    public void testAcceptLanguageStringULocaleArrayBooleanArray() {
+        boolean[] fallback = new boolean[1];
+        ULocale[] locales = { 
+            new ULocale("en_CA"), 
+            new ULocale("es_US"), 
+        };
+        ULocale result = ULocale.acceptLanguage("en-US, en-GB, en-CA, es-US", locales, fallback);
+        assertEquals(new ULocale("en_CA"), result);
+        assertFalse(fallback[0]);
+        result = ULocale.acceptLanguage("en-US, en-GB, es-US-NEWMEXICO", locales, fallback);
+        assertEquals(new ULocale("es_US"), result);
+        assertTrue(fallback[0]);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.acceptLanguage(ULocale[], ULocale[], boolean[])'
+     */
+    public void testAcceptLanguageULocaleArrayULocaleArrayBooleanArray() {
+        boolean[] fallback = new boolean[1];
+        ULocale[] locales = { 
+            new ULocale("en_CA"), 
+            new ULocale("es_US"), 
+        };
+        ULocale[] accept_locales = {
+            new ULocale("en_US"),
+            new ULocale("en_GB"),
+            new ULocale("en_CA"),
+            new ULocale("es_US"),
+        };
+        ULocale[] accept_locales2 = {
+            new ULocale("en_US"),
+            new ULocale("en_GB"),
+            new ULocale("es_US_NEWMEXICO"),
+        };
+        ULocale result = ULocale.acceptLanguage(accept_locales, locales, fallback);
+        assertEquals(new ULocale("en_CA"), result);
+        assertFalse(fallback[0]);
+        result = ULocale.acceptLanguage(accept_locales2, locales, fallback);
+        assertEquals(new ULocale("es_US"), result);
+        assertTrue(fallback[0]);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.acceptLanguage(String, boolean[])'
+     */
+    public void testAcceptLanguageStringBooleanArray() {
+        boolean[] fallback = new boolean[1];
+        ULocale result = ULocale.acceptLanguage("en-CA, en-GB, es-US", fallback);
+        assertEquals(new ULocale("en_CA"), result);
+        assertFalse(fallback[0]);
+        result = ULocale.acceptLanguage("es-US-NEWMEXICO", fallback);
+        assertNotNull(result); // actual result depends on jdk
+        assertTrue(fallback[0]);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.acceptLanguage(ULocale[], boolean[])'
+     */
+    public void testAcceptLanguageULocaleArrayBooleanArray() {
+        boolean[] fallback = new boolean[1];
+        ULocale[] accept_locales = {
+            new ULocale("en_CA"),
+            new ULocale("en_GB"),
+            new ULocale("es_US"),
+        };
+        ULocale[] accept_locales2 = {
+            new ULocale("es_US_NEWMEXICO"),
+        };
+        ULocale result = ULocale.acceptLanguage(accept_locales, fallback);
+        assertEquals(new ULocale("en_CA"), result);
+        assertFalse(fallback[0]);
+        result = ULocale.acceptLanguage(accept_locales2, fallback);
+        assertNotNull(result); // actual result depends on jdk
+        assertTrue(fallback[0]);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.toLanguageTag()'
+     */
+    public void testToLanguageTag() {
+        ULocale[] test_ulocales = {
+            new ULocale("en_US"),
+            new ULocale(""),
+            new ULocale("de_DE@collation=phonebook"),
+            new ULocale("en_Latn_US_POSIX"),
+            new ULocale("th_TH@numbers=thai;calendar=buddhist"),
+            new ULocale("und_CN@timezone=PRC"),
+            new ULocale("iw_IL"),
+        };
+
+        String[] expected = {
+            "en-US",
+            "und",
+            "de-DE-u-co-phonebk",
+            "en-Latn-US-u-va-posix",
+            "th-TH-u-ca-buddhist-nu-thai",
+            "und-CN-u-tz-cnsha",
+            "he-IL",
+        };
+
+        for (int i = 0; i < test_ulocales.length; i++) {
+            String result = test_ulocales[i].toLanguageTag();
+            assertEquals(expected[i], result);
+        }
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.forLanguageTag()'
+     */
+    public void testForLanguageTag() {
+        String[] test_tags = {
+            "en-us",
+            "Und-Us",
+            "ja-jp-u-ca-japanese",
+            "fr-FR-u-tz-frpar-ca-gregory",
+        };
+
+        ULocale[] expected = {
+            new ULocale("en_US"),
+            new ULocale("und_US"),
+            new ULocale("ja_JP@calendar=japanese"),
+            new ULocale("fr_FR@calendar=gregorian;timezone=Europe/Paris"),
+        };
+
+        for (int i = 0; i < test_tags.length; i++) {
+            ULocale result = ULocale.forLanguageTag(test_tags[i]);
+            assertEquals(expected[i], result);
+        }
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.getDefault(Category)'
+     */
+    public void testGetDefaultCategory() {
+        ULocale dispLoc = ULocale.getDefault(Category.DISPLAY);
+        assertNotNull(dispLoc);
+        ULocale formLoc = ULocale.getDefault(Category.FORMAT);
+        assertNotNull(formLoc);
+    }
+
+    /*
+     * Test method for 'com.ibm.icu.x.util.ULocale.setDefault(Category, ULocale)'
+     */
+    public void testSetDefaultCategoryULocale() {
+        ULocale orgDefault = ULocale.getDefault();
+        ULocale orgDisplay = ULocale.getDefault(Category.DISPLAY);
+        ULocale orgFormat = ULocale.getDefault(Category.FORMAT);
+
+        ULocale jaUS = new ULocale("ja_US");
+        ULocale.setDefault(jaUS);
+
+        // setDefault(ULocale) updates category defaults
+        assertEquals(ULocale.getDefault(), jaUS);
+        assertEquals(ULocale.getDefault(Category.DISPLAY), jaUS);
+        assertEquals(ULocale.getDefault(Category.FORMAT), jaUS);
+
+        ULocale frDE = new ULocale("fr_DE");
+        ULocale.setDefault(Category.DISPLAY, frDE);
+
+        // setDefault(Category, ULocale) only updates the category default
+        assertEquals(ULocale.getDefault(), jaUS);
+        assertEquals(ULocale.getDefault(Category.DISPLAY), frDE);
+        assertEquals(ULocale.getDefault(Category.FORMAT), jaUS);
+
+        // restore the original
+        ULocale.setDefault(orgDefault);
+        ULocale.setDefault(Category.DISPLAY, orgDisplay);
+        ULocale.setDefault(Category.FORMAT, orgFormat);
+
+        assertEquals(ULocale.getDefault(), orgDefault);
+        assertEquals(ULocale.getDefault(Category.DISPLAY), orgDisplay);
+        assertEquals(ULocale.getDefault(Category.FORMAT), orgFormat);
+    }
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/.classpath b/eclipse-build/plugins.template/com.ibm.icu.base/.classpath
index 0215967..45f024e 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base/.classpath
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/.classpath
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
 	<classpathentry kind="src" path="src"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/ICUCache.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/ICUCache.java
index c3ca4b5..17828f7 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/ICUCache.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/ICUCache.java
@@ -1,21 +1,21 @@
-/*
- ***************************************************************************
- * Copyright (c) 2007-2011 International Business Machines Corporation and *
- * others.  All rights reserved.                                           *
- ***************************************************************************
-*/
-
-package com.ibm.icu.impl;
-
-public interface ICUCache<K, V> {
-    // Type of reference holding the Map instance
-    public static final int SOFT = 0;
-    public static final int WEAK = 1;
-
-    // NULL object, which may be used for a cache key
-    public static final Object NULL = new Object();
-
-    public void clear();
-    public void put(K key, V value);
-    public V get(Object key);
-}
+/*
+ ***************************************************************************
+ * Copyright (c) 2007-2011 International Business Machines Corporation and *
+ * others.  All rights reserved.                                           *
+ ***************************************************************************
+*/
+
+package com.ibm.icu.impl;
+
+public interface ICUCache<K, V> {
+    // Type of reference holding the Map instance
+    public static final int SOFT = 0;
+    public static final int WEAK = 1;
+
+    // NULL object, which may be used for a cache key
+    public static final Object NULL = new Object();
+
+    public void clear();
+    public void put(K key, V value);
+    public V get(Object key);
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/LocaleIDParser.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/LocaleIDParser.java
index a9d0d30..67690da 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/LocaleIDParser.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/LocaleIDParser.java
@@ -1,741 +1,741 @@
-/*
-******************************************************************************
-* Copyright (C) 2003-2011, International Business Machines Corporation and   *
-* others. All Rights Reserved.                                               *
-******************************************************************************
-*/
-
-package com.ibm.icu.impl;
-
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.TreeMap;
-
-import com.ibm.icu.impl.locale.AsciiUtil;
-
-/**
- * Utility class to parse and normalize locale ids (including POSIX style)
- */
-public final class LocaleIDParser {
-    private char[] id;
-    private int index;
-    private char[] buffer;
-    private int blen;
-    // um, don't handle POSIX ids unless we request it.  why not?  well... because.
-    private boolean canonicalize;
-    private boolean hadCountry;
-
-    // used when canonicalizing
-    Map<String, String> keywords;
-    String baseName;
-
-    /**
-     * Parsing constants.
-     */
-    private static final char KEYWORD_SEPARATOR     = '@';
-    private static final char HYPHEN                = '-';
-    private static final char KEYWORD_ASSIGN        = '=';
-    private static final char COMMA                 = ',';
-    private static final char ITEM_SEPARATOR        = ';';
-    private static final char DOT                   = '.';
-    private static final char UNDERSCORE            = '_';
-
-    public LocaleIDParser(String localeID) {
-        this(localeID, false);
-    }
-
-    public LocaleIDParser(String localeID, boolean canonicalize) {
-        id = localeID.toCharArray();
-        index = 0;
-        buffer = new char[id.length + 5];
-        blen = 0;
-        this.canonicalize = canonicalize;
-    }
-
-    private void reset() {
-        index = blen = 0;
-    }
-
-    // utilities for working on text in the buffer
-
-    /**
-     * Append c to the buffer.
-     */
-    private void append(char c) {
-        try {
-            buffer[blen] = c;
-        }
-        catch (IndexOutOfBoundsException e) {
-            if (buffer.length > 512) {
-                // something is seriously wrong, let this go
-                throw e;
-            }
-            char[] nbuffer = new char[buffer.length * 2];
-            System.arraycopy(buffer, 0, nbuffer, 0, buffer.length);
-            nbuffer[blen] = c;
-            buffer = nbuffer;
-        }
-        ++blen;
-    }
-
-    private void addSeparator() {
-        append(UNDERSCORE);
-    }
-
-    /**
-     * Returns the text in the buffer from start to blen as a String.
-     */
-    private String getString(int start) {
-        if (start == blen) {
-            return "";
-        }
-        return new String(buffer, start, blen-start);
-    }
-
-    /**
-     * Set the length of the buffer to pos, then append the string.
-     */
-    private void set(int pos, String s) {
-        this.blen = pos; // no safety
-        append(s);
-    }
-
-    /**
-     * Append the string to the buffer.
-     */
-    private void append(String s) {
-        for (int i = 0; i < s.length(); ++i) {
-            append(s.charAt(i));
-        }
-    }
-
-    // utilities for parsing text out of the id
-
-    /**
-     * Character to indicate no more text is available in the id.
-     */
-    private static final char DONE = '\uffff';
-
-    /**
-     * Returns the character at index in the id, and advance index.  The returned character
-     * is DONE if index was at the limit of the buffer.  The index is advanced regardless
-     * so that decrementing the index will always 'unget' the last character returned.
-     */
-    private char next() {
-        if (index == id.length) {
-            index++;
-            return DONE;
-        }
-
-        return id[index++];
-    }
-
-    /**
-     * Advance index until the next terminator or id separator, and leave it there.
-     */
-    private void skipUntilTerminatorOrIDSeparator() {
-        while (!isTerminatorOrIDSeparator(next())) {
-        }
-        --index;
-    }
-
-    /**
-     * Returns true if the character at index in the id is a terminator.
-     */
-    private boolean atTerminator() {
-        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.
-     */
-    private boolean isTerminator(char c) {
-        // always terminate at DOT, even if not handling POSIX.  It's an error...
-        return c == KEYWORD_SEPARATOR || c == DONE || c == DOT;
-    }
-
-    /**
-     * Returns true if the character is a terminator or id separator.
-     */
-    private boolean isTerminatorOrIDSeparator(char c) {
-        return c == KEYWORD_SEPARATOR || c == UNDERSCORE || c == HYPHEN ||
-        c == DONE || c == DOT;
-    }
-
-    /**
-     * Returns true if the start of the buffer has an experimental or private language
-     * prefix, the pattern '[ixIX][-_].' shows the syntax checked.
-     */
-    private boolean haveExperimentalLanguagePrefix() {
-        if (id.length > 2) {
-            char c = id[1];
-            if (c == HYPHEN || c == UNDERSCORE) {
-                c = id[0];
-                return c == 'x' || c == 'X' || c == 'i' || c == 'I';
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Returns true if a value separator occurs at or after index.
-     */
-    private boolean haveKeywordAssign() {
-        // assume it is safe to start from index
-        for (int i = index; i < id.length; ++i) {
-            if (id[i] == KEYWORD_ASSIGN) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Advance index past language, and accumulate normalized language code in buffer.
-     * Index must be at 0 when this is called.  Index is left at a terminator or id
-     * separator.  Returns the start of the language code in the buffer.
-     */
-    private int parseLanguage() {
-        if (haveExperimentalLanguagePrefix()) {
-            append(Character.toLowerCase(id[0]));
-            append(HYPHEN);
-            index = 2;
-        }
-
-        char c;
-        while(!isTerminatorOrIDSeparator(c = next())) {
-            append(Character.toLowerCase(c));
-        }
-        --index; // unget
-
-        if (blen == 3) {
-            String lang = LocaleIDs.threeToTwoLetterLanguage(getString(0));
-            if (lang != null) {
-                set(0, lang);
-            }
-        }
-
-        return 0;
-    }
-
-    /**
-     * Advance index past language.  Index must be at 0 when this is called.  Index
-     * is left at a terminator or id separator.
-     */
-    private void skipLanguage() {
-        if (haveExperimentalLanguagePrefix()) {
-            index = 2;
-        }
-        skipUntilTerminatorOrIDSeparator();
-    }
-
-    /**
-     * Advance index past script, and accumulate normalized script in buffer.
-     * Index must be immediately after the language.
-     * If the item at this position is not a script (is not four characters
-     * long) leave index and buffer unchanged.  Otherwise index is left at
-     * a terminator or id separator.  Returns the start of the script code
-     * in the buffer (this may be equal to the buffer length, if there is no
-     * script).
-     */
-    private int parseScript() {
-        if (!atTerminator()) {
-            int oldIndex = index; // save original index
-            ++index;
-
-            int oldBlen = blen; // get before append hyphen, if we truncate everything is undone
-            char c;
-            while(!isTerminatorOrIDSeparator(c = next())) {
-                if (blen == oldBlen) { // first pass
-                    addSeparator();
-                    append(Character.toUpperCase(c));
-                } else {
-                    append(Character.toLowerCase(c));
-                }
-            }
-            --index; // unget
-
-            /* If it's not exactly 4 characters long, then it's not a script. */
-            if (index - oldIndex != 5) { // +1 to account for separator
-                index = oldIndex;
-                blen = oldBlen;
-            } else {
-                oldBlen++; // index past hyphen, for clients who want to extract just the script
-            }
-
-            return oldBlen;
-        }
-        return blen;
-    }
-
-    /**
-     * Advance index past script.
-     * Index must be immediately after the language and IDSeparator.
-     * If the item at this position is not a script (is not four characters
-     * long) leave index.  Otherwise index is left at a terminator or
-     * id separator.
-     */
-    private void skipScript() {
-        if (!atTerminator()) {
-            int oldIndex = index;
-            ++index;
-
-            skipUntilTerminatorOrIDSeparator();
-            if (index - oldIndex != 5) { // +1 to account for separator
-                index = oldIndex;
-            }
-        }
-    }
-
-    /**
-     * Advance index past country, and accumulate normalized country in buffer.
-     * Index must be immediately after the script (if there is one, else language)
-     * and IDSeparator.  Return the start of the country code in the buffer.
-     */
-    private int parseCountry() {
-        if (!atTerminator()) {
-            int oldIndex = index;
-            ++index;
-
-            int oldBlen = blen;
-            char c;
-            while (!isTerminatorOrIDSeparator(c = next())) {
-                if (oldBlen == blen) { // first, add hyphen
-                    hadCountry = true; // we have a country, let variant parsing know
-                    addSeparator();
-                    ++oldBlen; // increment past hyphen
-                }
-                append(Character.toUpperCase(c));
-            }
-            --index; // unget
-
-            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) {
-                String region = LocaleIDs.threeToTwoLetterRegion(getString(oldBlen));
-                if (region != null) {
-                    set(oldBlen, region);
-                }
-            }
-
-            return oldBlen;
-        }
-
-        return blen;
-    }
-
-    /**
-     * Advance index past country.
-     * Index must be immediately after the script (if there is one, else language)
-     * and IDSeparator.
-     */
-    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;
-            }
-        }
-    }
-
-    /**
-     * Advance index past variant, and accumulate normalized variant in buffer.  This ignores
-     * the codepage information from POSIX ids.  Index must be immediately after the country
-     * or script.  Index is left at the keyword separator or at the end of the text.  Return
-     * the start of the variant code in the buffer.
-     *
-     * In standard form, we can have the following forms:
-     * ll__VVVV
-     * ll_CC_VVVV
-     * ll_Ssss_VVVV
-     * ll_Ssss_CC_VVVV
-     *
-     * This also handles POSIX ids, which can have the following forms (pppp is code page id):
-     * ll_CC.pppp          --> ll_CC
-     * ll_CC.pppp@VVVV     --> ll_CC_VVVV
-     * ll_CC@VVVV          --> ll_CC_VVVV
-     *
-     * We identify this use of '@' in POSIX ids by looking for an '=' following
-     * the '@'.  If there is one, we consider '@' to start a keyword list, instead of
-     * being part of a POSIX id.
-     *
-     * Note:  since it was decided that we want an option to not handle POSIX ids, this
-     * becomes a bit more complex.
-     */
-    private int parseVariant() {
-        int oldBlen = blen;
-
-        boolean start = true;
-        boolean needSeparator = true;
-        boolean skipping = false;
-        char c;
-        while ((c = next()) != DONE) {
-            if (c == DOT) {
-                start = false;
-                skipping = true;
-            } else if (c == KEYWORD_SEPARATOR) {
-                if (haveKeywordAssign()) {
-                    break;
-                }
-                skipping = false;
-                start = false;
-                needSeparator = true; // add another underscore if we have more text
-            } else if (start) {
-                start = false;
-            } else if (!skipping) {
-                if (needSeparator) {
-                    boolean incOldBlen = blen == oldBlen; // need to skip separators
-                    needSeparator = false;
-                    if (incOldBlen && !hadCountry) { // no country, we'll need two
-                        addSeparator();
-                        ++oldBlen; // for sure
-                    }
-                    addSeparator();
-                    if (incOldBlen) { // only for the first separator
-                        ++oldBlen;
-                    }
-                }
-                c = Character.toUpperCase(c);
-                if (c == HYPHEN || c == COMMA) {
-                    c = UNDERSCORE;
-                }
-                append(c);
-            }
-        }
-        --index; // unget
-
-        return oldBlen;
-    }
-
-    // no need for skipvariant, to get the keywords we'll just scan directly for
-    // the keyword separator
-
-    /**
-     * Returns the normalized language id, or the empty string.
-     */
-    public String getLanguage() {
-        reset();
-        return getString(parseLanguage());
-    }
-
-    /**
-     * Returns the normalized script id, or the empty string.
-     */
-    public String getScript() {
-        reset();
-        skipLanguage();
-        return getString(parseScript());
-    }
-
-    /**
-     * return the normalized country id, or the empty string.
-     */
-    public String getCountry() {
-        reset();
-        skipLanguage();
-        skipScript();
-        return getString(parseCountry());
-    }
-
-    /**
-     * Returns the normalized variant id, or the empty string.
-     */
-    public String getVariant() {
-        reset();
-        skipLanguage();
-        skipScript();
-        skipCountry();
-        return getString(parseVariant());
-    }
-
-    /**
-     * Returns the language, script, country, and variant as separate strings.
-     */
-    public String[] getLanguageScriptCountryVariant() {
-        reset();
-        return new String[] {
-                getString(parseLanguage()),
-                getString(parseScript()),
-                getString(parseCountry()),
-                getString(parseVariant())
-        };
-    }
-
-    public void setBaseName(String baseName) {
-        this.baseName = baseName;
-    }
-
-    public void parseBaseName() {
-        if (baseName != null) {
-            set(0, baseName);
-        } else {
-            reset();
-            parseLanguage();
-            parseScript();
-            parseCountry();
-            parseVariant();
-
-            // catch unwanted trailing underscore after country if there was no variant
-            if (blen > 1 && buffer[blen-1] == UNDERSCORE) {
-                --blen;
-            }
-        }
-    }
-
-    /**
-     * Returns the normalized base form of the locale id.  The base
-     * form does not include keywords.
-     */
-    public String getBaseName() {
-        if (baseName != null) {
-            return baseName;
-        }
-        parseBaseName();
-        return getString(0);
-    }
-
-    /**
-     * Returns the normalized full form of the locale id.  The full
-     * form includes keywords if they are present.
-     */
-    public String getName() {
-        parseBaseName();
-        parseKeywords();
-        return getString(0);
-    }
-
-    // keyword utilities
-
-    /**
-     * If we have keywords, advance index to the start of the keywords and return true,
-     * otherwise return false.
-     */
-    private boolean setToKeywordStart() {
-        for (int i = index; i < id.length; ++i) {
-            if (id[i] == KEYWORD_SEPARATOR) {
-                if (canonicalize) {
-                    for (int j = ++i; j < id.length; ++j) { // increment i past separator for return
-                        if (id[j] == KEYWORD_ASSIGN) {
-                            index = i;
-                            return true;
-                        }
-                    }
-                } else {
-                    if (++i < id.length) {
-                        index = i;
-                        return true;
-                    }
-                }
-                break;
-            }
-        }
-        return false;
-    }
-
-    private static boolean isDoneOrKeywordAssign(char c) {
-        return c == DONE || c == KEYWORD_ASSIGN;
-    }
-
-    private static boolean isDoneOrItemSeparator(char c) {
-        return c == DONE || c == ITEM_SEPARATOR;
-    }
-
-    private String getKeyword() {
-        int start = index;
-        while (!isDoneOrKeywordAssign(next())) {
-        }
-        --index;
-        return AsciiUtil.toLowerString(new String(id, start, index-start).trim());
-    }
-
-    private String getValue() {
-        int start = index;
-        while (!isDoneOrItemSeparator(next())) {
-        }
-        --index;
-        return new String(id, start, index-start).trim(); // leave case alone
-    }
-
-    private Comparator<String> getKeyComparator() {
-        final Comparator<String> comp = new Comparator<String>() {
-            public int compare(String lhs, String rhs) {
-                return lhs.compareTo(rhs);
-            }
-        };
-        return comp;
-    }
-
-    /**
-     * Returns a map of the keywords and values, or null if there are none.
-     */
-    public Map<String, String> getKeywordMap() {
-        if (keywords == null) {
-            TreeMap<String, String> m = null;
-            if (setToKeywordStart()) {
-                // trim spaces and convert to lower case, both keywords and values.
-                do {
-                    String key = getKeyword();
-                    if (key.length() == 0) {
-                        break;
-                    }
-                    char c = next();
-                    if (c != KEYWORD_ASSIGN) {
-                        // throw new IllegalArgumentException("key '" + key + "' missing a value.");
-                        if (c == DONE) {
-                            break;
-                        } else {
-                            continue;
-                        }
-                    }
-                    String value = getValue();
-                    if (value.length() == 0) {
-                        // throw new IllegalArgumentException("key '" + key + "' missing a value.");
-                        continue;
-                    }
-                    if (m == null) {
-                        m = new TreeMap<String, String>(getKeyComparator());
-                    } else if (m.containsKey(key)) {
-                        // throw new IllegalArgumentException("key '" + key + "' already has a value.");
-                        continue;
-                    }
-                    m.put(key, value);
-                } while (next() == ITEM_SEPARATOR);
-            }
-            keywords = m != null ? m : Collections.<String, String>emptyMap();
-        }
-
-        return keywords;
-    }
-
-
-    /**
-     * Parse the keywords and return start of the string in the buffer.
-     */
-    private int parseKeywords() {
-        int oldBlen = blen;
-        Map<String, String> m = getKeywordMap();
-        if (!m.isEmpty()) {
-            boolean first = true;
-            for (Map.Entry<String, String> e : m.entrySet()) {
-                append(first ? KEYWORD_SEPARATOR : ITEM_SEPARATOR);
-                first = false;
-                append(e.getKey());
-                append(KEYWORD_ASSIGN);
-                append(e.getValue());
-            }
-            if (blen != oldBlen) {
-                ++oldBlen;
-            }
-        }
-        return oldBlen;
-    }
-
-    /**
-     * Returns an iterator over the keywords, or null if we have an empty map.
-     */
-    public Iterator<String> getKeywords() {
-        Map<String, String> m = getKeywordMap();
-        return m.isEmpty() ? null : m.keySet().iterator();
-    }
-
-    /**
-     * Returns the value for the named keyword, or null if the keyword is not
-     * present.
-     */
-    public String getKeywordValue(String keywordName) {
-        Map<String, String> m = getKeywordMap();
-        return m.isEmpty() ? null : m.get(AsciiUtil.toLowerString(keywordName.trim()));
-    }
-
-    /**
-     * Set the keyword value only if it is not already set to something else.
-     */
-    public void defaultKeywordValue(String keywordName, String value) {
-        setKeywordValue(keywordName, value, false);
-    }
-
-    /**
-     * Set the value for the named keyword, or unset it if value is null.  If
-     * keywordName itself is null, unset all keywords.  If keywordName is not null,
-     * value must not be null.
-     */
-    public void setKeywordValue(String keywordName, String value) {
-        setKeywordValue(keywordName, value, true);
-    }
-
-    /**
-     * Set the value for the named keyword, or unset it if value is null.  If
-     * keywordName itself is null, unset all keywords.  If keywordName is not null,
-     * value must not be null.  If reset is true, ignore any previous value for
-     * the keyword, otherwise do not change the keyword (including removal of
-     * one or all keywords).
-     */
-    private void setKeywordValue(String keywordName, String value, boolean reset) {
-        if (keywordName == null) {
-            if (reset) {
-                // force new map, ignore value
-                keywords = Collections.<String, String>emptyMap();
-            }
-        } else {
-            keywordName = AsciiUtil.toLowerString(keywordName.trim());
-            if (keywordName.length() == 0) {
-                throw new IllegalArgumentException("keyword must not be empty");
-            }
-            if (value != null) {
-                value = value.trim();
-                if (value.length() == 0) {
-                    throw new IllegalArgumentException("value must not be empty");
-                }
-            }
-            Map<String, String> m = getKeywordMap();
-            if (m.isEmpty()) { // it is EMPTY_MAP
-                if (value != null) {
-                    // force new map
-                    keywords = new TreeMap<String, String>(getKeyComparator());
-                    keywords.put(keywordName, value.trim());
-                }
-            } else {
-                if (reset || !m.containsKey(keywordName)) {
-                    if (value != null) {
-                        m.put(keywordName, value);
-                    } else {
-                        m.remove(keywordName);
-                        if (m.isEmpty()) {
-                            // force new map
-                            keywords = Collections.<String, String>emptyMap();
-                        }
-                    }
-                }
-            }
-        }
-    }
+/*
+******************************************************************************
+* Copyright (C) 2003-2011, International Business Machines Corporation and   *
+* others. All Rights Reserved.                                               *
+******************************************************************************
+*/
+
+package com.ibm.icu.impl;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.TreeMap;
+
+import com.ibm.icu.impl.locale.AsciiUtil;
+
+/**
+ * Utility class to parse and normalize locale ids (including POSIX style)
+ */
+public final class LocaleIDParser {
+    private char[] id;
+    private int index;
+    private char[] buffer;
+    private int blen;
+    // um, don't handle POSIX ids unless we request it.  why not?  well... because.
+    private boolean canonicalize;
+    private boolean hadCountry;
+
+    // used when canonicalizing
+    Map<String, String> keywords;
+    String baseName;
+
+    /**
+     * Parsing constants.
+     */
+    private static final char KEYWORD_SEPARATOR     = '@';
+    private static final char HYPHEN                = '-';
+    private static final char KEYWORD_ASSIGN        = '=';
+    private static final char COMMA                 = ',';
+    private static final char ITEM_SEPARATOR        = ';';
+    private static final char DOT                   = '.';
+    private static final char UNDERSCORE            = '_';
+
+    public LocaleIDParser(String localeID) {
+        this(localeID, false);
+    }
+
+    public LocaleIDParser(String localeID, boolean canonicalize) {
+        id = localeID.toCharArray();
+        index = 0;
+        buffer = new char[id.length + 5];
+        blen = 0;
+        this.canonicalize = canonicalize;
+    }
+
+    private void reset() {
+        index = blen = 0;
+    }
+
+    // utilities for working on text in the buffer
+
+    /**
+     * Append c to the buffer.
+     */
+    private void append(char c) {
+        try {
+            buffer[blen] = c;
+        }
+        catch (IndexOutOfBoundsException e) {
+            if (buffer.length > 512) {
+                // something is seriously wrong, let this go
+                throw e;
+            }
+            char[] nbuffer = new char[buffer.length * 2];
+            System.arraycopy(buffer, 0, nbuffer, 0, buffer.length);
+            nbuffer[blen] = c;
+            buffer = nbuffer;
+        }
+        ++blen;
+    }
+
+    private void addSeparator() {
+        append(UNDERSCORE);
+    }
+
+    /**
+     * Returns the text in the buffer from start to blen as a String.
+     */
+    private String getString(int start) {
+        if (start == blen) {
+            return "";
+        }
+        return new String(buffer, start, blen-start);
+    }
+
+    /**
+     * Set the length of the buffer to pos, then append the string.
+     */
+    private void set(int pos, String s) {
+        this.blen = pos; // no safety
+        append(s);
+    }
+
+    /**
+     * Append the string to the buffer.
+     */
+    private void append(String s) {
+        for (int i = 0; i < s.length(); ++i) {
+            append(s.charAt(i));
+        }
+    }
+
+    // utilities for parsing text out of the id
+
+    /**
+     * Character to indicate no more text is available in the id.
+     */
+    private static final char DONE = '\uffff';
+
+    /**
+     * Returns the character at index in the id, and advance index.  The returned character
+     * is DONE if index was at the limit of the buffer.  The index is advanced regardless
+     * so that decrementing the index will always 'unget' the last character returned.
+     */
+    private char next() {
+        if (index == id.length) {
+            index++;
+            return DONE;
+        }
+
+        return id[index++];
+    }
+
+    /**
+     * Advance index until the next terminator or id separator, and leave it there.
+     */
+    private void skipUntilTerminatorOrIDSeparator() {
+        while (!isTerminatorOrIDSeparator(next())) {
+        }
+        --index;
+    }
+
+    /**
+     * Returns true if the character at index in the id is a terminator.
+     */
+    private boolean atTerminator() {
+        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.
+     */
+    private boolean isTerminator(char c) {
+        // always terminate at DOT, even if not handling POSIX.  It's an error...
+        return c == KEYWORD_SEPARATOR || c == DONE || c == DOT;
+    }
+
+    /**
+     * Returns true if the character is a terminator or id separator.
+     */
+    private boolean isTerminatorOrIDSeparator(char c) {
+        return c == KEYWORD_SEPARATOR || c == UNDERSCORE || c == HYPHEN ||
+        c == DONE || c == DOT;
+    }
+
+    /**
+     * Returns true if the start of the buffer has an experimental or private language
+     * prefix, the pattern '[ixIX][-_].' shows the syntax checked.
+     */
+    private boolean haveExperimentalLanguagePrefix() {
+        if (id.length > 2) {
+            char c = id[1];
+            if (c == HYPHEN || c == UNDERSCORE) {
+                c = id[0];
+                return c == 'x' || c == 'X' || c == 'i' || c == 'I';
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Returns true if a value separator occurs at or after index.
+     */
+    private boolean haveKeywordAssign() {
+        // assume it is safe to start from index
+        for (int i = index; i < id.length; ++i) {
+            if (id[i] == KEYWORD_ASSIGN) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Advance index past language, and accumulate normalized language code in buffer.
+     * Index must be at 0 when this is called.  Index is left at a terminator or id
+     * separator.  Returns the start of the language code in the buffer.
+     */
+    private int parseLanguage() {
+        if (haveExperimentalLanguagePrefix()) {
+            append(Character.toLowerCase(id[0]));
+            append(HYPHEN);
+            index = 2;
+        }
+
+        char c;
+        while(!isTerminatorOrIDSeparator(c = next())) {
+            append(Character.toLowerCase(c));
+        }
+        --index; // unget
+
+        if (blen == 3) {
+            String lang = LocaleIDs.threeToTwoLetterLanguage(getString(0));
+            if (lang != null) {
+                set(0, lang);
+            }
+        }
+
+        return 0;
+    }
+
+    /**
+     * Advance index past language.  Index must be at 0 when this is called.  Index
+     * is left at a terminator or id separator.
+     */
+    private void skipLanguage() {
+        if (haveExperimentalLanguagePrefix()) {
+            index = 2;
+        }
+        skipUntilTerminatorOrIDSeparator();
+    }
+
+    /**
+     * Advance index past script, and accumulate normalized script in buffer.
+     * Index must be immediately after the language.
+     * If the item at this position is not a script (is not four characters
+     * long) leave index and buffer unchanged.  Otherwise index is left at
+     * a terminator or id separator.  Returns the start of the script code
+     * in the buffer (this may be equal to the buffer length, if there is no
+     * script).
+     */
+    private int parseScript() {
+        if (!atTerminator()) {
+            int oldIndex = index; // save original index
+            ++index;
+
+            int oldBlen = blen; // get before append hyphen, if we truncate everything is undone
+            char c;
+            while(!isTerminatorOrIDSeparator(c = next())) {
+                if (blen == oldBlen) { // first pass
+                    addSeparator();
+                    append(Character.toUpperCase(c));
+                } else {
+                    append(Character.toLowerCase(c));
+                }
+            }
+            --index; // unget
+
+            /* If it's not exactly 4 characters long, then it's not a script. */
+            if (index - oldIndex != 5) { // +1 to account for separator
+                index = oldIndex;
+                blen = oldBlen;
+            } else {
+                oldBlen++; // index past hyphen, for clients who want to extract just the script
+            }
+
+            return oldBlen;
+        }
+        return blen;
+    }
+
+    /**
+     * Advance index past script.
+     * Index must be immediately after the language and IDSeparator.
+     * If the item at this position is not a script (is not four characters
+     * long) leave index.  Otherwise index is left at a terminator or
+     * id separator.
+     */
+    private void skipScript() {
+        if (!atTerminator()) {
+            int oldIndex = index;
+            ++index;
+
+            skipUntilTerminatorOrIDSeparator();
+            if (index - oldIndex != 5) { // +1 to account for separator
+                index = oldIndex;
+            }
+        }
+    }
+
+    /**
+     * Advance index past country, and accumulate normalized country in buffer.
+     * Index must be immediately after the script (if there is one, else language)
+     * and IDSeparator.  Return the start of the country code in the buffer.
+     */
+    private int parseCountry() {
+        if (!atTerminator()) {
+            int oldIndex = index;
+            ++index;
+
+            int oldBlen = blen;
+            char c;
+            while (!isTerminatorOrIDSeparator(c = next())) {
+                if (oldBlen == blen) { // first, add hyphen
+                    hadCountry = true; // we have a country, let variant parsing know
+                    addSeparator();
+                    ++oldBlen; // increment past hyphen
+                }
+                append(Character.toUpperCase(c));
+            }
+            --index; // unget
+
+            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) {
+                String region = LocaleIDs.threeToTwoLetterRegion(getString(oldBlen));
+                if (region != null) {
+                    set(oldBlen, region);
+                }
+            }
+
+            return oldBlen;
+        }
+
+        return blen;
+    }
+
+    /**
+     * Advance index past country.
+     * Index must be immediately after the script (if there is one, else language)
+     * and IDSeparator.
+     */
+    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;
+            }
+        }
+    }
+
+    /**
+     * Advance index past variant, and accumulate normalized variant in buffer.  This ignores
+     * the codepage information from POSIX ids.  Index must be immediately after the country
+     * or script.  Index is left at the keyword separator or at the end of the text.  Return
+     * the start of the variant code in the buffer.
+     *
+     * In standard form, we can have the following forms:
+     * ll__VVVV
+     * ll_CC_VVVV
+     * ll_Ssss_VVVV
+     * ll_Ssss_CC_VVVV
+     *
+     * This also handles POSIX ids, which can have the following forms (pppp is code page id):
+     * ll_CC.pppp          --> ll_CC
+     * ll_CC.pppp@VVVV     --> ll_CC_VVVV
+     * ll_CC@VVVV          --> ll_CC_VVVV
+     *
+     * We identify this use of '@' in POSIX ids by looking for an '=' following
+     * the '@'.  If there is one, we consider '@' to start a keyword list, instead of
+     * being part of a POSIX id.
+     *
+     * Note:  since it was decided that we want an option to not handle POSIX ids, this
+     * becomes a bit more complex.
+     */
+    private int parseVariant() {
+        int oldBlen = blen;
+
+        boolean start = true;
+        boolean needSeparator = true;
+        boolean skipping = false;
+        char c;
+        while ((c = next()) != DONE) {
+            if (c == DOT) {
+                start = false;
+                skipping = true;
+            } else if (c == KEYWORD_SEPARATOR) {
+                if (haveKeywordAssign()) {
+                    break;
+                }
+                skipping = false;
+                start = false;
+                needSeparator = true; // add another underscore if we have more text
+            } else if (start) {
+                start = false;
+            } else if (!skipping) {
+                if (needSeparator) {
+                    boolean incOldBlen = blen == oldBlen; // need to skip separators
+                    needSeparator = false;
+                    if (incOldBlen && !hadCountry) { // no country, we'll need two
+                        addSeparator();
+                        ++oldBlen; // for sure
+                    }
+                    addSeparator();
+                    if (incOldBlen) { // only for the first separator
+                        ++oldBlen;
+                    }
+                }
+                c = Character.toUpperCase(c);
+                if (c == HYPHEN || c == COMMA) {
+                    c = UNDERSCORE;
+                }
+                append(c);
+            }
+        }
+        --index; // unget
+
+        return oldBlen;
+    }
+
+    // no need for skipvariant, to get the keywords we'll just scan directly for
+    // the keyword separator
+
+    /**
+     * Returns the normalized language id, or the empty string.
+     */
+    public String getLanguage() {
+        reset();
+        return getString(parseLanguage());
+    }
+
+    /**
+     * Returns the normalized script id, or the empty string.
+     */
+    public String getScript() {
+        reset();
+        skipLanguage();
+        return getString(parseScript());
+    }
+
+    /**
+     * return the normalized country id, or the empty string.
+     */
+    public String getCountry() {
+        reset();
+        skipLanguage();
+        skipScript();
+        return getString(parseCountry());
+    }
+
+    /**
+     * Returns the normalized variant id, or the empty string.
+     */
+    public String getVariant() {
+        reset();
+        skipLanguage();
+        skipScript();
+        skipCountry();
+        return getString(parseVariant());
+    }
+
+    /**
+     * Returns the language, script, country, and variant as separate strings.
+     */
+    public String[] getLanguageScriptCountryVariant() {
+        reset();
+        return new String[] {
+                getString(parseLanguage()),
+                getString(parseScript()),
+                getString(parseCountry()),
+                getString(parseVariant())
+        };
+    }
+
+    public void setBaseName(String baseName) {
+        this.baseName = baseName;
+    }
+
+    public void parseBaseName() {
+        if (baseName != null) {
+            set(0, baseName);
+        } else {
+            reset();
+            parseLanguage();
+            parseScript();
+            parseCountry();
+            parseVariant();
+
+            // catch unwanted trailing underscore after country if there was no variant
+            if (blen > 1 && buffer[blen-1] == UNDERSCORE) {
+                --blen;
+            }
+        }
+    }
+
+    /**
+     * Returns the normalized base form of the locale id.  The base
+     * form does not include keywords.
+     */
+    public String getBaseName() {
+        if (baseName != null) {
+            return baseName;
+        }
+        parseBaseName();
+        return getString(0);
+    }
+
+    /**
+     * Returns the normalized full form of the locale id.  The full
+     * form includes keywords if they are present.
+     */
+    public String getName() {
+        parseBaseName();
+        parseKeywords();
+        return getString(0);
+    }
+
+    // keyword utilities
+
+    /**
+     * If we have keywords, advance index to the start of the keywords and return true,
+     * otherwise return false.
+     */
+    private boolean setToKeywordStart() {
+        for (int i = index; i < id.length; ++i) {
+            if (id[i] == KEYWORD_SEPARATOR) {
+                if (canonicalize) {
+                    for (int j = ++i; j < id.length; ++j) { // increment i past separator for return
+                        if (id[j] == KEYWORD_ASSIGN) {
+                            index = i;
+                            return true;
+                        }
+                    }
+                } else {
+                    if (++i < id.length) {
+                        index = i;
+                        return true;
+                    }
+                }
+                break;
+            }
+        }
+        return false;
+    }
+
+    private static boolean isDoneOrKeywordAssign(char c) {
+        return c == DONE || c == KEYWORD_ASSIGN;
+    }
+
+    private static boolean isDoneOrItemSeparator(char c) {
+        return c == DONE || c == ITEM_SEPARATOR;
+    }
+
+    private String getKeyword() {
+        int start = index;
+        while (!isDoneOrKeywordAssign(next())) {
+        }
+        --index;
+        return AsciiUtil.toLowerString(new String(id, start, index-start).trim());
+    }
+
+    private String getValue() {
+        int start = index;
+        while (!isDoneOrItemSeparator(next())) {
+        }
+        --index;
+        return new String(id, start, index-start).trim(); // leave case alone
+    }
+
+    private Comparator<String> getKeyComparator() {
+        final Comparator<String> comp = new Comparator<String>() {
+            public int compare(String lhs, String rhs) {
+                return lhs.compareTo(rhs);
+            }
+        };
+        return comp;
+    }
+
+    /**
+     * Returns a map of the keywords and values, or null if there are none.
+     */
+    public Map<String, String> getKeywordMap() {
+        if (keywords == null) {
+            TreeMap<String, String> m = null;
+            if (setToKeywordStart()) {
+                // trim spaces and convert to lower case, both keywords and values.
+                do {
+                    String key = getKeyword();
+                    if (key.length() == 0) {
+                        break;
+                    }
+                    char c = next();
+                    if (c != KEYWORD_ASSIGN) {
+                        // throw new IllegalArgumentException("key '" + key + "' missing a value.");
+                        if (c == DONE) {
+                            break;
+                        } else {
+                            continue;
+                        }
+                    }
+                    String value = getValue();
+                    if (value.length() == 0) {
+                        // throw new IllegalArgumentException("key '" + key + "' missing a value.");
+                        continue;
+                    }
+                    if (m == null) {
+                        m = new TreeMap<String, String>(getKeyComparator());
+                    } else if (m.containsKey(key)) {
+                        // throw new IllegalArgumentException("key '" + key + "' already has a value.");
+                        continue;
+                    }
+                    m.put(key, value);
+                } while (next() == ITEM_SEPARATOR);
+            }
+            keywords = m != null ? m : Collections.<String, String>emptyMap();
+        }
+
+        return keywords;
+    }
+
+
+    /**
+     * Parse the keywords and return start of the string in the buffer.
+     */
+    private int parseKeywords() {
+        int oldBlen = blen;
+        Map<String, String> m = getKeywordMap();
+        if (!m.isEmpty()) {
+            boolean first = true;
+            for (Map.Entry<String, String> e : m.entrySet()) {
+                append(first ? KEYWORD_SEPARATOR : ITEM_SEPARATOR);
+                first = false;
+                append(e.getKey());
+                append(KEYWORD_ASSIGN);
+                append(e.getValue());
+            }
+            if (blen != oldBlen) {
+                ++oldBlen;
+            }
+        }
+        return oldBlen;
+    }
+
+    /**
+     * Returns an iterator over the keywords, or null if we have an empty map.
+     */
+    public Iterator<String> getKeywords() {
+        Map<String, String> m = getKeywordMap();
+        return m.isEmpty() ? null : m.keySet().iterator();
+    }
+
+    /**
+     * Returns the value for the named keyword, or null if the keyword is not
+     * present.
+     */
+    public String getKeywordValue(String keywordName) {
+        Map<String, String> m = getKeywordMap();
+        return m.isEmpty() ? null : m.get(AsciiUtil.toLowerString(keywordName.trim()));
+    }
+
+    /**
+     * Set the keyword value only if it is not already set to something else.
+     */
+    public void defaultKeywordValue(String keywordName, String value) {
+        setKeywordValue(keywordName, value, false);
+    }
+
+    /**
+     * Set the value for the named keyword, or unset it if value is null.  If
+     * keywordName itself is null, unset all keywords.  If keywordName is not null,
+     * value must not be null.
+     */
+    public void setKeywordValue(String keywordName, String value) {
+        setKeywordValue(keywordName, value, true);
+    }
+
+    /**
+     * Set the value for the named keyword, or unset it if value is null.  If
+     * keywordName itself is null, unset all keywords.  If keywordName is not null,
+     * value must not be null.  If reset is true, ignore any previous value for
+     * the keyword, otherwise do not change the keyword (including removal of
+     * one or all keywords).
+     */
+    private void setKeywordValue(String keywordName, String value, boolean reset) {
+        if (keywordName == null) {
+            if (reset) {
+                // force new map, ignore value
+                keywords = Collections.<String, String>emptyMap();
+            }
+        } else {
+            keywordName = AsciiUtil.toLowerString(keywordName.trim());
+            if (keywordName.length() == 0) {
+                throw new IllegalArgumentException("keyword must not be empty");
+            }
+            if (value != null) {
+                value = value.trim();
+                if (value.length() == 0) {
+                    throw new IllegalArgumentException("value must not be empty");
+                }
+            }
+            Map<String, String> m = getKeywordMap();
+            if (m.isEmpty()) { // it is EMPTY_MAP
+                if (value != null) {
+                    // force new map
+                    keywords = new TreeMap<String, String>(getKeyComparator());
+                    keywords.put(keywordName, value.trim());
+                }
+            } else {
+                if (reset || !m.containsKey(keywordName)) {
+                    if (value != null) {
+                        m.put(keywordName, value);
+                    } else {
+                        m.remove(keywordName);
+                        if (m.isEmpty()) {
+                            // force new map
+                            keywords = Collections.<String, String>emptyMap();
+                        }
+                    }
+                }
+            }
+        }
+    }
 }
\ No newline at end of file
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/LocaleIDs.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/LocaleIDs.java
index 8edd3d4..34c0a5b 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/LocaleIDs.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/LocaleIDs.java
@@ -1,536 +1,536 @@
-/*
- *******************************************************************************
- * Copyright (C) 2009-2011, International Business Machines Corporation and    *
- * others. All Rights Reserved.                                                *
- *******************************************************************************
- */
-package com.ibm.icu.impl;
-
-import java.util.MissingResourceException;
-
-import com.ibm.icu.util.ULocale;
-
-
-/**
- * Utilities for mapping between old and new language, country, and other
- * locale ID related names.
- */
-public class LocaleIDs {
-
-    /**
-     * Returns a list of all 2-letter country codes defined in ISO 3166.
-     * Can be used to create Locales.
-     * @stable ICU 3.0
-     */
-    public static String[] getISOCountries() {
-        initCountryTables();
-        return _countries.clone();
-    }
-
-    /**
-     * Returns a list of all 2-letter language codes defined in ISO 639.
-     * Can be used to create Locales.
-     * [NOTE:  ISO 639 is not a stable standard-- some languages' codes have changed.
-     * The list this function returns includes both the new and the old codes for the
-     * languages whose codes have changed.]
-     * @stable ICU 3.0
-     */
-    public static String[] getISOLanguages() {
-        initLanguageTables();
-        return _languages.clone();
-    }
-
-    /**
-     * Returns a three-letter abbreviation for the provided country.  If the provided
-     * country is empty, returns the empty string.  Otherwise, returns
-     * an uppercase ISO 3166 3-letter country code.
-     * @exception MissingResourceException Throws MissingResourceException if the
-     * three-letter country abbreviation is not available for this locale.
-     * @stable ICU 3.0
-     */
-    public static String getISO3Country(String country){
-        initCountryTables();
-
-        int offset = findIndex(_countries, country);
-        if(offset>=0){
-            return _countries3[offset];
-        }else{
-            offset = findIndex(_obsoleteCountries, country);
-            if(offset>=0){
-                return _obsoleteCountries3[offset];
-            }
-        }
-        return "";
-    }
-    /**
-     * Returns a three-letter abbreviation for the language.  If language is
-     * empty, returns the empty string.  Otherwise, returns
-     * a lowercase ISO 639-2/T language code.
-     * The ISO 639-2 language codes can be found on-line at
-     *   <a href="ftp://dkuug.dk/i18n/iso-639-2.txt"><code>ftp://dkuug.dk/i18n/iso-639-2.txt</code></a>
-     * @exception MissingResourceException Throws MissingResourceException if the
-     * three-letter language abbreviation is not available for this locale.
-     * @stable ICU 3.0
-     */
-    public static String getISO3Language(String language) {
-        initLanguageTables();
-
-        int offset = findIndex(_languages, language);
-        if(offset>=0){
-            return _languages3[offset];
-        } else {
-            offset = findIndex(_obsoleteLanguages, language);
-            if (offset >= 0) {
-                return _obsoleteLanguages3[offset];
-            }
-        }
-        return "";
-    }
-
-    public static String threeToTwoLetterLanguage(String lang) {
-        initLanguageTables();
-
-        /* convert 3 character code to 2 character code if possible *CWB*/
-        int offset = findIndex(_languages3, lang);
-        if (offset >= 0) {
-            return _languages[offset];
-        }
-
-        offset = findIndex(_obsoleteLanguages3, lang);
-        if (offset >= 0) {
-            return _obsoleteLanguages[offset];
-        }
-
-        return null;
-    }
-
-    public static String threeToTwoLetterRegion(String region) {
-        initCountryTables();
-
-        /* convert 3 character code to 2 character code if possible *CWB*/
-        int offset = findIndex(_countries3, region);
-        if (offset >= 0) {
-            return _countries[offset];
-        }
-
-        offset = findIndex(_obsoleteCountries3, region);
-        if (offset >= 0) {
-            return _obsoleteCountries[offset];
-        }
-
-        return null;
-    }
-
-    /**
-     * linear search of the string array. the arrays are unfortunately ordered by the
-     * two-letter target code, not the three-letter search code, which seems backwards.
-     */
-    private static int findIndex(String[] array, String target){
-        for (int i = 0; i < array.length; i++) {
-            if (target.equals(array[i])) {
-                return i;
-            }
-        }
-        return -1;
-    }
-
-
-    /**
-     * Tables used in normalizing portions of the id.
-     */
-    /* tables updated per http://lcweb.loc.gov/standards/iso639-2/
-       to include the revisions up to 2001/7/27 *CWB*/
-    /* The 3 character codes are the terminology codes like RFC 3066.
-       This is compatible with prior ICU codes */
-    /* "in" "iw" "ji" "jw" & "sh" have been withdrawn but are still in
-       the table but now at the end of the table because
-       3 character codes are duplicates.  This avoids bad searches
-       going from 3 to 2 character codes.*/
-    /* The range qaa-qtz is reserved for local use. */
-
-    private static String[] _languages;
-    private static String[] _replacementLanguages;
-    private static String[] _obsoleteLanguages;
-    private static String[] _languages3;
-    private static String[] _obsoleteLanguages3;
-
-    // Avoid initializing languages tables unless we have to.
-    private static void initLanguageTables() {
-        if (_languages == null) {
-
-            /* This list MUST be in sorted order, and MUST contain the two-letter codes
-               if one exists otherwise use the three letter code */
-            String[] tempLanguages = {
-                "aa",  "ab",  "ace", "ach", "ada", "ady", "ae",  "af",  "afa",
-                "afh", "ak",  "akk", "ale", "alg", "am",  "an",  "ang", "apa",
-                "ar",  "arc", "arn", "arp", "art", "arw", "as",  "ast",
-                "ath", "aus", "av",  "awa", "ay",  "az",  "ba",  "bad",
-                "bai", "bal", "ban", "bas", "bat", "be",  "bej",
-                "bem", "ber", "bg",  "bh",  "bho", "bi",  "bik", "bin",
-                "bla", "bm",  "bn",  "bnt", "bo",  "br",  "bra", "bs",
-                "btk", "bua", "bug", "byn", "ca",  "cad", "cai", "car", "cau",
-                "ce",  "ceb", "cel", "ch",  "chb", "chg", "chk", "chm",
-                "chn", "cho", "chp", "chr", "chy", "cmc", "co",  "cop",
-                "cpe", "cpf", "cpp", "cr",  "crh", "crp", "cs",  "csb", "cu",  "cus",
-                "cv",  "cy",  "da",  "dak", "dar", "day", "de",  "del", "den",
-                "dgr", "din", "doi", "dra", "dsb", "dua", "dum", "dv",  "dyu",
-                "dz",  "ee",  "efi", "egy", "eka", "el",  "elx", "en",
-                "enm", "eo",  "es",  "et",  "eu",  "ewo", "fa",
-                "fan", "fat", "ff",  "fi",  "fiu", "fj",  "fo",  "fon",
-                "fr",  "frm", "fro", "fur", "fy",  "ga",  "gaa", "gay",
-                "gba", "gd",  "gem", "gez", "gil", "gl",  "gmh", "gn",
-                "goh", "gon", "gor", "got", "grb", "grc", "gu",  "gv",
-                "gwi", "ha",  "hai", "haw", "he",  "hi",  "hil", "him",
-                "hit", "hmn", "ho",  "hr",  "hsb", "ht",  "hu",  "hup", "hy",  "hz",
-                "ia",  "iba", "id",  "ie",  "ig",  "ii",  "ijo", "ik",
-                "ilo", "inc", "ine", "inh", "io",  "ira", "iro", "is",  "it",
-                "iu",  "ja",  "jbo", "jpr", "jrb", "jv",  "ka",  "kaa", "kab",
-                "kac", "kam", "kar", "kaw", "kbd", "kg",  "kha", "khi",
-                "kho", "ki",  "kj",  "kk",  "kl",  "km",  "kmb", "kn",
-                "ko",  "kok", "kos", "kpe", "kr",  "krc", "kro", "kru", "ks",
-                "ku",  "kum", "kut", "kv",  "kw",  "ky",  "la",  "lad",
-                "lah", "lam", "lb",  "lez", "lg",  "li",  "ln",  "lo",  "lol",
-                "loz", "lt",  "lu",  "lua", "lui", "lun", "luo", "lus",
-                "lv",  "mad", "mag", "mai", "mak", "man", "map", "mas",
-                "mdf", "mdr", "men", "mg",  "mga", "mh",  "mi",  "mic", "min",
-                "mis", "mk",  "mkh", "ml",  "mn",  "mnc", "mni", "mno",
-                "mo",  "moh", "mos", "mr",  "ms",  "mt",  "mul", "mun",
-                "mus", "mwr", "my",  "myn", "myv", "na",  "nah", "nai", "nap",
-                "nb",  "nd",  "nds", "ne",  "new", "ng",  "nia", "nic",
-                "niu", "nl",  "nn",  "no",  "nog", "non", "nr",  "nso", "nub",
-                "nv",  "nwc", "ny",  "nym", "nyn", "nyo", "nzi", "oc",  "oj",
-                "om",  "or",  "os",  "osa", "ota", "oto", "pa",  "paa",
-                "pag", "pal", "pam", "pap", "pau", "peo", "phi", "phn",
-                "pi",  "pl",  "pon", "pra", "pro", "ps",  "pt",  "qu",
-                "raj", "rap", "rar", "rm",  "rn",  "ro",  "roa", "rom",
-                "ru",  "rup", "rw",  "sa",  "sad", "sah", "sai", "sal", "sam",
-                "sas", "sat", "sc",  "sco", "sd",  "se",  "sel", "sem",
-                "sg",  "sga", "sgn", "shn", "si",  "sid", "sio", "sit",
-                "sk",  "sl",  "sla", "sm",  "sma", "smi", "smj", "smn",
-                "sms", "sn",  "snk", "so",  "sog", "son", "sq",  "sr",
-                "srr", "ss",  "ssa", "st",  "su",  "suk", "sus", "sux",
-                "sv",  "sw",  "syr", "ta",  "tai", "te",  "tem", "ter",
-                "tet", "tg",  "th",  "ti",  "tig", "tiv", "tk",  "tkl",
-                "tl",  "tlh", "tli", "tmh", "tn",  "to",  "tog", "tpi", "tr",
-                "ts",  "tsi", "tt",  "tum", "tup", "tut", "tvl", "tw",
-                "ty",  "tyv", "udm", "ug",  "uga", "uk",  "umb", "und", "ur",
-                "uz",  "vai", "ve",  "vi",  "vo",  "vot", "wa",  "wak",
-                "wal", "war", "was", "wen", "wo",  "xal", "xh",  "yao", "yap",
-                "yi",  "yo",  "ypk", "za",  "zap", "zen", "zh",  "znd",
-                "zu",  "zun",
-            };
-
-            String[] tempReplacementLanguages = {
-                "id", "he", "yi", "jv", "sr", "nb",/* replacement language codes */
-            };
-
-            String[] tempObsoleteLanguages = {
-                "in", "iw", "ji", "jw", "sh", "no",    /* obsolete language codes */
-            };
-
-            /* This list MUST contain a three-letter code for every two-letter code in the
-               list above, and they MUST ne in the same order (i.e., the same language must
-               be in the same place in both lists)! */
-            String[] tempLanguages3 = {
-                /*"aa",  "ab",  "ace", "ach", "ada", "ady", "ae",  "af",  "afa",    */
-                "aar", "abk", "ace", "ach", "ada", "ady", "ave", "afr", "afa",
-                /*"afh", "ak",  "akk", "ale", "alg", "am",  "an",  "ang", "apa",    */
-                "afh", "aka", "akk", "ale", "alg", "amh", "arg", "ang", "apa",
-                /*"ar",  "arc", "arn", "arp", "art", "arw", "as",  "ast",    */
-                "ara", "arc", "arn", "arp", "art", "arw", "asm", "ast",
-                /*"ath", "aus", "av",  "awa", "ay",  "az",  "ba",  "bad",    */
-                "ath", "aus", "ava", "awa", "aym", "aze", "bak", "bad",
-                /*"bai", "bal", "ban", "bas", "bat", "be",  "bej",    */
-                "bai", "bal", "ban", "bas", "bat", "bel", "bej",
-                /*"bem", "ber", "bg",  "bh",  "bho", "bi",  "bik", "bin",    */
-                "bem", "ber", "bul", "bih", "bho", "bis", "bik", "bin",
-                /*"bla", "bm",  "bn",  "bnt", "bo",  "br",  "bra", "bs",     */
-                "bla", "bam",  "ben", "bnt", "bod", "bre", "bra", "bos",
-                /*"btk", "bua", "bug", "byn", "ca",  "cad", "cai", "car", "cau",    */
-                "btk", "bua", "bug", "byn", "cat", "cad", "cai", "car", "cau",
-                /*"ce",  "ceb", "cel", "ch",  "chb", "chg", "chk", "chm",    */
-                "che", "ceb", "cel", "cha", "chb", "chg", "chk", "chm",
-                /*"chn", "cho", "chp", "chr", "chy", "cmc", "co",  "cop",    */
-                "chn", "cho", "chp", "chr", "chy", "cmc", "cos", "cop",
-                /*"cpe", "cpf", "cpp", "cr",  "crh", "crp", "cs",  "csb", "cu",  "cus",    */
-                "cpe", "cpf", "cpp", "cre", "crh", "crp", "ces", "csb", "chu", "cus",
-                /*"cv",  "cy",  "da",  "dak", "dar", "day", "de",  "del", "den",    */
-                "chv", "cym", "dan", "dak", "dar", "day", "deu", "del", "den",
-                /*"dgr", "din", "doi", "dra", "dsb", "dua", "dum", "dv",  "dyu",    */
-                "dgr", "din", "doi", "dra", "dsb", "dua", "dum", "div", "dyu",
-                /*"dz",  "ee",  "efi", "egy", "eka", "el",  "elx", "en",     */
-                "dzo", "ewe", "efi", "egy", "eka", "ell", "elx", "eng",
-                /*"enm", "eo",  "es",  "et",  "eu",  "ewo", "fa",     */
-                "enm", "epo", "spa", "est", "eus", "ewo", "fas",
-                /*"fan", "fat", "ff",  "fi",  "fiu", "fj",  "fo",  "fon",    */
-                "fan", "fat", "ful", "fin", "fiu", "fij", "fao", "fon",
-                /*"fr",  "frm", "fro", "fur", "fy",  "ga",  "gaa", "gay",    */
-                "fra", "frm", "fro", "fur", "fry", "gle", "gaa", "gay",
-                /*"gba", "gd",  "gem", "gez", "gil", "gl",  "gmh", "gn",     */
-                "gba", "gla", "gem", "gez", "gil", "glg", "gmh", "grn",
-                /*"goh", "gon", "gor", "got", "grb", "grc", "gu",  "gv",     */
-                "goh", "gon", "gor", "got", "grb", "grc", "guj", "glv",
-                /*"gwi", "ha",  "hai", "haw", "he",  "hi",  "hil", "him",    */
-                "gwi", "hau", "hai", "haw", "heb", "hin", "hil", "him",
-                /*"hit", "hmn", "ho",  "hr",  "hsb", "ht",  "hu",  "hup", "hy",  "hz",     */
-                "hit", "hmn", "hmo", "hrv", "hsb", "hat", "hun", "hup", "hye", "her",
-                /*"ia",  "iba", "id",  "ie",  "ig",  "ii",  "ijo", "ik",     */
-                "ina", "iba", "ind", "ile", "ibo", "iii", "ijo", "ipk",
-                /*"ilo", "inc", "ine", "inh", "io",  "ira", "iro", "is",  "it",      */
-                "ilo", "inc", "ine", "inh", "ido", "ira", "iro", "isl", "ita",
-                /*"iu",  "ja",  "jbo", "jpr", "jrb", "jv",  "ka",  "kaa", "kab",   */
-                "iku", "jpn", "jbo", "jpr", "jrb", "jaw", "kat", "kaa", "kab",
-                /*"kac", "kam", "kar", "kaw", "kbd", "kg",  "kha", "khi",    */
-                "kac", "kam", "kar", "kaw", "kbd", "kon", "kha", "khi",
-                /*"kho", "ki",  "kj",  "kk",  "kl",  "km",  "kmb", "kn",     */
-                "kho", "kik", "kua", "kaz", "kal", "khm", "kmb", "kan",
-                /*"ko",  "kok", "kos", "kpe", "kr",  "krc", "kro", "kru", "ks",     */
-                "kor", "kok", "kos", "kpe", "kau", "krc", "kro", "kru", "kas",
-                /*"ku",  "kum", "kut", "kv",  "kw",  "ky",  "la",  "lad",    */
-                "kur", "kum", "kut", "kom", "cor", "kir", "lat", "lad",
-                /*"lah", "lam", "lb",  "lez", "lg",  "li",  "ln",  "lo",  "lol",    */
-                "lah", "lam", "ltz", "lez", "lug", "lim", "lin", "lao", "lol",
-                /*"loz", "lt",  "lu",  "lua", "lui", "lun", "luo", "lus",    */
-                "loz", "lit", "lub", "lua", "lui", "lun", "luo", "lus",
-                /*"lv",  "mad", "mag", "mai", "mak", "man", "map", "mas",    */
-                "lav", "mad", "mag", "mai", "mak", "man", "map", "mas",
-                /*"mdf", "mdr", "men", "mg",  "mga", "mh",  "mi",  "mic", "min",    */
-                "mdf", "mdr", "men", "mlg", "mga", "mah", "mri", "mic", "min",
-                /*"mis", "mk",  "mkh", "ml",  "mn",  "mnc", "mni", "mno",    */
-                "mis", "mkd", "mkh", "mal", "mon", "mnc", "mni", "mno",
-                /*"mo",  "moh", "mos", "mr",  "ms",  "mt",  "mul", "mun",    */
-                "mol", "moh", "mos", "mar", "msa", "mlt", "mul", "mun",
-                /*"mus", "mwr", "my",  "myn", "myv", "na",  "nah", "nai", "nap",    */
-                "mus", "mwr", "mya", "myn", "myv", "nau", "nah", "nai", "nap",
-                /*"nb",  "nd",  "nds", "ne",  "new", "ng",  "nia", "nic",    */
-                "nob", "nde", "nds", "nep", "new", "ndo", "nia", "nic",
-                /*"niu", "nl",  "nn",  "no",  "nog", "non", "nr",  "nso", "nub",    */
-                "niu", "nld", "nno", "nor", "nog", "non", "nbl", "nso", "nub",
-                /*"nv",  "nwc", "ny",  "nym", "nyn", "nyo", "nzi", "oc",  "oj",     */
-                "nav", "nwc", "nya", "nym", "nyn", "nyo", "nzi", "oci", "oji",
-                /*"om",  "or",  "os",  "osa", "ota", "oto", "pa",  "paa",    */
-                "orm", "ori", "oss", "osa", "ota", "oto", "pan", "paa",
-                /*"pag", "pal", "pam", "pap", "pau", "peo", "phi", "phn",    */
-                "pag", "pal", "pam", "pap", "pau", "peo", "phi", "phn",
-                /*"pi",  "pl",  "pon", "pra", "pro", "ps",  "pt",  "qu",     */
-                "pli", "pol", "pon", "pra", "pro", "pus", "por", "que",
-                /*"raj", "rap", "rar", "rm",  "rn",  "ro",  "roa", "rom",    */
-                "raj", "rap", "rar", "roh", "run", "ron", "roa", "rom",
-                /*"ru",  "rup", "rw",  "sa",  "sad", "sah", "sai", "sal", "sam",    */
-                "rus", "rup", "kin", "san", "sad", "sah", "sai", "sal", "sam",
-                /*"sas", "sat", "sc",  "sco", "sd",  "se",  "sel", "sem",    */
-                "sas", "sat", "srd", "sco", "snd", "sme", "sel", "sem",
-                /*"sg",  "sga", "sgn", "shn", "si",  "sid", "sio", "sit",    */
-                "sag", "sga", "sgn", "shn", "sin", "sid", "sio", "sit",
-                /*"sk",  "sl",  "sla", "sm",  "sma", "smi", "smj", "smn",    */
-                "slk", "slv", "sla", "smo", "sma", "smi", "smj", "smn",
-                /*"sms", "sn",  "snk", "so",  "sog", "son", "sq",  "sr",     */
-                "sms", "sna", "snk", "som", "sog", "son", "sqi", "srp",
-                /*"srr", "ss",  "ssa", "st",  "su",  "suk", "sus", "sux",    */
-                "srr", "ssw", "ssa", "sot", "sun", "suk", "sus", "sux",
-                /*"sv",  "sw",  "syr", "ta",  "tai", "te",  "tem", "ter",    */
-                "swe", "swa", "syr", "tam", "tai", "tel", "tem", "ter",
-                /*"tet", "tg",  "th",  "ti",  "tig", "tiv", "tk",  "tkl",    */
-                "tet", "tgk", "tha", "tir", "tig", "tiv", "tuk", "tkl",
-                /*"tl",  "tlh", "tli", "tmh", "tn",  "to",  "tog", "tpi", "tr",     */
-                "tgl", "tlh", "tli", "tmh", "tsn", "ton", "tog", "tpi", "tur",
-                /*"ts",  "tsi", "tt",  "tum", "tup", "tut", "tvl", "tw",     */
-                "tso", "tsi", "tat", "tum", "tup", "tut", "tvl", "twi",
-                /*"ty",  "tyv", "udm", "ug",  "uga", "uk",  "umb", "und", "ur",     */
-                "tah", "tyv", "udm", "uig", "uga", "ukr", "umb", "und", "urd",
-                /*"uz",  "vai", "ve",  "vi",  "vo",  "vot", "wa",  "wak",    */
-                "uzb", "vai", "ven", "vie", "vol", "vot", "wln", "wak",
-                /*"wal", "war", "was", "wen", "wo",  "xal", "xh",  "yao", "yap",    */
-                "wal", "war", "was", "wen", "wol", "xal", "xho", "yao", "yap",
-                /*"yi",  "yo",  "ypk", "za",  "zap", "zen", "zh",  "znd",    */
-                "yid", "yor", "ypk", "zha", "zap", "zen", "zho", "znd",
-                /*"zu",  "zun",                                              */
-                "zul", "zun",
-            };
-
-            String[] tempObsoleteLanguages3 = {
-                /* "in",  "iw",  "ji",  "jw",  "sh", */
-                "ind", "heb", "yid", "jaw", "srp",
-            };
-
-            synchronized (ULocale.class) {
-                if (_languages == null) {
-                    _languages = tempLanguages;
-                    _replacementLanguages = tempReplacementLanguages;
-                    _obsoleteLanguages = tempObsoleteLanguages;
-                    _languages3 = tempLanguages3;
-                    _obsoleteLanguages3 = tempObsoleteLanguages3;
-                }
-            }
-        }
-    }
-
-    private static String[] _countries;
-    private static String[] _deprecatedCountries;
-    private static String[] _replacementCountries;
-    private static String[] _obsoleteCountries;
-    private static String[] _countries3;
-    private static String[] _obsoleteCountries3;
-
-    // Avoid initializing country tables unless we have to.
-    private static void initCountryTables() {
-        if (_countries == null) {
-            /* ZR(ZAR) is now CD(COD) and FX(FXX) is PS(PSE) as per
-               http://www.evertype.com/standards/iso3166/iso3166-1-en.html
-               added new codes keeping the old ones for compatibility
-               updated to include 1999/12/03 revisions *CWB*/
-
-            /* RO(ROM) is now RO(ROU) according to
-               http://www.iso.org/iso/en/prods-services/iso3166ma/03updates-on-iso-3166/nlv3e-rou.html
-            */
-
-            /* 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",  "AX",  "AZ",
-                "BA",  "BB",  "BD",  "BE",  "BF",  "BG",  "BH",  "BI",
-                "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",  "GG",  "GH",  "GI",  "GL",
-                "GM",  "GN",  "GP",  "GQ",  "GR",  "GS",  "GT",  "GU",
-                "GW",  "GY",  "HK",  "HM",  "HN",  "HR",  "HT",  "HU",
-                "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",  "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",  "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",  "ZA",  "ZM",  "ZW",
-            };
-
-            /* this table is used for 3 letter codes */
-            String[] tempObsoleteCountries = {
-                "FX",  "CS",  "RO",  "TP",  "YU",  "ZR",  /* obsolete country codes */
-            };
-
-            String[] tempDeprecatedCountries = {
-               "BU", "CS", "DY", "FX", "HV", "NH", "RH", "TP", "YU", "ZR" /* deprecated country list */
-            };
-            String[] tempReplacementCountries = {
-           /*  "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",  "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",  "CS",  "RO",  "TP",  "YU",  "ZR",   */
-                "FXX", "SCG", "ROM", "TMP", "YUG", "ZAR",
-            };
-
-            synchronized (ULocale.class) {
-                if (_countries == null) {
-                    _countries = tempCountries;
-                    _deprecatedCountries = tempDeprecatedCountries;
-                    _replacementCountries = tempReplacementCountries;
-                    _obsoleteCountries = tempObsoleteCountries;
-                    _countries3 = tempCountries3;
-                    _obsoleteCountries3 = tempObsoleteCountries3;
-                }
-            }
-        }
-    }
-
-    public static String getCurrentCountryID(String oldID){
-        initCountryTables();
-        int offset = findIndex(_deprecatedCountries, oldID);
-        if (offset >= 0) {
-            return _replacementCountries[offset];
-        }
-        return oldID;
-    }
-
-    public static String getCurrentLanguageID(String oldID){
-        initLanguageTables();
-        int offset = findIndex(_obsoleteLanguages, oldID);
-        if (offset >= 0) {
-            return _replacementLanguages[offset];
-        }
-        return oldID;
-    }
-
-
-}
+/*
+ *******************************************************************************
+ * Copyright (C) 2009-2011, International Business Machines Corporation and    *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+package com.ibm.icu.impl;
+
+import java.util.MissingResourceException;
+
+import com.ibm.icu.util.ULocale;
+
+
+/**
+ * Utilities for mapping between old and new language, country, and other
+ * locale ID related names.
+ */
+public class LocaleIDs {
+
+    /**
+     * Returns a list of all 2-letter country codes defined in ISO 3166.
+     * Can be used to create Locales.
+     * @stable ICU 3.0
+     */
+    public static String[] getISOCountries() {
+        initCountryTables();
+        return _countries.clone();
+    }
+
+    /**
+     * Returns a list of all 2-letter language codes defined in ISO 639.
+     * Can be used to create Locales.
+     * [NOTE:  ISO 639 is not a stable standard-- some languages' codes have changed.
+     * The list this function returns includes both the new and the old codes for the
+     * languages whose codes have changed.]
+     * @stable ICU 3.0
+     */
+    public static String[] getISOLanguages() {
+        initLanguageTables();
+        return _languages.clone();
+    }
+
+    /**
+     * Returns a three-letter abbreviation for the provided country.  If the provided
+     * country is empty, returns the empty string.  Otherwise, returns
+     * an uppercase ISO 3166 3-letter country code.
+     * @exception MissingResourceException Throws MissingResourceException if the
+     * three-letter country abbreviation is not available for this locale.
+     * @stable ICU 3.0
+     */
+    public static String getISO3Country(String country){
+        initCountryTables();
+
+        int offset = findIndex(_countries, country);
+        if(offset>=0){
+            return _countries3[offset];
+        }else{
+            offset = findIndex(_obsoleteCountries, country);
+            if(offset>=0){
+                return _obsoleteCountries3[offset];
+            }
+        }
+        return "";
+    }
+    /**
+     * Returns a three-letter abbreviation for the language.  If language is
+     * empty, returns the empty string.  Otherwise, returns
+     * a lowercase ISO 639-2/T language code.
+     * The ISO 639-2 language codes can be found on-line at
+     *   <a href="ftp://dkuug.dk/i18n/iso-639-2.txt"><code>ftp://dkuug.dk/i18n/iso-639-2.txt</code></a>
+     * @exception MissingResourceException Throws MissingResourceException if the
+     * three-letter language abbreviation is not available for this locale.
+     * @stable ICU 3.0
+     */
+    public static String getISO3Language(String language) {
+        initLanguageTables();
+
+        int offset = findIndex(_languages, language);
+        if(offset>=0){
+            return _languages3[offset];
+        } else {
+            offset = findIndex(_obsoleteLanguages, language);
+            if (offset >= 0) {
+                return _obsoleteLanguages3[offset];
+            }
+        }
+        return "";
+    }
+
+    public static String threeToTwoLetterLanguage(String lang) {
+        initLanguageTables();
+
+        /* convert 3 character code to 2 character code if possible *CWB*/
+        int offset = findIndex(_languages3, lang);
+        if (offset >= 0) {
+            return _languages[offset];
+        }
+
+        offset = findIndex(_obsoleteLanguages3, lang);
+        if (offset >= 0) {
+            return _obsoleteLanguages[offset];
+        }
+
+        return null;
+    }
+
+    public static String threeToTwoLetterRegion(String region) {
+        initCountryTables();
+
+        /* convert 3 character code to 2 character code if possible *CWB*/
+        int offset = findIndex(_countries3, region);
+        if (offset >= 0) {
+            return _countries[offset];
+        }
+
+        offset = findIndex(_obsoleteCountries3, region);
+        if (offset >= 0) {
+            return _obsoleteCountries[offset];
+        }
+
+        return null;
+    }
+
+    /**
+     * linear search of the string array. the arrays are unfortunately ordered by the
+     * two-letter target code, not the three-letter search code, which seems backwards.
+     */
+    private static int findIndex(String[] array, String target){
+        for (int i = 0; i < array.length; i++) {
+            if (target.equals(array[i])) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+
+    /**
+     * Tables used in normalizing portions of the id.
+     */
+    /* tables updated per http://lcweb.loc.gov/standards/iso639-2/
+       to include the revisions up to 2001/7/27 *CWB*/
+    /* The 3 character codes are the terminology codes like RFC 3066.
+       This is compatible with prior ICU codes */
+    /* "in" "iw" "ji" "jw" & "sh" have been withdrawn but are still in
+       the table but now at the end of the table because
+       3 character codes are duplicates.  This avoids bad searches
+       going from 3 to 2 character codes.*/
+    /* The range qaa-qtz is reserved for local use. */
+
+    private static String[] _languages;
+    private static String[] _replacementLanguages;
+    private static String[] _obsoleteLanguages;
+    private static String[] _languages3;
+    private static String[] _obsoleteLanguages3;
+
+    // Avoid initializing languages tables unless we have to.
+    private static void initLanguageTables() {
+        if (_languages == null) {
+
+            /* This list MUST be in sorted order, and MUST contain the two-letter codes
+               if one exists otherwise use the three letter code */
+            String[] tempLanguages = {
+                "aa",  "ab",  "ace", "ach", "ada", "ady", "ae",  "af",  "afa",
+                "afh", "ak",  "akk", "ale", "alg", "am",  "an",  "ang", "apa",
+                "ar",  "arc", "arn", "arp", "art", "arw", "as",  "ast",
+                "ath", "aus", "av",  "awa", "ay",  "az",  "ba",  "bad",
+                "bai", "bal", "ban", "bas", "bat", "be",  "bej",
+                "bem", "ber", "bg",  "bh",  "bho", "bi",  "bik", "bin",
+                "bla", "bm",  "bn",  "bnt", "bo",  "br",  "bra", "bs",
+                "btk", "bua", "bug", "byn", "ca",  "cad", "cai", "car", "cau",
+                "ce",  "ceb", "cel", "ch",  "chb", "chg", "chk", "chm",
+                "chn", "cho", "chp", "chr", "chy", "cmc", "co",  "cop",
+                "cpe", "cpf", "cpp", "cr",  "crh", "crp", "cs",  "csb", "cu",  "cus",
+                "cv",  "cy",  "da",  "dak", "dar", "day", "de",  "del", "den",
+                "dgr", "din", "doi", "dra", "dsb", "dua", "dum", "dv",  "dyu",
+                "dz",  "ee",  "efi", "egy", "eka", "el",  "elx", "en",
+                "enm", "eo",  "es",  "et",  "eu",  "ewo", "fa",
+                "fan", "fat", "ff",  "fi",  "fiu", "fj",  "fo",  "fon",
+                "fr",  "frm", "fro", "fur", "fy",  "ga",  "gaa", "gay",
+                "gba", "gd",  "gem", "gez", "gil", "gl",  "gmh", "gn",
+                "goh", "gon", "gor", "got", "grb", "grc", "gu",  "gv",
+                "gwi", "ha",  "hai", "haw", "he",  "hi",  "hil", "him",
+                "hit", "hmn", "ho",  "hr",  "hsb", "ht",  "hu",  "hup", "hy",  "hz",
+                "ia",  "iba", "id",  "ie",  "ig",  "ii",  "ijo", "ik",
+                "ilo", "inc", "ine", "inh", "io",  "ira", "iro", "is",  "it",
+                "iu",  "ja",  "jbo", "jpr", "jrb", "jv",  "ka",  "kaa", "kab",
+                "kac", "kam", "kar", "kaw", "kbd", "kg",  "kha", "khi",
+                "kho", "ki",  "kj",  "kk",  "kl",  "km",  "kmb", "kn",
+                "ko",  "kok", "kos", "kpe", "kr",  "krc", "kro", "kru", "ks",
+                "ku",  "kum", "kut", "kv",  "kw",  "ky",  "la",  "lad",
+                "lah", "lam", "lb",  "lez", "lg",  "li",  "ln",  "lo",  "lol",
+                "loz", "lt",  "lu",  "lua", "lui", "lun", "luo", "lus",
+                "lv",  "mad", "mag", "mai", "mak", "man", "map", "mas",
+                "mdf", "mdr", "men", "mg",  "mga", "mh",  "mi",  "mic", "min",
+                "mis", "mk",  "mkh", "ml",  "mn",  "mnc", "mni", "mno",
+                "mo",  "moh", "mos", "mr",  "ms",  "mt",  "mul", "mun",
+                "mus", "mwr", "my",  "myn", "myv", "na",  "nah", "nai", "nap",
+                "nb",  "nd",  "nds", "ne",  "new", "ng",  "nia", "nic",
+                "niu", "nl",  "nn",  "no",  "nog", "non", "nr",  "nso", "nub",
+                "nv",  "nwc", "ny",  "nym", "nyn", "nyo", "nzi", "oc",  "oj",
+                "om",  "or",  "os",  "osa", "ota", "oto", "pa",  "paa",
+                "pag", "pal", "pam", "pap", "pau", "peo", "phi", "phn",
+                "pi",  "pl",  "pon", "pra", "pro", "ps",  "pt",  "qu",
+                "raj", "rap", "rar", "rm",  "rn",  "ro",  "roa", "rom",
+                "ru",  "rup", "rw",  "sa",  "sad", "sah", "sai", "sal", "sam",
+                "sas", "sat", "sc",  "sco", "sd",  "se",  "sel", "sem",
+                "sg",  "sga", "sgn", "shn", "si",  "sid", "sio", "sit",
+                "sk",  "sl",  "sla", "sm",  "sma", "smi", "smj", "smn",
+                "sms", "sn",  "snk", "so",  "sog", "son", "sq",  "sr",
+                "srr", "ss",  "ssa", "st",  "su",  "suk", "sus", "sux",
+                "sv",  "sw",  "syr", "ta",  "tai", "te",  "tem", "ter",
+                "tet", "tg",  "th",  "ti",  "tig", "tiv", "tk",  "tkl",
+                "tl",  "tlh", "tli", "tmh", "tn",  "to",  "tog", "tpi", "tr",
+                "ts",  "tsi", "tt",  "tum", "tup", "tut", "tvl", "tw",
+                "ty",  "tyv", "udm", "ug",  "uga", "uk",  "umb", "und", "ur",
+                "uz",  "vai", "ve",  "vi",  "vo",  "vot", "wa",  "wak",
+                "wal", "war", "was", "wen", "wo",  "xal", "xh",  "yao", "yap",
+                "yi",  "yo",  "ypk", "za",  "zap", "zen", "zh",  "znd",
+                "zu",  "zun",
+            };
+
+            String[] tempReplacementLanguages = {
+                "id", "he", "yi", "jv", "sr", "nb",/* replacement language codes */
+            };
+
+            String[] tempObsoleteLanguages = {
+                "in", "iw", "ji", "jw", "sh", "no",    /* obsolete language codes */
+            };
+
+            /* This list MUST contain a three-letter code for every two-letter code in the
+               list above, and they MUST ne in the same order (i.e., the same language must
+               be in the same place in both lists)! */
+            String[] tempLanguages3 = {
+                /*"aa",  "ab",  "ace", "ach", "ada", "ady", "ae",  "af",  "afa",    */
+                "aar", "abk", "ace", "ach", "ada", "ady", "ave", "afr", "afa",
+                /*"afh", "ak",  "akk", "ale", "alg", "am",  "an",  "ang", "apa",    */
+                "afh", "aka", "akk", "ale", "alg", "amh", "arg", "ang", "apa",
+                /*"ar",  "arc", "arn", "arp", "art", "arw", "as",  "ast",    */
+                "ara", "arc", "arn", "arp", "art", "arw", "asm", "ast",
+                /*"ath", "aus", "av",  "awa", "ay",  "az",  "ba",  "bad",    */
+                "ath", "aus", "ava", "awa", "aym", "aze", "bak", "bad",
+                /*"bai", "bal", "ban", "bas", "bat", "be",  "bej",    */
+                "bai", "bal", "ban", "bas", "bat", "bel", "bej",
+                /*"bem", "ber", "bg",  "bh",  "bho", "bi",  "bik", "bin",    */
+                "bem", "ber", "bul", "bih", "bho", "bis", "bik", "bin",
+                /*"bla", "bm",  "bn",  "bnt", "bo",  "br",  "bra", "bs",     */
+                "bla", "bam",  "ben", "bnt", "bod", "bre", "bra", "bos",
+                /*"btk", "bua", "bug", "byn", "ca",  "cad", "cai", "car", "cau",    */
+                "btk", "bua", "bug", "byn", "cat", "cad", "cai", "car", "cau",
+                /*"ce",  "ceb", "cel", "ch",  "chb", "chg", "chk", "chm",    */
+                "che", "ceb", "cel", "cha", "chb", "chg", "chk", "chm",
+                /*"chn", "cho", "chp", "chr", "chy", "cmc", "co",  "cop",    */
+                "chn", "cho", "chp", "chr", "chy", "cmc", "cos", "cop",
+                /*"cpe", "cpf", "cpp", "cr",  "crh", "crp", "cs",  "csb", "cu",  "cus",    */
+                "cpe", "cpf", "cpp", "cre", "crh", "crp", "ces", "csb", "chu", "cus",
+                /*"cv",  "cy",  "da",  "dak", "dar", "day", "de",  "del", "den",    */
+                "chv", "cym", "dan", "dak", "dar", "day", "deu", "del", "den",
+                /*"dgr", "din", "doi", "dra", "dsb", "dua", "dum", "dv",  "dyu",    */
+                "dgr", "din", "doi", "dra", "dsb", "dua", "dum", "div", "dyu",
+                /*"dz",  "ee",  "efi", "egy", "eka", "el",  "elx", "en",     */
+                "dzo", "ewe", "efi", "egy", "eka", "ell", "elx", "eng",
+                /*"enm", "eo",  "es",  "et",  "eu",  "ewo", "fa",     */
+                "enm", "epo", "spa", "est", "eus", "ewo", "fas",
+                /*"fan", "fat", "ff",  "fi",  "fiu", "fj",  "fo",  "fon",    */
+                "fan", "fat", "ful", "fin", "fiu", "fij", "fao", "fon",
+                /*"fr",  "frm", "fro", "fur", "fy",  "ga",  "gaa", "gay",    */
+                "fra", "frm", "fro", "fur", "fry", "gle", "gaa", "gay",
+                /*"gba", "gd",  "gem", "gez", "gil", "gl",  "gmh", "gn",     */
+                "gba", "gla", "gem", "gez", "gil", "glg", "gmh", "grn",
+                /*"goh", "gon", "gor", "got", "grb", "grc", "gu",  "gv",     */
+                "goh", "gon", "gor", "got", "grb", "grc", "guj", "glv",
+                /*"gwi", "ha",  "hai", "haw", "he",  "hi",  "hil", "him",    */
+                "gwi", "hau", "hai", "haw", "heb", "hin", "hil", "him",
+                /*"hit", "hmn", "ho",  "hr",  "hsb", "ht",  "hu",  "hup", "hy",  "hz",     */
+                "hit", "hmn", "hmo", "hrv", "hsb", "hat", "hun", "hup", "hye", "her",
+                /*"ia",  "iba", "id",  "ie",  "ig",  "ii",  "ijo", "ik",     */
+                "ina", "iba", "ind", "ile", "ibo", "iii", "ijo", "ipk",
+                /*"ilo", "inc", "ine", "inh", "io",  "ira", "iro", "is",  "it",      */
+                "ilo", "inc", "ine", "inh", "ido", "ira", "iro", "isl", "ita",
+                /*"iu",  "ja",  "jbo", "jpr", "jrb", "jv",  "ka",  "kaa", "kab",   */
+                "iku", "jpn", "jbo", "jpr", "jrb", "jaw", "kat", "kaa", "kab",
+                /*"kac", "kam", "kar", "kaw", "kbd", "kg",  "kha", "khi",    */
+                "kac", "kam", "kar", "kaw", "kbd", "kon", "kha", "khi",
+                /*"kho", "ki",  "kj",  "kk",  "kl",  "km",  "kmb", "kn",     */
+                "kho", "kik", "kua", "kaz", "kal", "khm", "kmb", "kan",
+                /*"ko",  "kok", "kos", "kpe", "kr",  "krc", "kro", "kru", "ks",     */
+                "kor", "kok", "kos", "kpe", "kau", "krc", "kro", "kru", "kas",
+                /*"ku",  "kum", "kut", "kv",  "kw",  "ky",  "la",  "lad",    */
+                "kur", "kum", "kut", "kom", "cor", "kir", "lat", "lad",
+                /*"lah", "lam", "lb",  "lez", "lg",  "li",  "ln",  "lo",  "lol",    */
+                "lah", "lam", "ltz", "lez", "lug", "lim", "lin", "lao", "lol",
+                /*"loz", "lt",  "lu",  "lua", "lui", "lun", "luo", "lus",    */
+                "loz", "lit", "lub", "lua", "lui", "lun", "luo", "lus",
+                /*"lv",  "mad", "mag", "mai", "mak", "man", "map", "mas",    */
+                "lav", "mad", "mag", "mai", "mak", "man", "map", "mas",
+                /*"mdf", "mdr", "men", "mg",  "mga", "mh",  "mi",  "mic", "min",    */
+                "mdf", "mdr", "men", "mlg", "mga", "mah", "mri", "mic", "min",
+                /*"mis", "mk",  "mkh", "ml",  "mn",  "mnc", "mni", "mno",    */
+                "mis", "mkd", "mkh", "mal", "mon", "mnc", "mni", "mno",
+                /*"mo",  "moh", "mos", "mr",  "ms",  "mt",  "mul", "mun",    */
+                "mol", "moh", "mos", "mar", "msa", "mlt", "mul", "mun",
+                /*"mus", "mwr", "my",  "myn", "myv", "na",  "nah", "nai", "nap",    */
+                "mus", "mwr", "mya", "myn", "myv", "nau", "nah", "nai", "nap",
+                /*"nb",  "nd",  "nds", "ne",  "new", "ng",  "nia", "nic",    */
+                "nob", "nde", "nds", "nep", "new", "ndo", "nia", "nic",
+                /*"niu", "nl",  "nn",  "no",  "nog", "non", "nr",  "nso", "nub",    */
+                "niu", "nld", "nno", "nor", "nog", "non", "nbl", "nso", "nub",
+                /*"nv",  "nwc", "ny",  "nym", "nyn", "nyo", "nzi", "oc",  "oj",     */
+                "nav", "nwc", "nya", "nym", "nyn", "nyo", "nzi", "oci", "oji",
+                /*"om",  "or",  "os",  "osa", "ota", "oto", "pa",  "paa",    */
+                "orm", "ori", "oss", "osa", "ota", "oto", "pan", "paa",
+                /*"pag", "pal", "pam", "pap", "pau", "peo", "phi", "phn",    */
+                "pag", "pal", "pam", "pap", "pau", "peo", "phi", "phn",
+                /*"pi",  "pl",  "pon", "pra", "pro", "ps",  "pt",  "qu",     */
+                "pli", "pol", "pon", "pra", "pro", "pus", "por", "que",
+                /*"raj", "rap", "rar", "rm",  "rn",  "ro",  "roa", "rom",    */
+                "raj", "rap", "rar", "roh", "run", "ron", "roa", "rom",
+                /*"ru",  "rup", "rw",  "sa",  "sad", "sah", "sai", "sal", "sam",    */
+                "rus", "rup", "kin", "san", "sad", "sah", "sai", "sal", "sam",
+                /*"sas", "sat", "sc",  "sco", "sd",  "se",  "sel", "sem",    */
+                "sas", "sat", "srd", "sco", "snd", "sme", "sel", "sem",
+                /*"sg",  "sga", "sgn", "shn", "si",  "sid", "sio", "sit",    */
+                "sag", "sga", "sgn", "shn", "sin", "sid", "sio", "sit",
+                /*"sk",  "sl",  "sla", "sm",  "sma", "smi", "smj", "smn",    */
+                "slk", "slv", "sla", "smo", "sma", "smi", "smj", "smn",
+                /*"sms", "sn",  "snk", "so",  "sog", "son", "sq",  "sr",     */
+                "sms", "sna", "snk", "som", "sog", "son", "sqi", "srp",
+                /*"srr", "ss",  "ssa", "st",  "su",  "suk", "sus", "sux",    */
+                "srr", "ssw", "ssa", "sot", "sun", "suk", "sus", "sux",
+                /*"sv",  "sw",  "syr", "ta",  "tai", "te",  "tem", "ter",    */
+                "swe", "swa", "syr", "tam", "tai", "tel", "tem", "ter",
+                /*"tet", "tg",  "th",  "ti",  "tig", "tiv", "tk",  "tkl",    */
+                "tet", "tgk", "tha", "tir", "tig", "tiv", "tuk", "tkl",
+                /*"tl",  "tlh", "tli", "tmh", "tn",  "to",  "tog", "tpi", "tr",     */
+                "tgl", "tlh", "tli", "tmh", "tsn", "ton", "tog", "tpi", "tur",
+                /*"ts",  "tsi", "tt",  "tum", "tup", "tut", "tvl", "tw",     */
+                "tso", "tsi", "tat", "tum", "tup", "tut", "tvl", "twi",
+                /*"ty",  "tyv", "udm", "ug",  "uga", "uk",  "umb", "und", "ur",     */
+                "tah", "tyv", "udm", "uig", "uga", "ukr", "umb", "und", "urd",
+                /*"uz",  "vai", "ve",  "vi",  "vo",  "vot", "wa",  "wak",    */
+                "uzb", "vai", "ven", "vie", "vol", "vot", "wln", "wak",
+                /*"wal", "war", "was", "wen", "wo",  "xal", "xh",  "yao", "yap",    */
+                "wal", "war", "was", "wen", "wol", "xal", "xho", "yao", "yap",
+                /*"yi",  "yo",  "ypk", "za",  "zap", "zen", "zh",  "znd",    */
+                "yid", "yor", "ypk", "zha", "zap", "zen", "zho", "znd",
+                /*"zu",  "zun",                                              */
+                "zul", "zun",
+            };
+
+            String[] tempObsoleteLanguages3 = {
+                /* "in",  "iw",  "ji",  "jw",  "sh", */
+                "ind", "heb", "yid", "jaw", "srp",
+            };
+
+            synchronized (ULocale.class) {
+                if (_languages == null) {
+                    _languages = tempLanguages;
+                    _replacementLanguages = tempReplacementLanguages;
+                    _obsoleteLanguages = tempObsoleteLanguages;
+                    _languages3 = tempLanguages3;
+                    _obsoleteLanguages3 = tempObsoleteLanguages3;
+                }
+            }
+        }
+    }
+
+    private static String[] _countries;
+    private static String[] _deprecatedCountries;
+    private static String[] _replacementCountries;
+    private static String[] _obsoleteCountries;
+    private static String[] _countries3;
+    private static String[] _obsoleteCountries3;
+
+    // Avoid initializing country tables unless we have to.
+    private static void initCountryTables() {
+        if (_countries == null) {
+            /* ZR(ZAR) is now CD(COD) and FX(FXX) is PS(PSE) as per
+               http://www.evertype.com/standards/iso3166/iso3166-1-en.html
+               added new codes keeping the old ones for compatibility
+               updated to include 1999/12/03 revisions *CWB*/
+
+            /* RO(ROM) is now RO(ROU) according to
+               http://www.iso.org/iso/en/prods-services/iso3166ma/03updates-on-iso-3166/nlv3e-rou.html
+            */
+
+            /* 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",  "AX",  "AZ",
+                "BA",  "BB",  "BD",  "BE",  "BF",  "BG",  "BH",  "BI",
+                "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",  "GG",  "GH",  "GI",  "GL",
+                "GM",  "GN",  "GP",  "GQ",  "GR",  "GS",  "GT",  "GU",
+                "GW",  "GY",  "HK",  "HM",  "HN",  "HR",  "HT",  "HU",
+                "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",  "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",  "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",  "ZA",  "ZM",  "ZW",
+            };
+
+            /* this table is used for 3 letter codes */
+            String[] tempObsoleteCountries = {
+                "FX",  "CS",  "RO",  "TP",  "YU",  "ZR",  /* obsolete country codes */
+            };
+
+            String[] tempDeprecatedCountries = {
+               "BU", "CS", "DY", "FX", "HV", "NH", "RH", "TP", "YU", "ZR" /* deprecated country list */
+            };
+            String[] tempReplacementCountries = {
+           /*  "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",  "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",  "CS",  "RO",  "TP",  "YU",  "ZR",   */
+                "FXX", "SCG", "ROM", "TMP", "YUG", "ZAR",
+            };
+
+            synchronized (ULocale.class) {
+                if (_countries == null) {
+                    _countries = tempCountries;
+                    _deprecatedCountries = tempDeprecatedCountries;
+                    _replacementCountries = tempReplacementCountries;
+                    _obsoleteCountries = tempObsoleteCountries;
+                    _countries3 = tempCountries3;
+                    _obsoleteCountries3 = tempObsoleteCountries3;
+                }
+            }
+        }
+    }
+
+    public static String getCurrentCountryID(String oldID){
+        initCountryTables();
+        int offset = findIndex(_deprecatedCountries, oldID);
+        if (offset >= 0) {
+            return _replacementCountries[offset];
+        }
+        return oldID;
+    }
+
+    public static String getCurrentLanguageID(String oldID){
+        initLanguageTables();
+        int offset = findIndex(_obsoleteLanguages, oldID);
+        if (offset >= 0) {
+            return _replacementLanguages[offset];
+        }
+        return oldID;
+    }
+
+
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/LocaleUtility.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/LocaleUtility.java
index f219f09..143ac9d 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/LocaleUtility.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/LocaleUtility.java
@@ -1,132 +1,132 @@
-/*
- ******************************************************************************
- * Copyright (C) 1996-2011, International Business Machines Corporation and   *
- * others. All Rights Reserved.                                               *
- ******************************************************************************
- *
- ******************************************************************************
- */
- 
-package com.ibm.icu.impl;
-
-import java.util.Locale;
-
-/**
- * A class to hold utility functions missing from java.util.Locale.
- */
-public class LocaleUtility {
-
-    /**
-     * A helper function to convert a string of the form
-     * aa_BB_CC to a locale object.  Why isn't this in Locale?
-     */
-    public static Locale getLocaleFromName(String name) {
-        String language = "";
-        String country = "";
-        String variant = "";
-
-        int i1 = name.indexOf('_');
-        if (i1 < 0) {
-            language = name;
-        } else {
-            language = name.substring(0, i1);
-            ++i1;
-            int i2 = name.indexOf('_', i1);
-            if (i2 < 0) {
-                country = name.substring(i1);
-            } else {
-                country = name.substring(i1, i2);
-                variant = name.substring(i2+1);
-            }
-        }
-
-        return new Locale(language, country, variant);
-    }
-
-    /**
-     * Compare two locale strings of the form aa_BB_CC, and
-     * return true if parent is a 'strict' fallback of child, that is,
-     * if child =~ "^parent(_.+)*" (roughly).
-     */
-    public static boolean isFallbackOf(String parent, String child) {
-        if (!child.startsWith(parent)) {
-            return false;
-        }
-        int i = parent.length();
-        return (i == child.length() ||
-                child.charAt(i) == '_');
-    }
-
-    /**
-     * Compare two locales, and return true if the parent is a
-     * 'strict' fallback of the child (parent string is a fallback
-     * of child string).
-     */
-    public static boolean isFallbackOf(Locale parent, Locale child) {
-        return isFallbackOf(parent.toString(), child.toString());
-    }
-
-
-    /*
-     * Convenience method that calls canonicalLocaleString(String) with
-     * locale.toString();
-     */
-    /*public static String canonicalLocaleString(Locale locale) {
-        return canonicalLocaleString(locale.toString());
-    }*/
-
-    /*
-     * You'd think that Locale canonicalizes, since it munges the
-     * renamed languages, but it doesn't quite.  It forces the region
-     * to be upper case but doesn't do anything about the language or
-     * variant.  Our canonical form is 'lower_UPPER_UPPER'.  
-     */
-    /*public static String canonicalLocaleString(String id) {
-        if (id != null) {
-            int x = id.indexOf("_");
-            if (x == -1) {
-                id = id.toLowerCase(Locale.ENGLISH);
-            } else {
-                StringBuffer buf = new StringBuffer();
-                buf.append(id.substring(0, x).toLowerCase(Locale.ENGLISH));
-                buf.append(id.substring(x).toUpperCase(Locale.ENGLISH));
-
-                int len = buf.length();
-                int n = len;
-                while (--n >= 0 && buf.charAt(n) == '_') {
-                }
-                if (++n != len) {
-                    buf.delete(n, len);
-                }
-                id = buf.toString();
-            }
-        }
-        return id;
-    }*/
-
-    /**
-     * Fallback from the given locale name by removing the rightmost _-delimited
-     * element. If there is none, return the root locale ("", "", ""). If this
-     * is the root locale, return null. NOTE: The string "root" is not
-     * recognized; do not use it.
-     * 
-     * @return a new Locale that is a fallback from the given locale, or null.
-     */
-    public 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]);
-    }
-}
+/*
+ ******************************************************************************
+ * Copyright (C) 1996-2011, International Business Machines Corporation and   *
+ * others. All Rights Reserved.                                               *
+ ******************************************************************************
+ *
+ ******************************************************************************
+ */
+ 
+package com.ibm.icu.impl;
+
+import java.util.Locale;
+
+/**
+ * A class to hold utility functions missing from java.util.Locale.
+ */
+public class LocaleUtility {
+
+    /**
+     * A helper function to convert a string of the form
+     * aa_BB_CC to a locale object.  Why isn't this in Locale?
+     */
+    public static Locale getLocaleFromName(String name) {
+        String language = "";
+        String country = "";
+        String variant = "";
+
+        int i1 = name.indexOf('_');
+        if (i1 < 0) {
+            language = name;
+        } else {
+            language = name.substring(0, i1);
+            ++i1;
+            int i2 = name.indexOf('_', i1);
+            if (i2 < 0) {
+                country = name.substring(i1);
+            } else {
+                country = name.substring(i1, i2);
+                variant = name.substring(i2+1);
+            }
+        }
+
+        return new Locale(language, country, variant);
+    }
+
+    /**
+     * Compare two locale strings of the form aa_BB_CC, and
+     * return true if parent is a 'strict' fallback of child, that is,
+     * if child =~ "^parent(_.+)*" (roughly).
+     */
+    public static boolean isFallbackOf(String parent, String child) {
+        if (!child.startsWith(parent)) {
+            return false;
+        }
+        int i = parent.length();
+        return (i == child.length() ||
+                child.charAt(i) == '_');
+    }
+
+    /**
+     * Compare two locales, and return true if the parent is a
+     * 'strict' fallback of the child (parent string is a fallback
+     * of child string).
+     */
+    public static boolean isFallbackOf(Locale parent, Locale child) {
+        return isFallbackOf(parent.toString(), child.toString());
+    }
+
+
+    /*
+     * Convenience method that calls canonicalLocaleString(String) with
+     * locale.toString();
+     */
+    /*public static String canonicalLocaleString(Locale locale) {
+        return canonicalLocaleString(locale.toString());
+    }*/
+
+    /*
+     * You'd think that Locale canonicalizes, since it munges the
+     * renamed languages, but it doesn't quite.  It forces the region
+     * to be upper case but doesn't do anything about the language or
+     * variant.  Our canonical form is 'lower_UPPER_UPPER'.  
+     */
+    /*public static String canonicalLocaleString(String id) {
+        if (id != null) {
+            int x = id.indexOf("_");
+            if (x == -1) {
+                id = id.toLowerCase(Locale.ENGLISH);
+            } else {
+                StringBuffer buf = new StringBuffer();
+                buf.append(id.substring(0, x).toLowerCase(Locale.ENGLISH));
+                buf.append(id.substring(x).toUpperCase(Locale.ENGLISH));
+
+                int len = buf.length();
+                int n = len;
+                while (--n >= 0 && buf.charAt(n) == '_') {
+                }
+                if (++n != len) {
+                    buf.delete(n, len);
+                }
+                id = buf.toString();
+            }
+        }
+        return id;
+    }*/
+
+    /**
+     * Fallback from the given locale name by removing the rightmost _-delimited
+     * element. If there is none, return the root locale ("", "", ""). If this
+     * is the root locale, return null. NOTE: The string "root" is not
+     * recognized; do not use it.
+     * 
+     * @return a new Locale that is a fallback from the given locale, or null.
+     */
+    public 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]);
+    }
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/SimpleCache.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/SimpleCache.java
index fc431b0..7ee2dc5 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/SimpleCache.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/SimpleCache.java
@@ -1,73 +1,73 @@
-/*
- ****************************************************************************
- * Copyright (c) 2007-2011 International Business Machines Corporation and  *
- * others.  All rights reserved.                                            *
- ****************************************************************************
- */
-
-package com.ibm.icu.impl;
-
-import java.lang.ref.Reference;
-import java.lang.ref.SoftReference;
-import java.lang.ref.WeakReference;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-public class SimpleCache<K, V> implements ICUCache<K, V> {
-    private static final int DEFAULT_CAPACITY = 16;
-
-    private Reference<Map<K, V>> cacheRef = null;
-    private int type = ICUCache.SOFT;
-    private int capacity = DEFAULT_CAPACITY;
-
-    public SimpleCache() {
-    }
-
-    public SimpleCache(int cacheType) {
-        this(cacheType, DEFAULT_CAPACITY);
-    }
-
-    public SimpleCache(int cacheType, int initialCapacity) {
-        if (cacheType == ICUCache.WEAK) {
-            type = cacheType;
-        }
-        if (initialCapacity > 0) {
-            capacity = initialCapacity;
-        }
-    }
-
-    public V get(Object key) {
-        Reference<Map<K, V>> ref = cacheRef;
-        if (ref != null) {
-            Map<K, V> map = ref.get();
-            if (map != null) {
-                return map.get(key);
-            }
-        }
-        return null;
-    }
-
-    public void put(K key, V value) {
-        Reference<Map<K, V>> ref = cacheRef;
-        Map<K, V> map = null;
-        if (ref != null) {
-            map = ref.get();
-        }
-        if (map == null) {
-            map = Collections.synchronizedMap(new HashMap<K, V>(capacity));
-            if (type == ICUCache.WEAK) {
-                ref = new WeakReference<Map<K, V>>(map);
-            } else {
-                ref = new SoftReference<Map<K, V>>(map);
-            }
-            cacheRef = ref;
-        }
-        map.put(key, value);
-    }
-
-    public void clear() {
-        cacheRef = null;
-    }
-
-}
+/*
+ ****************************************************************************
+ * Copyright (c) 2007-2011 International Business Machines Corporation and  *
+ * others.  All rights reserved.                                            *
+ ****************************************************************************
+ */
+
+package com.ibm.icu.impl;
+
+import java.lang.ref.Reference;
+import java.lang.ref.SoftReference;
+import java.lang.ref.WeakReference;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+public class SimpleCache<K, V> implements ICUCache<K, V> {
+    private static final int DEFAULT_CAPACITY = 16;
+
+    private Reference<Map<K, V>> cacheRef = null;
+    private int type = ICUCache.SOFT;
+    private int capacity = DEFAULT_CAPACITY;
+
+    public SimpleCache() {
+    }
+
+    public SimpleCache(int cacheType) {
+        this(cacheType, DEFAULT_CAPACITY);
+    }
+
+    public SimpleCache(int cacheType, int initialCapacity) {
+        if (cacheType == ICUCache.WEAK) {
+            type = cacheType;
+        }
+        if (initialCapacity > 0) {
+            capacity = initialCapacity;
+        }
+    }
+
+    public V get(Object key) {
+        Reference<Map<K, V>> ref = cacheRef;
+        if (ref != null) {
+            Map<K, V> map = ref.get();
+            if (map != null) {
+                return map.get(key);
+            }
+        }
+        return null;
+    }
+
+    public void put(K key, V value) {
+        Reference<Map<K, V>> ref = cacheRef;
+        Map<K, V> map = null;
+        if (ref != null) {
+            map = ref.get();
+        }
+        if (map == null) {
+            map = Collections.synchronizedMap(new HashMap<K, V>(capacity));
+            if (type == ICUCache.WEAK) {
+                ref = new WeakReference<Map<K, V>>(map);
+            } else {
+                ref = new SoftReference<Map<K, V>>(map);
+            }
+            cacheRef = ref;
+        }
+        map.put(key, value);
+    }
+
+    public void clear() {
+        cacheRef = null;
+    }
+
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/locale/AsciiUtil.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/locale/AsciiUtil.java
index 24383f0..2f751d9 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/locale/AsciiUtil.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/locale/AsciiUtil.java
@@ -1,180 +1,183 @@
-/*
- *******************************************************************************
- * Copyright (C) 2009-2011, International Business Machines Corporation and    *
- * others. All Rights Reserved.                                                *
- *******************************************************************************
- */
-package com.ibm.icu.impl.locale;
-
-public final class AsciiUtil {
-    public static boolean caseIgnoreMatch(String s1, String s2) {
-        if (s1 == s2) {
-            return true;
-        }
-        int len = s1.length();
-        if (len != s2.length()) {
-            return false;
-        }
-        int i = 0;
-        while (i < len) {
-            char c1 = s1.charAt(i);
-            char c2 = s2.charAt(i);
-            if (c1 != c2 && toLower(c1) != toLower(c2)) {
-                break;
-            }
-            i++;
-        }
-        return (i == len);
-    }
-
-    public static int caseIgnoreCompare(String s1, String s2) {
-        if (s1 == s2) {
-            return 0;
-        }
-        return AsciiUtil.toLowerString(s1).compareTo(AsciiUtil.toLowerString(s2));
-    }
-
-
-    public static char toUpper(char c) {
-        if (c >= 'a' && c <= 'z') {
-            c -= 0x20;
-        }
-        return c;
-    }
-
-    public static char toLower(char c) {
-        if (c >= 'A' && c <= 'Z') {
-            c += 0x20;
-        }
-        return c;
-    }
-
-    public static String toLowerString(String s) {
-        int idx = 0;
-        for (; idx < s.length(); idx++) {
-            char c = s.charAt(idx);
-            if (c >= 'A' && c <= 'Z') {
-                break;
-            }
-        }
-        if (idx == s.length()) {
-            return s;
-        }
-        StringBuilder buf = new StringBuilder(s.substring(0, idx));
-        for (; idx < s.length(); idx++) {
-            buf.append(toLower(s.charAt(idx)));
-        }
-        return buf.toString();
-    }
-
-    public static String toUpperString(String s) {
-        int idx = 0;
-        for (; idx < s.length(); idx++) {
-            char c = s.charAt(idx);
-            if (c >= 'a' && c <= 'z') {
-                break;
-            }
-        }
-        if (idx == s.length()) {
-            return s;
-        }
-        StringBuilder buf = new StringBuilder(s.substring(0, idx));
-        for (; idx < s.length(); idx++) {
-            buf.append(toUpper(s.charAt(idx)));
-        }
-        return buf.toString();
-    }
-
-    public static String toTitleString(String s) {
-        if (s.length() == 0) {
-            return s;
-        }
-        int idx = 0;
-        char c = s.charAt(idx);
-        if (!(c >= 'a' && c <= 'z')) {
-            for (idx = 1; idx < s.length(); idx++) {
-                if (c >= 'A' && c <= 'Z') {
-                    break;
-                }
-            }
-        }
-        if (idx == s.length()) {
-            return s;
-        }
-        StringBuilder buf = new StringBuilder(s.substring(0, idx));
-        if (idx == 0) {
-            buf.append(toUpper(s.charAt(idx)));
-            idx++;
-        }
-        for (; idx < s.length(); idx++) {
-            buf.append(toLower(s.charAt(idx)));
-        }
-        return buf.toString();
-    }
-
-    public static boolean isAlpha(char c) {
-        return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
-    }
-
-    public static boolean isAlphaString(String s) {
-        boolean b = true;
-        for (int i = 0; i < s.length(); i++) {
-            if (!isAlpha(s.charAt(i))) {
-                b = false;
-                break;
-            }
-        }
-        return b;
-    }
-
-    public static boolean isNumeric(char c) {
-        return (c >= '0' && c <= '9');
-    }
-
-    public static boolean isNumericString(String s) {
-        boolean b = true;
-        for (int i = 0; i < s.length(); i++) {
-            if (!isNumeric(s.charAt(i))) {
-                b = false;
-                break;
-            }
-        }
-        return b;
-    }
-
-    public static boolean isAlphaNumeric(char c) {
-        return isAlpha(c) || isNumeric(c);
-    }
-
-    public static boolean isAlphaNumericString(String s) {
-        boolean b = true;
-        for (int i = 0; i < s.length(); i++) {
-            if (!isAlphaNumeric(s.charAt(i))) {
-                b = false;
-                break;
-            }
-        }
-        return b;
-    }
-
-    public static class CaseInsensitiveKey {
-        private String _key;
-        private int _hash;
-
-        public CaseInsensitiveKey(String key) {
-            _key = key;
-            _hash = AsciiUtil.toLowerString(key).hashCode();
-        }
-
-        public boolean equals(Object o) {
-            if (o instanceof CaseInsensitiveKey) {
-                return AsciiUtil.caseIgnoreMatch(_key, ((CaseInsensitiveKey)o)._key);
-            }
-            return false;
-        }
-
-        public int hashCode() {
-            return _hash;
-        }
-    }
-}
+/*
+ *******************************************************************************
+ * Copyright (C) 2009-2011, International Business Machines Corporation and    *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+package com.ibm.icu.impl.locale;
+
+public final class AsciiUtil {
+    public static boolean caseIgnoreMatch(String s1, String s2) {
+        if (s1 == s2) {
+            return true;
+        }
+        int len = s1.length();
+        if (len != s2.length()) {
+            return false;
+        }
+        int i = 0;
+        while (i < len) {
+            char c1 = s1.charAt(i);
+            char c2 = s2.charAt(i);
+            if (c1 != c2 && toLower(c1) != toLower(c2)) {
+                break;
+            }
+            i++;
+        }
+        return (i == len);
+    }
+
+    public static int caseIgnoreCompare(String s1, String s2) {
+        if (s1 == s2) {
+            return 0;
+        }
+        return AsciiUtil.toLowerString(s1).compareTo(AsciiUtil.toLowerString(s2));
+    }
+
+
+    public static char toUpper(char c) {
+        if (c >= 'a' && c <= 'z') {
+            c -= 0x20;
+        }
+        return c;
+    }
+
+    public static char toLower(char c) {
+        if (c >= 'A' && c <= 'Z') {
+            c += 0x20;
+        }
+        return c;
+    }
+
+    public static String toLowerString(String s) {
+        int idx = 0;
+        for (; idx < s.length(); idx++) {
+            char c = s.charAt(idx);
+            if (c >= 'A' && c <= 'Z') {
+                break;
+            }
+        }
+        if (idx == s.length()) {
+            return s;
+        }
+        StringBuilder buf = new StringBuilder(s.substring(0, idx));
+        for (; idx < s.length(); idx++) {
+            buf.append(toLower(s.charAt(idx)));
+        }
+        return buf.toString();
+    }
+
+    public static String toUpperString(String s) {
+        int idx = 0;
+        for (; idx < s.length(); idx++) {
+            char c = s.charAt(idx);
+            if (c >= 'a' && c <= 'z') {
+                break;
+            }
+        }
+        if (idx == s.length()) {
+            return s;
+        }
+        StringBuilder buf = new StringBuilder(s.substring(0, idx));
+        for (; idx < s.length(); idx++) {
+            buf.append(toUpper(s.charAt(idx)));
+        }
+        return buf.toString();
+    }
+
+    public static String toTitleString(String s) {
+        if (s.length() == 0) {
+            return s;
+        }
+        int idx = 0;
+        char c = s.charAt(idx);
+        if (!(c >= 'a' && c <= 'z')) {
+            for (idx = 1; idx < s.length(); idx++) {
+                if (c >= 'A' && c <= 'Z') {
+                    break;
+                }
+            }
+        }
+        if (idx == s.length()) {
+            return s;
+        }
+        StringBuilder buf = new StringBuilder(s.substring(0, idx));
+        if (idx == 0) {
+            buf.append(toUpper(s.charAt(idx)));
+            idx++;
+        }
+        for (; idx < s.length(); idx++) {
+            buf.append(toLower(s.charAt(idx)));
+        }
+        return buf.toString();
+    }
+
+    public static boolean isAlpha(char c) {
+        return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
+    }
+
+    public static boolean isAlphaString(String s) {
+        boolean b = true;
+        for (int i = 0; i < s.length(); i++) {
+            if (!isAlpha(s.charAt(i))) {
+                b = false;
+                break;
+            }
+        }
+        return b;
+    }
+
+    public static boolean isNumeric(char c) {
+        return (c >= '0' && c <= '9');
+    }
+
+    public static boolean isNumericString(String s) {
+        boolean b = true;
+        for (int i = 0; i < s.length(); i++) {
+            if (!isNumeric(s.charAt(i))) {
+                b = false;
+                break;
+            }
+        }
+        return b;
+    }
+
+    public static boolean isAlphaNumeric(char c) {
+        return isAlpha(c) || isNumeric(c);
+    }
+
+    public static boolean isAlphaNumericString(String s) {
+        boolean b = true;
+        for (int i = 0; i < s.length(); i++) {
+            if (!isAlphaNumeric(s.charAt(i))) {
+                b = false;
+                break;
+            }
+        }
+        return b;
+    }
+
+    public static class CaseInsensitiveKey {
+        private String _key;
+        private int _hash;
+
+        public CaseInsensitiveKey(String key) {
+            _key = key;
+            _hash = AsciiUtil.toLowerString(key).hashCode();
+        }
+
+        public boolean equals(Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (o instanceof CaseInsensitiveKey) {
+                return AsciiUtil.caseIgnoreMatch(_key, ((CaseInsensitiveKey)o)._key);
+            }
+            return false;
+        }
+
+        public int hashCode() {
+            return _hash;
+        }
+    }
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/locale/BaseLocale.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/locale/BaseLocale.java
new file mode 100644
index 0000000..be24cff
--- /dev/null
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/locale/BaseLocale.java
@@ -0,0 +1,257 @@
+/*
+ *******************************************************************************
+ * Copyright (C) 2009-2011, International Business Machines Corporation and    *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+
+package com.ibm.icu.impl.locale;
+
+
+public final class BaseLocale {
+
+    private static final boolean JDKIMPL = false;
+
+    public static final String SEP = "_";
+
+    private static final Cache CACHE = new Cache();
+    public static final BaseLocale ROOT = BaseLocale.getInstance("", "", "", "");
+
+    private String _language = "";
+    private String _script = "";
+    private String _region = "";
+    private String _variant = "";
+
+    private transient volatile int _hash = 0;
+
+    private BaseLocale(String language, String script, String region, String variant) {
+        if (language != null) {
+            _language = AsciiUtil.toLowerString(language).intern();
+        }
+        if (script != null) {
+            _script = AsciiUtil.toTitleString(script).intern();
+        }
+        if (region != null) {
+            _region = AsciiUtil.toUpperString(region).intern();
+        }
+        if (variant != null) {
+            if (JDKIMPL) {
+                // preserve upper/lower cases
+                _variant = variant.intern();
+            } else {
+                _variant = AsciiUtil.toUpperString(variant).intern();
+            }
+        }
+    }
+
+    public static BaseLocale getInstance(String language, String script, String region, String variant) {
+        if (JDKIMPL) {
+            // JDK uses deprecated ISO639.1 language codes for he, yi and id
+            if (AsciiUtil.caseIgnoreMatch(language, "he")) {
+                language = "iw";
+            } else if (AsciiUtil.caseIgnoreMatch(language, "yi")) {
+                language = "ji";
+            } else if (AsciiUtil.caseIgnoreMatch(language, "id")) {
+                language = "in";
+            }
+        }
+        Key key = new Key(language, script, region, variant);
+        BaseLocale baseLocale = CACHE.get(key);
+        return baseLocale;
+    }
+
+    public String getLanguage() {
+        return _language;
+    }
+
+    public String getScript() {
+        return _script;
+    }
+
+    public String getRegion() {
+        return _region;
+    }
+
+    public String getVariant() {
+        return _variant;
+    }
+
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (!(obj instanceof BaseLocale)) {
+            return false;
+        }
+        BaseLocale other = (BaseLocale)obj;
+        return hashCode() == other.hashCode()
+                && _language.equals(other._language)
+                && _script.equals(other._script)
+                && _region.equals(other._region)
+                && _variant.equals(other._variant);
+    }
+
+    public String toString() {
+        StringBuilder buf = new StringBuilder();
+        if (_language.length() > 0) {
+            buf.append("language=");
+            buf.append(_language);
+        }
+        if (_script.length() > 0) {
+            if (buf.length() > 0) {
+                buf.append(", ");
+            }
+            buf.append("script=");
+            buf.append(_script);
+        }
+        if (_region.length() > 0) {
+            if (buf.length() > 0) {
+                buf.append(", ");
+            }
+            buf.append("region=");
+            buf.append(_region);
+        }
+        if (_variant.length() > 0) {
+            if (buf.length() > 0) {
+                buf.append(", ");
+            }
+            buf.append("variant=");
+            buf.append(_variant);
+        }
+        return buf.toString();
+    }
+
+    public int hashCode() {
+        int h = _hash;
+        if (h == 0) {
+            // Generating a hash value from language, script, region and variant
+            for (int i = 0; i < _language.length(); i++) {
+                h = 31*h + _language.charAt(i);
+            }
+            for (int i = 0; i < _script.length(); i++) {
+                h = 31*h + _script.charAt(i);
+            }
+            for (int i = 0; i < _region.length(); i++) {
+                h = 31*h + _region.charAt(i);
+            }
+            for (int i = 0; i < _variant.length(); i++) {
+                h = 31*h + _variant.charAt(i);
+            }
+            _hash = h;
+        }
+        return h;
+    }
+
+    private static class Key implements Comparable<Key> {
+        private String _lang = "";
+        private String _scrt = "";
+        private String _regn = "";
+        private String _vart = "";
+
+        private volatile int _hash; // Default to 0
+
+        public Key(String language, String script, String region, String variant) {
+            if (language != null) {
+                _lang = language;
+            }
+            if (script != null) {
+                _scrt = script;
+            }
+            if (region != null) {
+                _regn = region;
+            }
+            if (variant != null) {
+                _vart = variant;
+            }
+        }
+
+        public boolean equals(Object obj) {
+            if (JDKIMPL) {
+                return (this == obj) ||
+                        (obj instanceof Key)
+                        && AsciiUtil.caseIgnoreMatch(((Key)obj)._lang, this._lang)
+                        && AsciiUtil.caseIgnoreMatch(((Key)obj)._scrt, this._scrt)
+                        && AsciiUtil.caseIgnoreMatch(((Key)obj)._regn, this._regn)
+                        && ((Key)obj)._vart.equals(_vart); // variant is case sensitive in JDK!
+            }
+            return (this == obj) ||
+                    (obj instanceof Key)
+                    && AsciiUtil.caseIgnoreMatch(((Key)obj)._lang, this._lang)
+                    && AsciiUtil.caseIgnoreMatch(((Key)obj)._scrt, this._scrt)
+                    && AsciiUtil.caseIgnoreMatch(((Key)obj)._regn, this._regn)
+                    && AsciiUtil.caseIgnoreMatch(((Key)obj)._vart, this._vart);
+        }
+
+        public int compareTo(Key other) {
+            int res = AsciiUtil.caseIgnoreCompare(this._lang, other._lang);
+            if (res == 0) {
+                res = AsciiUtil.caseIgnoreCompare(this._scrt, other._scrt);
+                if (res == 0) {
+                    res = AsciiUtil.caseIgnoreCompare(this._regn, other._regn);
+                    if (res == 0) {
+                        if (JDKIMPL) {
+                            res = this._vart.compareTo(other._vart);
+                        } else {
+                            res = AsciiUtil.caseIgnoreCompare(this._vart, other._vart);
+                        }
+                    }
+                }
+            }
+            return res;
+        }
+
+        public int hashCode() {
+            int h = _hash;
+            if (h == 0) {
+                // Generating a hash value from language, script, region and variant
+                for (int i = 0; i < _lang.length(); i++) {
+                    h = 31*h + AsciiUtil.toLower(_lang.charAt(i));
+                }
+                for (int i = 0; i < _scrt.length(); i++) {
+                    h = 31*h + AsciiUtil.toLower(_scrt.charAt(i));
+                }
+                for (int i = 0; i < _regn.length(); i++) {
+                    h = 31*h + AsciiUtil.toLower(_regn.charAt(i));
+                }
+                for (int i = 0; i < _vart.length(); i++) {
+                    if (JDKIMPL) {
+                        h = 31*h + _vart.charAt(i);
+                    } else {
+                        h = 31*h + AsciiUtil.toLower(_vart.charAt(i));
+                    }
+                }
+                _hash = h;
+            }
+            return h;
+        }
+
+        public static Key normalize(Key key) {
+            String lang = AsciiUtil.toLowerString(key._lang).intern();
+            String scrt = AsciiUtil.toTitleString(key._scrt).intern();
+            String regn = AsciiUtil.toUpperString(key._regn).intern();
+            String vart;
+            if (JDKIMPL) {
+                // preserve upper/lower cases
+                vart = key._vart.intern();
+            } else {
+                vart = AsciiUtil.toUpperString(key._vart).intern();
+            }
+            return new Key(lang, scrt, regn, vart);
+        }
+    }
+
+    private static class Cache extends LocaleObjectCache<Key, BaseLocale> {
+
+        public Cache() {
+        }
+
+        protected Key normalizeKey(Key key) {
+            return Key.normalize(key);
+        }
+
+        protected BaseLocale createObject(Key key) {
+            return new BaseLocale(key._lang, key._scrt, key._regn, key._vart);
+        }
+
+    }
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/locale/Extension.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/locale/Extension.java
new file mode 100644
index 0000000..dec331c
--- /dev/null
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/locale/Extension.java
@@ -0,0 +1,38 @@
+/*
+ *******************************************************************************
+ * Copyright (C) 2009-2011, International Business Machines Corporation and    *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+package com.ibm.icu.impl.locale;
+
+
+public class Extension {
+    private char _key;
+    protected String _value;
+
+    protected Extension(char key) {
+        _key = key;
+    }
+
+    Extension(char key, String value) {
+        _key = key;
+        _value = value;
+    }
+
+    public char getKey() {
+        return _key;
+    }
+
+    public String getValue() {
+        return _value;
+    }
+
+    public String getID() {
+        return _key + LanguageTag.SEP + _value;
+    }
+
+    public String toString() {
+        return getID();
+    }
+}
\ No newline at end of file
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/locale/InternalLocaleBuilder.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/locale/InternalLocaleBuilder.java
new file mode 100644
index 0000000..27d0ef8
--- /dev/null
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/locale/InternalLocaleBuilder.java
@@ -0,0 +1,684 @@
+/*
+ *******************************************************************************
+ * Copyright (C) 2009-2011, International Business Machines Corporation and    *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+package com.ibm.icu.impl.locale;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public final class InternalLocaleBuilder {
+
+    private static final boolean JDKIMPL = false;
+
+    private String _language = "";
+    private String _script = "";
+    private String _region = "";
+    private String _variant = "";
+
+    private static final CaseInsensitiveChar PRIVUSE_KEY = new CaseInsensitiveChar(LanguageTag.PRIVATEUSE.charAt(0));
+
+    private HashMap<CaseInsensitiveChar, String> _extensions;
+    private HashSet<CaseInsensitiveString> _uattributes;
+    private HashMap<CaseInsensitiveString, String> _ukeywords;
+
+
+    public InternalLocaleBuilder() {
+    }
+
+    public InternalLocaleBuilder setLanguage(String language) throws LocaleSyntaxException {
+        if (language == null || language.length() == 0) {
+            _language = "";
+        } else {
+            if (!LanguageTag.isLanguage(language)) {
+                throw new LocaleSyntaxException("Ill-formed language: " + language, 0);
+            }
+            _language = language;
+        }
+        return this;
+    }
+
+    public InternalLocaleBuilder setScript(String script) throws LocaleSyntaxException {
+        if (script == null || script.length() == 0) {
+            _script = "";
+        } else {
+            if (!LanguageTag.isScript(script)) {
+                throw new LocaleSyntaxException("Ill-formed script: " + script, 0);
+            }
+            _script = script;
+        }
+        return this;
+    }
+
+    public InternalLocaleBuilder setRegion(String region) throws LocaleSyntaxException {
+        if (region == null || region.length() == 0) {
+            _region = "";
+        } else {
+            if (!LanguageTag.isRegion(region)) {
+                throw new LocaleSyntaxException("Ill-formed region: " + region, 0);
+            }
+            _region = region;
+        }
+        return this;
+    }
+
+    public InternalLocaleBuilder setVariant(String variant) throws LocaleSyntaxException {
+        if (variant == null || variant.length() == 0) {
+            _variant = "";
+        } else {
+            // normalize separators to "_"
+            String var = variant.replaceAll(LanguageTag.SEP, BaseLocale.SEP);
+            int errIdx = checkVariants(var, BaseLocale.SEP);
+            if (errIdx != -1) {
+                throw new LocaleSyntaxException("Ill-formed variant: " + variant, errIdx);
+            }
+            _variant = var;
+        }
+        return this;
+    }
+
+    public InternalLocaleBuilder addUnicodeLocaleAttribute(String attribute) throws LocaleSyntaxException {
+        if (attribute == null || !UnicodeLocaleExtension.isAttribute(attribute)) {
+            throw new LocaleSyntaxException("Ill-formed Unicode locale attribute: " + attribute);
+        }
+        // Use case insensitive string to prevent duplication
+        if (_uattributes == null) {
+            _uattributes = new HashSet<CaseInsensitiveString>(4);
+        }
+        _uattributes.add(new CaseInsensitiveString(attribute));
+        return this;
+    }
+
+    public InternalLocaleBuilder removeUnicodeLocaleAttribute(String attribute) throws LocaleSyntaxException {
+        if (attribute == null || !UnicodeLocaleExtension.isAttribute(attribute)) {
+            throw new LocaleSyntaxException("Ill-formed Unicode locale attribute: " + attribute);
+        }
+        if (_uattributes != null) {
+            _uattributes.remove(new CaseInsensitiveString(attribute));
+        }
+        return this;
+    }
+
+    public InternalLocaleBuilder setUnicodeLocaleKeyword(String key, String type) throws LocaleSyntaxException {
+        if (!UnicodeLocaleExtension.isKey(key)) {
+            throw new LocaleSyntaxException("Ill-formed Unicode locale keyword key: " + key);
+        }
+
+        CaseInsensitiveString cikey = new CaseInsensitiveString(key);
+        if (type == null) {
+            if (_ukeywords != null) {
+                // null type is used for remove the key
+                _ukeywords.remove(cikey);
+            }
+        } else {
+            if (type.length() != 0) {
+                // normalize separator to "-"
+                String tp = type.replaceAll(BaseLocale.SEP, LanguageTag.SEP);
+                // validate
+                StringTokenIterator itr = new StringTokenIterator(tp, LanguageTag.SEP);
+                while (!itr.isDone()) {
+                    String s = itr.current();
+                    if (!UnicodeLocaleExtension.isTypeSubtag(s)) {
+                        throw new LocaleSyntaxException("Ill-formed Unicode locale keyword type: " + type, itr.currentStart());
+                    }
+                    itr.next();
+                }
+            }
+            if (_ukeywords == null) {
+                _ukeywords = new HashMap<CaseInsensitiveString, String>(4);
+            }
+            _ukeywords.put(cikey, type);
+        }
+        return this;
+    }
+
+    public InternalLocaleBuilder setExtension(char singleton, String value) throws LocaleSyntaxException {
+        // validate key
+        boolean isBcpPrivateuse = LanguageTag.isPrivateusePrefixChar(singleton);
+        if (!isBcpPrivateuse && !LanguageTag.isExtensionSingletonChar(singleton)) {
+            throw new LocaleSyntaxException("Ill-formed extension key: " + singleton);
+        }
+
+        boolean remove = (value == null || value.length() == 0);
+        CaseInsensitiveChar key = new CaseInsensitiveChar(singleton);
+
+        if (remove) {
+            if (UnicodeLocaleExtension.isSingletonChar(key.value())) {
+                // clear entire Unicode locale extension
+                if (_uattributes != null) {
+                    _uattributes.clear();
+                }
+                if (_ukeywords != null) {
+                    _ukeywords.clear();
+                }
+            } else {
+                if (_extensions != null && _extensions.containsKey(key)) {
+                    _extensions.remove(key);
+                }
+            }
+        } else {
+            // validate value
+            String val = value.replaceAll(BaseLocale.SEP, LanguageTag.SEP);
+            StringTokenIterator itr = new StringTokenIterator(val, LanguageTag.SEP);
+            while (!itr.isDone()) {
+                String s = itr.current();
+                boolean validSubtag;
+                if (isBcpPrivateuse) {
+                    validSubtag = LanguageTag.isPrivateuseSubtag(s);
+                } else {
+                    validSubtag = LanguageTag.isExtensionSubtag(s);
+                }
+                if (!validSubtag) {
+                    throw new LocaleSyntaxException("Ill-formed extension value: " + s, itr.currentStart());
+                }
+                itr.next();
+            }
+
+            if (UnicodeLocaleExtension.isSingletonChar(key.value())) {
+                setUnicodeLocaleExtension(val);
+            } else {
+                if (_extensions == null) {
+                    _extensions = new HashMap<CaseInsensitiveChar, String>(4);
+                }
+                _extensions.put(key, val);
+            }
+        }
+        return this;
+    }
+
+    /*
+     * Set extension/private subtags in a single string representation
+     */
+    public InternalLocaleBuilder setExtensions(String subtags) throws LocaleSyntaxException {
+        if (subtags == null || subtags.length() == 0) {
+            clearExtensions();
+            return this;
+        }
+        subtags = subtags.replaceAll(BaseLocale.SEP, LanguageTag.SEP);
+        StringTokenIterator itr = new StringTokenIterator(subtags, LanguageTag.SEP);
+
+        List<String> extensions = null;
+        String privateuse = null;
+
+        int parsed = 0;
+        int start;
+
+        // Make a list of extension subtags
+        while (!itr.isDone()) {
+            String s = itr.current();
+            if (LanguageTag.isExtensionSingleton(s)) {
+                start = itr.currentStart();
+                String singleton = s;
+                StringBuilder sb = new StringBuilder(singleton);
+
+                itr.next();
+                while (!itr.isDone()) {
+                    s = itr.current();
+                    if (LanguageTag.isExtensionSubtag(s)) {
+                        sb.append(LanguageTag.SEP).append(s);
+                        parsed = itr.currentEnd();
+                    } else {
+                        break;
+                    }
+                    itr.next();
+                }
+
+                if (parsed < start) {
+                    throw new LocaleSyntaxException("Incomplete extension '" + singleton + "'", start);
+                }
+
+                if (extensions == null) {
+                    extensions = new ArrayList<String>(4);
+                }
+                extensions.add(sb.toString());
+            } else {
+                break;
+            }
+        }
+        if (!itr.isDone()) {
+            String s = itr.current();
+            if (LanguageTag.isPrivateusePrefix(s)) {
+                start = itr.currentStart();
+                StringBuilder sb = new StringBuilder(s);
+
+                itr.next();
+                while (!itr.isDone()) {
+                    s = itr.current();
+                    if (!LanguageTag.isPrivateuseSubtag(s)) {
+                        break;
+                    }
+                    sb.append(LanguageTag.SEP).append(s);
+                    parsed = itr.currentEnd();
+
+                    itr.next();
+                }
+                if (parsed <= start) {
+                    throw new LocaleSyntaxException("Incomplete privateuse:" + subtags.substring(start), start);
+                } else {
+                    privateuse = sb.toString();
+                }
+            }
+        }
+
+        if (!itr.isDone()) {
+            throw new LocaleSyntaxException("Ill-formed extension subtags:" + subtags.substring(itr.currentStart()), itr.currentStart());
+        }
+
+        return setExtensions(extensions, privateuse);
+    }
+
+    /*
+     * Set a list of BCP47 extensions and private use subtags
+     * BCP47 extensions are already validated and well-formed, but may contain duplicates
+     */
+    private InternalLocaleBuilder setExtensions(List<String> bcpExtensions, String privateuse) {
+        clearExtensions();
+
+        if (bcpExtensions != null && bcpExtensions.size() > 0) {
+            HashSet<CaseInsensitiveChar> processedExtensions = new HashSet<CaseInsensitiveChar>(bcpExtensions.size());
+            for (String bcpExt : bcpExtensions) {
+                CaseInsensitiveChar key = new CaseInsensitiveChar(bcpExt.charAt(0));
+                // ignore duplicates
+                if (!processedExtensions.contains(key)) {
+                    // each extension string contains singleton, e.g. "a-abc-def"
+                    if (UnicodeLocaleExtension.isSingletonChar(key.value())) {
+                        setUnicodeLocaleExtension(bcpExt.substring(2));
+                    } else {
+                        if (_extensions == null) {
+                            _extensions = new HashMap<CaseInsensitiveChar, String>(4);
+                        }
+                        _extensions.put(key, bcpExt.substring(2));
+                    }
+                }
+            }
+        }
+        if (privateuse != null && privateuse.length() > 0) {
+            // privateuse string contains prefix, e.g. "x-abc-def"
+            if (_extensions == null) {
+                _extensions = new HashMap<CaseInsensitiveChar, String>(1);
+            }
+            _extensions.put(new CaseInsensitiveChar(privateuse.charAt(0)), privateuse.substring(2));
+        }
+
+        return this;
+    }
+
+    /*
+     * Reset Builder's internal state with the given language tag
+     */
+    public InternalLocaleBuilder setLanguageTag(LanguageTag langtag) {
+        clear();
+        if (langtag.getExtlangs().size() > 0) {
+            _language = langtag.getExtlangs().get(0);
+        } else {
+            String language = langtag.getLanguage();
+            if (!language.equals(LanguageTag.UNDETERMINED)) {
+                _language = language;
+            }
+        }
+        _script = langtag.getScript();
+        _region = langtag.getRegion();
+
+        List<String> bcpVariants = langtag.getVariants();
+        if (bcpVariants.size() > 0) {
+            StringBuilder var = new StringBuilder(bcpVariants.get(0));
+            for (int i = 1; i < bcpVariants.size(); i++) {
+                var.append(BaseLocale.SEP).append(bcpVariants.get(i));
+            }
+            _variant = var.toString();
+        }
+
+        setExtensions(langtag.getExtensions(), langtag.getPrivateuse());
+
+        return this;
+    }
+
+    public InternalLocaleBuilder setLocale(BaseLocale base, LocaleExtensions extensions) throws LocaleSyntaxException {
+        String language = base.getLanguage();
+        String script = base.getScript();
+        String region = base.getRegion();
+        String variant = base.getVariant();
+
+        if (JDKIMPL) {
+            // Special backward compatibility support
+
+            // Exception 1 - ja_JP_JP
+            if (language.equals("ja") && region.equals("JP") && variant.equals("JP")) {
+                // When locale ja_JP_JP is created, ca-japanese is always there.
+                // The builder ignores the variant "JP"
+                assert("japanese".equals(extensions.getUnicodeLocaleType("ca")));
+                variant = "";
+            }
+            // Exception 2 - th_TH_TH
+            else if (language.equals("th") && region.equals("TH") && variant.equals("TH")) {
+                // When locale th_TH_TH is created, nu-thai is always there.
+                // The builder ignores the variant "TH"
+                assert("thai".equals(extensions.getUnicodeLocaleType("nu")));
+                variant = "";
+            }
+            // Exception 3 - no_NO_NY
+            else if (language.equals("no") && region.equals("NO") && variant.equals("NY")) {
+                // no_NO_NY is a valid locale and used by Java 6 or older versions.
+                // The build ignores the variant "NY" and change the language to "nn".
+                language = "nn";
+                variant = "";
+            }
+        }
+
+        // Validate base locale fields before updating internal state.
+        // LocaleExtensions always store validated/canonicalized values,
+        // so no checks are necessary.
+        if (language.length() > 0 && !LanguageTag.isLanguage(language)) {
+            throw new LocaleSyntaxException("Ill-formed language: " + language);
+        }
+
+        if (script.length() > 0 && !LanguageTag.isScript(script)) {
+            throw new LocaleSyntaxException("Ill-formed script: " + script);
+        }
+
+        if (region.length() > 0 && !LanguageTag.isRegion(region)) {
+            throw new LocaleSyntaxException("Ill-formed region: " + region);
+        }
+
+        if (variant.length() > 0) {
+            int errIdx = checkVariants(variant, BaseLocale.SEP);
+            if (errIdx != -1) {
+                throw new LocaleSyntaxException("Ill-formed variant: " + variant, errIdx);
+            }
+        }
+
+        // The input locale is validated at this point.
+        // Now, updating builder's internal fields.
+        _language = language;
+        _script = script;
+        _region = region;
+        _variant = variant;
+        clearExtensions();
+
+        Set<Character> extKeys = (extensions == null) ? null : extensions.getKeys();
+        if (extKeys != null) {
+            // map extensions back to builder's internal format
+            for (Character key : extKeys) {
+                Extension e = extensions.getExtension(key);
+                if (e instanceof UnicodeLocaleExtension) {
+                    UnicodeLocaleExtension ue = (UnicodeLocaleExtension)e;
+                    for (String uatr : ue.getUnicodeLocaleAttributes()) {
+                        if (_uattributes == null) {
+                            _uattributes = new HashSet<CaseInsensitiveString>(4);
+                        }
+                        _uattributes.add(new CaseInsensitiveString(uatr));
+                    }
+                    for (String ukey : ue.getUnicodeLocaleKeys()) {
+                        if (_ukeywords == null) {
+                            _ukeywords = new HashMap<CaseInsensitiveString, String>(4);
+                        }
+                        _ukeywords.put(new CaseInsensitiveString(ukey), ue.getUnicodeLocaleType(ukey));
+                    }
+                } else {
+                    if (_extensions == null) {
+                        _extensions = new HashMap<CaseInsensitiveChar, String>(4);
+                    }
+                    _extensions.put(new CaseInsensitiveChar(key.charValue()), e.getValue());
+                }
+            }
+        }
+        return this;
+    }
+
+    public InternalLocaleBuilder clear() {
+        _language = "";
+        _script = "";
+        _region = "";
+        _variant = "";
+        clearExtensions();
+        return this;
+    }
+
+    public InternalLocaleBuilder clearExtensions() {
+        if (_extensions != null) {
+            _extensions.clear();
+        }
+        if (_uattributes != null) {
+            _uattributes.clear();
+        }
+        if (_ukeywords != null) {
+            _ukeywords.clear();
+        }
+        return this;
+    }
+
+    public BaseLocale getBaseLocale() {
+        String language = _language;
+        String script = _script;
+        String region = _region;
+        String variant = _variant;
+
+        // Special private use subtag sequence identified by "lvariant" will be
+        // interpreted as Java variant.
+        if (_extensions != null) {
+            String privuse = _extensions.get(PRIVUSE_KEY);
+            if (privuse != null) {
+                StringTokenIterator itr = new StringTokenIterator(privuse, LanguageTag.SEP);
+                boolean sawPrefix = false;
+                int privVarStart = -1;
+                while (!itr.isDone()) {
+                    if (sawPrefix) {
+                        privVarStart = itr.currentStart();
+                        break;
+                    }
+                    if (AsciiUtil.caseIgnoreMatch(itr.current(), LanguageTag.PRIVUSE_VARIANT_PREFIX)) {
+                        sawPrefix = true;
+                    }
+                    itr.next();
+                }
+                if (privVarStart != -1) {
+                    StringBuilder sb = new StringBuilder(variant);
+                    if (sb.length() != 0) {
+                        sb.append(BaseLocale.SEP);
+                    }
+                    sb.append(privuse.substring(privVarStart).replaceAll(LanguageTag.SEP, BaseLocale.SEP));
+                    variant = sb.toString();
+                }
+            }
+        }
+
+        return BaseLocale.getInstance(language, script, region, variant);
+    }
+
+    public LocaleExtensions getLocaleExtensions() {
+        if ((_extensions == null || _extensions.size() == 0)
+                && (_uattributes == null || _uattributes.size() == 0)
+                && (_ukeywords == null || _ukeywords.size() == 0)) {
+            return LocaleExtensions.EMPTY_EXTENSIONS;
+        }
+
+        return new LocaleExtensions(_extensions, _uattributes, _ukeywords);
+    }
+
+    /*
+     * Remove special private use subtag sequence identified by "lvariant"
+     * and return the rest. Only used by LocaleExtensions
+     */
+    static String removePrivateuseVariant(String privuseVal) {
+        StringTokenIterator itr = new StringTokenIterator(privuseVal, LanguageTag.SEP);
+
+        // Note: privateuse value "abc-lvariant" is unchanged
+        // because no subtags after "lvariant".
+
+        int prefixStart = -1;
+        boolean sawPrivuseVar = false;
+        while (!itr.isDone()) {
+            if (prefixStart != -1) {
+                // Note: privateuse value "abc-lvariant" is unchanged
+                // because no subtags after "lvariant".
+                sawPrivuseVar = true;
+                break;
+            }
+            if (AsciiUtil.caseIgnoreMatch(itr.current(), LanguageTag.PRIVUSE_VARIANT_PREFIX)) {
+                prefixStart = itr.currentStart();
+            }
+            itr.next();
+        }
+        if (!sawPrivuseVar) {
+            return privuseVal;
+        }
+
+        assert(prefixStart == 0 || prefixStart > 1);
+        return (prefixStart == 0) ? null : privuseVal.substring(0, prefixStart -1);
+    }
+
+    /*
+     * Check if the given variant subtags separated by the given
+     * separator(s) are valid
+     */
+    private int checkVariants(String variants, String sep) {
+        StringTokenIterator itr = new StringTokenIterator(variants, sep);
+        while (!itr.isDone()) {
+            String s = itr.current();
+            if (!LanguageTag.isVariant(s)) {
+                return itr.currentStart();
+            }
+            itr.next();
+        }
+        return -1;
+    }
+
+    /*
+     * Private methods parsing Unicode Locale Extension subtags.
+     * Duplicated attributes/keywords will be ignored.
+     * The input must be a valid extension subtags (excluding singleton).
+     */
+    private void setUnicodeLocaleExtension(String subtags) {
+        // wipe out existing attributes/keywords
+        if (_uattributes != null) {
+            _uattributes.clear();
+        }
+        if (_ukeywords != null) {
+            _ukeywords.clear();
+        }
+
+        StringTokenIterator itr = new StringTokenIterator(subtags, LanguageTag.SEP);
+
+        // parse attributes
+        while (!itr.isDone()) {
+            if (!UnicodeLocaleExtension.isAttribute(itr.current())) {
+                break;
+            }
+            if (_uattributes == null) {
+                _uattributes = new HashSet<CaseInsensitiveString>(4);
+            }
+            _uattributes.add(new CaseInsensitiveString(itr.current()));
+            itr.next();
+        }
+
+        // parse keywords
+        CaseInsensitiveString key = null;
+        String type;
+        int typeStart = -1;
+        int typeEnd = -1;
+        while (!itr.isDone()) {
+            if (key != null) {
+                if (UnicodeLocaleExtension.isKey(itr.current())) {
+                    // next keyword - emit previous one
+                    assert(typeStart == -1 || typeEnd != -1);
+                    type = (typeStart == -1) ? "" : subtags.substring(typeStart, typeEnd);
+                    if (_ukeywords == null) {
+                        _ukeywords = new HashMap<CaseInsensitiveString, String>(4);
+                    }
+                    _ukeywords.put(key, type);
+
+                    // reset keyword info
+                    CaseInsensitiveString tmpKey = new CaseInsensitiveString(itr.current());
+                    key = _ukeywords.containsKey(tmpKey) ? null : tmpKey;
+                    typeStart = typeEnd = -1;
+                } else {
+                    if (typeStart == -1) {
+                        typeStart = itr.currentStart();
+                    }
+                    typeEnd = itr.currentEnd();
+                }
+            } else if (UnicodeLocaleExtension.isKey(itr.current())) {
+                // 1. first keyword or
+                // 2. next keyword, but previous one was duplicate
+                key = new CaseInsensitiveString(itr.current());
+                if (_ukeywords != null && _ukeywords.containsKey(key)) {
+                    // duplicate
+                    key = null;
+                }
+            }
+
+            if (!itr.hasNext()) {
+                if (key != null) {
+                    // last keyword
+                    assert(typeStart == -1 || typeEnd != -1);
+                    type = (typeStart == -1) ? "" : subtags.substring(typeStart, typeEnd);
+                    if (_ukeywords == null) {
+                        _ukeywords = new HashMap<CaseInsensitiveString, String>(4);
+                    }
+                    _ukeywords.put(key, type);
+                }
+                break;
+            }
+
+            itr.next();
+        }
+    }
+
+    static class CaseInsensitiveString {
+        private String _s;
+
+        CaseInsensitiveString(String s) {
+            _s = s;
+        }
+
+        public String value() {
+            return _s;
+        }
+
+        public int hashCode() {
+            return AsciiUtil.toLowerString(_s).hashCode();
+        }
+
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (!(obj instanceof CaseInsensitiveString)) {
+                return false;
+            }
+            return AsciiUtil.caseIgnoreMatch(_s, ((CaseInsensitiveString)obj).value());
+        }
+    }
+
+    static class CaseInsensitiveChar {
+        private char _c;
+
+        CaseInsensitiveChar(char c) {
+            _c = c;
+        }
+
+        public char value() {
+            return _c;
+        }
+
+        public int hashCode() {
+            return AsciiUtil.toLower(_c);
+        }
+
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (!(obj instanceof CaseInsensitiveChar)) {
+                return false;
+            }
+            return _c ==  AsciiUtil.toLower(((CaseInsensitiveChar)obj).value());
+        }
+
+    }
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/locale/LanguageTag.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/locale/LanguageTag.java
new file mode 100644
index 0000000..e889a7d
--- /dev/null
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/locale/LanguageTag.java
@@ -0,0 +1,720 @@
+/*
+ *******************************************************************************
+ * Copyright (C) 2010-2011, International Business Machines Corporation and    *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+package com.ibm.icu.impl.locale;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class LanguageTag {
+    private static final boolean JDKIMPL = false;
+
+    //
+    // static fields
+    //
+    public static final String SEP = "-";
+    public static final String PRIVATEUSE = "x";
+    public static String UNDETERMINED = "und";
+    public static final String PRIVUSE_VARIANT_PREFIX = "lvariant";
+
+    //
+    // Language subtag fields
+    //
+    private String _language = "";      // language subtag
+    private String _script = "";        // script subtag
+    private String _region = "";        // region subtag
+    private String _privateuse = "";    // privateuse
+
+    private List<String> _extlangs = Collections.emptyList();   // extlang subtags
+    private List<String> _variants = Collections.emptyList();   // variant subtags
+    private List<String> _extensions = Collections.emptyList(); // extensions
+
+    // Map contains grandfathered tags and its preferred mappings from
+    // http://www.ietf.org/rfc/rfc5646.txt
+    private static final Map<AsciiUtil.CaseInsensitiveKey, String[]> GRANDFATHERED =
+        new HashMap<AsciiUtil.CaseInsensitiveKey, String[]>();
+
+    static {
+        // grandfathered = irregular           ; non-redundant tags registered
+        //               / regular             ; during the RFC 3066 era
+        //
+        // irregular     = "en-GB-oed"         ; irregular tags do not match
+        //               / "i-ami"             ; the 'langtag' production and
+        //               / "i-bnn"             ; would not otherwise be
+        //               / "i-default"         ; considered 'well-formed'
+        //               / "i-enochian"        ; These tags are all valid,
+        //               / "i-hak"             ; but most are deprecated
+        //               / "i-klingon"         ; in favor of more modern
+        //               / "i-lux"             ; subtags or subtag
+        //               / "i-mingo"           ; combination
+        //               / "i-navajo"
+        //               / "i-pwn"
+        //               / "i-tao"
+        //               / "i-tay"
+        //               / "i-tsu"
+        //               / "sgn-BE-FR"
+        //               / "sgn-BE-NL"
+        //               / "sgn-CH-DE"
+        //
+        // regular       = "art-lojban"        ; these tags match the 'langtag'
+        //               / "cel-gaulish"       ; production, but their subtags
+        //               / "no-bok"            ; are not extended language
+        //               / "no-nyn"            ; or variant subtags: their meaning
+        //               / "zh-guoyu"          ; is defined by their registration
+        //               / "zh-hakka"          ; and all of these are deprecated
+        //               / "zh-min"            ; in favor of a more modern
+        //               / "zh-min-nan"        ; subtag or sequence of subtags
+        //               / "zh-xiang"
+
+        final String[][] entries = {
+          //{"tag",         "preferred"},
+            {"art-lojban",  "jbo"},
+            {"cel-gaulish", "xtg-x-cel-gaulish"},   // fallback
+            {"en-GB-oed",   "en-GB-x-oed"},         // fallback
+            {"i-ami",       "ami"},
+            {"i-bnn",       "bnn"},
+            {"i-default",   "en-x-i-default"},      // fallback
+            {"i-enochian",  "und-x-i-enochian"},    // fallback
+            {"i-hak",       "hak"},
+            {"i-klingon",   "tlh"},
+            {"i-lux",       "lb"},
+            {"i-mingo",     "see-x-i-mingo"},       // fallback
+            {"i-navajo",    "nv"},
+            {"i-pwn",       "pwn"},
+            {"i-tao",       "tao"},
+            {"i-tay",       "tay"},
+            {"i-tsu",       "tsu"},
+            {"no-bok",      "nb"},
+            {"no-nyn",      "nn"},
+            {"sgn-BE-FR",   "sfb"},
+            {"sgn-BE-NL",   "vgt"},
+            {"sgn-CH-DE",   "sgg"},
+            {"zh-guoyu",    "cmn"},
+            {"zh-hakka",    "hak"},
+            {"zh-min",      "nan-x-zh-min"},        // fallback
+            {"zh-min-nan",  "nan"},
+            {"zh-xiang",    "hsn"},
+        };
+        for (String[] e : entries) {
+            GRANDFATHERED.put(new AsciiUtil.CaseInsensitiveKey(e[0]), e);
+        }
+    }
+
+    private LanguageTag() {
+    }
+
+    /*
+     * BNF in RFC5464
+     *  
+     * Language-Tag  = langtag             ; normal language tags
+     *               / privateuse          ; private use tag
+     *               / grandfathered       ; grandfathered tags
+     *
+     * 
+     * langtag       = language
+     *                 ["-" script]
+     *                 ["-" region]
+     *                 *("-" variant)
+     *                 *("-" extension)
+     *                 ["-" privateuse]
+     * 
+     * language      = 2*3ALPHA            ; shortest ISO 639 code
+     *                 ["-" extlang]       ; sometimes followed by
+     *                                     ; extended language subtags
+     *               / 4ALPHA              ; or reserved for future use
+     *               / 5*8ALPHA            ; or registered language subtag
+     * 
+     * extlang       = 3ALPHA              ; selected ISO 639 codes
+     *                 *2("-" 3ALPHA)      ; permanently reserved
+     * 
+     * script        = 4ALPHA              ; ISO 15924 code
+     * 
+     * region        = 2ALPHA              ; ISO 3166-1 code
+     *               / 3DIGIT              ; UN M.49 code
+     * 
+     * variant       = 5*8alphanum         ; registered variants
+     *               / (DIGIT 3alphanum)
+     * 
+     * extension     = singleton 1*("-" (2*8alphanum))
+     * 
+     *                                     ; Single alphanumerics
+     *                                     ; "x" reserved for private use
+     * singleton     = DIGIT               ; 0 - 9
+     *               / %x41-57             ; A - W
+     *               / %x59-5A             ; Y - Z
+     *               / %x61-77             ; a - w
+     *               / %x79-7A             ; y - z
+     * 
+     * privateuse    = "x" 1*("-" (1*8alphanum))
+     * 
+     */
+    public static LanguageTag parse(String languageTag, ParseStatus sts) {
+        if (sts == null) {
+            sts = new ParseStatus();
+        } else {
+            sts.reset();
+        }
+
+        StringTokenIterator itr;
+
+        // Check if the tag is grandfathered
+        String[] gfmap = GRANDFATHERED.get(new AsciiUtil.CaseInsensitiveKey(languageTag));
+        if (gfmap != null) {
+            // use preferred mapping
+            itr = new StringTokenIterator(gfmap[1], SEP);
+        } else {
+            itr = new StringTokenIterator(languageTag, SEP);
+        }
+
+        LanguageTag tag = new LanguageTag();
+
+        // langtag must start with either language or privateuse
+        if (tag.parseLanguage(itr, sts)) {
+            tag.parseExtlangs(itr, sts);
+            tag.parseScript(itr, sts);
+            tag.parseRegion(itr, sts);
+            tag.parseVariants(itr, sts);
+            tag.parseExtensions(itr, sts);
+        }
+        tag.parsePrivateuse(itr, sts);
+
+        if (!itr.isDone() && !sts.isError()) {
+            String s = itr.current();
+            sts._errorIndex = itr.currentStart();
+            if (s.length() == 0) {
+                sts._errorMsg = "Empty subtag";
+            } else {
+                sts._errorMsg = "Invalid subtag: " + s; 
+            }
+        }
+
+        return tag;
+    }
+
+    //
+    // Language subtag parsers
+    //
+
+    private boolean parseLanguage(StringTokenIterator itr, ParseStatus sts) {
+        if (itr.isDone() || sts.isError()) {
+            return false;
+        }
+
+        boolean found = false;
+
+        String s = itr.current();
+        if (isLanguage(s)) {
+            found = true;
+            _language = s;
+            sts._parseLength = itr.currentEnd();
+            itr.next();
+        }
+
+        return found;
+    }
+
+    private boolean parseExtlangs(StringTokenIterator itr, ParseStatus sts) {
+        if (itr.isDone() || sts.isError()) {
+            return false;
+        }
+
+        boolean found = false;
+
+        while (!itr.isDone()) {
+            String s = itr.current();
+            if (!isExtlang(s)) {
+                break;
+            }
+            found = true;
+            if (_extlangs.isEmpty()) {
+                _extlangs = new ArrayList<String>(3);
+            }
+            _extlangs.add(s);
+            sts._parseLength = itr.currentEnd();
+            itr.next();
+
+            if (_extlangs.size() == 3) {
+                // Maximum 3 extlangs
+                break;
+            }
+        }
+
+        return found;
+    }
+
+    private boolean parseScript(StringTokenIterator itr, ParseStatus sts) {
+        if (itr.isDone() || sts.isError()) {
+            return false;
+        }
+
+        boolean found = false;
+
+        String s = itr.current();
+        if (isScript(s)) {
+            found = true;
+            _script = s;
+            sts._parseLength = itr.currentEnd();
+            itr.next();
+        }
+
+        return found;
+    }
+
+    private boolean parseRegion(StringTokenIterator itr, ParseStatus sts) {
+        if (itr.isDone() || sts.isError()) {
+            return false;
+        }
+
+        boolean found = false;
+
+        String s = itr.current();
+        if (isRegion(s)) {
+            found = true;
+            _region = s;
+            sts._parseLength = itr.currentEnd();
+            itr.next();
+        }
+
+        return found;
+    }
+
+    private boolean parseVariants(StringTokenIterator itr, ParseStatus sts) {
+        if (itr.isDone() || sts.isError()) {
+            return false;
+        }
+
+        boolean found = false;
+
+        while (!itr.isDone()) {
+            String s = itr.current();
+            if (!isVariant(s)) {
+                break;
+            }
+            found = true;
+            if (_variants.isEmpty()) {
+                _variants = new ArrayList<String>(3);
+            }
+            _variants.add(s);
+            sts._parseLength = itr.currentEnd();
+            itr.next();
+        }
+
+        return found;
+    }
+
+    private boolean parseExtensions(StringTokenIterator itr, ParseStatus sts) {
+        if (itr.isDone() || sts.isError()) {
+            return false;
+        }
+
+        boolean found = false;
+
+        while (!itr.isDone()) {
+            String s = itr.current();
+            if (isExtensionSingleton(s)) {
+                int start = itr.currentStart();
+                String singleton = s;
+                StringBuilder sb = new StringBuilder(singleton);
+
+                itr.next();
+                while (!itr.isDone()) {
+                    s = itr.current();
+                    if (isExtensionSubtag(s)) {
+                        sb.append(SEP).append(s);
+                        sts._parseLength = itr.currentEnd();
+                    } else {
+                        break;
+                    }
+                    itr.next();
+                }
+
+                if (sts._parseLength <= start) {
+                    sts._errorIndex = start;
+                    sts._errorMsg = "Incomplete extension '" + singleton + "'";
+                    break;
+                }
+
+                if (_extensions.size() == 0) {
+                    _extensions = new ArrayList<String>(4);
+                }
+                _extensions.add(sb.toString());
+                found = true;
+            } else {
+                break;
+            }
+        }
+        return found;
+    }
+
+    private boolean parsePrivateuse(StringTokenIterator itr, ParseStatus sts) {
+        if (itr.isDone() || sts.isError()) {
+            return false;
+        }
+
+        boolean found = false;
+
+        String s = itr.current();
+        if (isPrivateusePrefix(s)) {
+            int start = itr.currentStart();
+            StringBuilder sb = new StringBuilder(s);
+
+            itr.next();
+            while (!itr.isDone()) {
+                s = itr.current();
+                if (!isPrivateuseSubtag(s)) {
+                    break;
+                }
+                sb.append(SEP).append(s);
+                sts._parseLength = itr.currentEnd();
+
+                itr.next();
+            }
+
+            if (sts._parseLength <= start) {
+                // need at least 1 private subtag
+                sts._errorIndex = start;
+                sts._errorMsg = "Incomplete privateuse";
+            } else {
+                _privateuse = sb.toString();
+                found = true;
+            }
+        }
+
+        return found;
+    }
+
+    public static LanguageTag parseLocale(BaseLocale baseLocale, LocaleExtensions localeExtensions) {
+        LanguageTag tag = new LanguageTag();
+
+        String language = baseLocale.getLanguage();
+        String script = baseLocale.getScript();
+        String region = baseLocale.getRegion();
+        String variant = baseLocale.getVariant();
+
+        boolean hasSubtag = false;
+
+        String privuseVar = null;   // store ill-formed variant subtags
+
+        if (language.length() > 0 && isLanguage(language)) {
+            // Convert a deprecated language code used by Java to
+            // a new code
+            if (language.equals("iw")) {
+                language = "he";
+            } else if (language.equals("ji")) {
+                language = "yi";
+            } else if (language.equals("in")) {
+                language = "id";
+            }
+            tag._language = language;
+        }
+
+        if (script.length() > 0 && isScript(script)) {
+            tag._script = canonicalizeScript(script);
+            hasSubtag = true;
+        }
+
+        if (region.length() > 0 && isRegion(region)) {
+            tag._region = canonicalizeRegion(region);
+            hasSubtag = true;
+        }
+
+        if (JDKIMPL) {
+            // Special handling for no_NO_NY - use nn_NO for language tag
+            if (tag._language.equals("no") && tag._region.equals("NO") && variant.equals("NY")) {
+                tag._language = "nn";
+                variant = "";
+            }
+        }
+
+        if (variant.length() > 0) {
+            List<String> variants = null;
+            StringTokenIterator varitr = new StringTokenIterator(variant, BaseLocale.SEP);
+            while (!varitr.isDone()) {
+                String var = varitr.current();
+                if (!isVariant(var)) {
+                    break;
+                }
+                if (variants == null) {
+                    variants = new ArrayList<String>();
+                }
+                if (JDKIMPL) {
+                    variants.add(var);  // Do not canonicalize!
+                } else {
+                    variants.add(canonicalizeVariant(var));
+                }
+                varitr.next();
+            }
+            if (variants != null) {
+                tag._variants = variants;
+                hasSubtag = true;
+            }
+            if (!varitr.isDone()) {
+                // ill-formed variant subtags
+                StringBuilder buf = new StringBuilder();
+                while (!varitr.isDone()) {
+                    String prvv = varitr.current();
+                    if (!isPrivateuseSubtag(prvv)) {
+                        // cannot use private use subtag - truncated
+                        break;
+                    }
+                    if (buf.length() > 0) {
+                        buf.append(SEP);
+                    }
+                    if (!JDKIMPL) {
+                        prvv = AsciiUtil.toLowerString(prvv);
+                    }
+                    buf.append(prvv);
+                    varitr.next();
+                }
+                if (buf.length() > 0) {
+                    privuseVar = buf.toString();
+                }
+            }
+        }
+
+        List<String> extensions = null;
+        String privateuse = null;
+
+        Set<Character> locextKeys = localeExtensions.getKeys();
+        for (Character locextKey : locextKeys) {
+            Extension ext = localeExtensions.getExtension(locextKey);
+            if (isPrivateusePrefixChar(locextKey.charValue())) {
+                privateuse = ext.getValue();
+            } else {
+                if (extensions == null) {
+                    extensions = new ArrayList<String>();
+                }
+                extensions.add(locextKey.toString() + SEP + ext.getValue());
+            }
+        }
+
+        if (extensions != null) {
+            tag._extensions = extensions;
+            hasSubtag = true;
+        }
+
+        // append ill-formed variant subtags to private use
+        if (privuseVar != null) {
+            if (privateuse == null) {
+                privateuse = PRIVUSE_VARIANT_PREFIX + SEP + privuseVar;
+            } else {
+                privateuse = privateuse + SEP + PRIVUSE_VARIANT_PREFIX + SEP + privuseVar.replace(BaseLocale.SEP, SEP);
+            }
+        }
+
+        if (privateuse != null) {
+            tag._privateuse = privateuse;
+        }
+
+        if (tag._language.length() == 0 && (hasSubtag || privateuse == null)) {
+            // use lang "und" when 1) no language is available AND
+            // 2) any of other subtags other than private use are available or
+            // no private use tag is available
+            tag._language = UNDETERMINED;
+        }
+
+        return tag;
+    }
+
+    //
+    // Getter methods for language subtag fields
+    //
+
+    public String getLanguage() {
+        return _language;
+    }
+
+    public List<String> getExtlangs() {
+        return Collections.unmodifiableList(_extlangs);
+    }
+
+    public String getScript() {
+        return _script;
+    }
+
+    public String getRegion() {
+        return _region;
+    }
+
+    public List<String> getVariants() {
+        return Collections.unmodifiableList(_variants);
+    }
+
+    public List<String> getExtensions() {
+        return Collections.unmodifiableList(_extensions);
+    }
+
+    public String getPrivateuse() {
+        return _privateuse;
+    }
+
+    //
+    // Language subtag syntax checking methods
+    //
+
+    public static boolean isLanguage(String s) {
+        // language      = 2*3ALPHA            ; shortest ISO 639 code
+        //                 ["-" extlang]       ; sometimes followed by
+        //                                     ;   extended language subtags
+        //               / 4ALPHA              ; or reserved for future use
+        //               / 5*8ALPHA            ; or registered language subtag
+        return (s.length() >= 2) && (s.length() <= 8) && AsciiUtil.isAlphaString(s);
+    }
+
+    public static boolean isExtlang(String s) {
+        // extlang       = 3ALPHA              ; selected ISO 639 codes
+        //                 *2("-" 3ALPHA)      ; permanently reserved
+        return (s.length() == 3) && AsciiUtil.isAlphaString(s);
+    }
+
+    public static boolean isScript(String s) {
+        // script        = 4ALPHA              ; ISO 15924 code
+        return (s.length() == 4) && AsciiUtil.isAlphaString(s);
+    }
+
+    public static boolean isRegion(String s) {
+        // region        = 2ALPHA              ; ISO 3166-1 code
+        //               / 3DIGIT              ; UN M.49 code
+        return ((s.length() == 2) && AsciiUtil.isAlphaString(s))
+                || ((s.length() == 3) && AsciiUtil.isNumericString(s));
+    }
+
+    public static boolean isVariant(String s) {
+        // variant       = 5*8alphanum         ; registered variants
+        //               / (DIGIT 3alphanum)
+        int len = s.length();
+        if (len >= 5 && len <= 8) {
+            return AsciiUtil.isAlphaNumericString(s);
+        }
+        if (len == 4) {
+            return AsciiUtil.isNumeric(s.charAt(0))
+                    && AsciiUtil.isAlphaNumeric(s.charAt(1))
+                    && AsciiUtil.isAlphaNumeric(s.charAt(2))
+                    && AsciiUtil.isAlphaNumeric(s.charAt(3));
+        }
+        return false;
+    }
+
+    public static boolean isExtensionSingleton(String s) {
+        // singleton     = DIGIT               ; 0 - 9
+        //               / %x41-57             ; A - W
+        //               / %x59-5A             ; Y - Z
+        //               / %x61-77             ; a - w
+        //               / %x79-7A             ; y - z
+
+        return (s.length() == 1)
+                && AsciiUtil.isAlphaString(s)
+                && !AsciiUtil.caseIgnoreMatch(PRIVATEUSE, s);
+    }
+
+    public static boolean isExtensionSingletonChar(char c) {
+        return isExtensionSingleton(String.valueOf(c));
+    }
+
+    public static boolean isExtensionSubtag(String s) {
+        // extension     = singleton 1*("-" (2*8alphanum))
+        return (s.length() >= 2) && (s.length() <= 8) && AsciiUtil.isAlphaNumericString(s);
+    }
+
+    public static boolean isPrivateusePrefix(String s) {
+        // privateuse    = "x" 1*("-" (1*8alphanum))
+        return (s.length() == 1)
+                && AsciiUtil.caseIgnoreMatch(PRIVATEUSE, s);
+    }
+
+    public static boolean isPrivateusePrefixChar(char c) {
+        return (AsciiUtil.caseIgnoreMatch(PRIVATEUSE, String.valueOf(c)));
+    }
+
+    public static boolean isPrivateuseSubtag(String s) {
+        // privateuse    = "x" 1*("-" (1*8alphanum))
+        return (s.length() >= 1) && (s.length() <= 8) && AsciiUtil.isAlphaNumericString(s);
+    }
+
+    //
+    // Language subtag canonicalization methods
+    //
+
+    public static String canonicalizeLanguage(String s) {
+        return AsciiUtil.toLowerString(s);
+    }
+
+    public static String canonicalizeExtlang(String s) {
+        return AsciiUtil.toLowerString(s);
+    }
+
+    public static String canonicalizeScript(String s) {
+        return AsciiUtil.toTitleString(s);
+    }
+
+    public static String canonicalizeRegion(String s) {
+        return AsciiUtil.toUpperString(s);
+    }
+
+    public static String canonicalizeVariant(String s) {
+        return AsciiUtil.toLowerString(s);
+    }
+
+    public static String canonicalizeExtension(String s) {
+        return AsciiUtil.toLowerString(s);
+    }
+
+    public static String canonicalizeExtensionSingleton(String s) {
+        return AsciiUtil.toLowerString(s);
+    }
+
+    public static String canonicalizeExtensionSubtag(String s) {
+        return AsciiUtil.toLowerString(s);
+    }
+
+    public static String canonicalizePrivateuse(String s) {
+        return AsciiUtil.toLowerString(s);
+    }
+
+    public static String canonicalizePrivateuseSubtag(String s) {
+        return AsciiUtil.toLowerString(s);
+    }
+
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+
+        if (_language.length() > 0) {
+            sb.append(_language);
+
+            for (String extlang : _extlangs) {
+                sb.append(SEP).append(extlang);
+            }
+
+            if (_script.length() > 0) {
+                sb.append(SEP).append(_script);
+            }
+
+            if (_region.length() > 0) {
+                sb.append(SEP).append(_region);
+            }
+
+            for (String variant : _extlangs) {
+                sb.append(SEP).append(variant);
+            }
+
+            for (String extension : _extensions) {
+                sb.append(SEP).append(extension);
+            }
+        }
+        if (_privateuse.length() > 0) {
+            if (sb.length() > 0) {
+                sb.append(SEP);
+            }
+            sb.append(_privateuse);
+        }
+
+        return sb.toString();
+    }
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/locale/LocaleExtensions.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/locale/LocaleExtensions.java
new file mode 100644
index 0000000..fc81e0d
--- /dev/null
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/locale/LocaleExtensions.java
@@ -0,0 +1,221 @@
+/*
+ *******************************************************************************
+ * Copyright (C) 2009-2011, International Business Machines Corporation and    *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+package com.ibm.icu.impl.locale;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import com.ibm.icu.impl.locale.InternalLocaleBuilder.CaseInsensitiveChar;
+import com.ibm.icu.impl.locale.InternalLocaleBuilder.CaseInsensitiveString;
+
+
+public class LocaleExtensions {
+
+    private SortedMap<Character, Extension> _map;
+    private String _id;
+
+    private static final SortedMap<Character, Extension> EMPTY_MAP =
+        Collections.unmodifiableSortedMap(new TreeMap<Character, Extension>());
+
+    public static final LocaleExtensions EMPTY_EXTENSIONS;
+    public static final LocaleExtensions CALENDAR_JAPANESE;
+    public static final LocaleExtensions NUMBER_THAI;
+
+    static {
+        EMPTY_EXTENSIONS = new LocaleExtensions();
+        EMPTY_EXTENSIONS._id = "";
+        EMPTY_EXTENSIONS._map = EMPTY_MAP;
+
+        CALENDAR_JAPANESE = new LocaleExtensions();
+        CALENDAR_JAPANESE._id = "u-ca-japanese";
+        CALENDAR_JAPANESE._map = new TreeMap<Character, Extension>();
+        CALENDAR_JAPANESE._map.put(Character.valueOf(UnicodeLocaleExtension.SINGLETON), UnicodeLocaleExtension.CA_JAPANESE);
+
+        NUMBER_THAI = new LocaleExtensions();
+        NUMBER_THAI._id = "u-nu-thai";
+        NUMBER_THAI._map = new TreeMap<Character, Extension>();
+        NUMBER_THAI._map.put(Character.valueOf(UnicodeLocaleExtension.SINGLETON), UnicodeLocaleExtension.NU_THAI);
+    }
+
+    private LocaleExtensions() {
+    }
+
+    /*
+     * Package local constructor, only used by InternalLocaleBuilder.
+     */
+    LocaleExtensions(Map<CaseInsensitiveChar, String> extensions,
+            Set<CaseInsensitiveString> uattributes, Map<CaseInsensitiveString, String> ukeywords) {
+        boolean hasExtension = (extensions != null && extensions.size() > 0);
+        boolean hasUAttributes = (uattributes != null && uattributes.size() > 0);
+        boolean hasUKeywords = (ukeywords != null && ukeywords.size() > 0);
+
+        if (!hasExtension && !hasUAttributes && !hasUKeywords) {
+            _map = EMPTY_MAP;
+            _id = "";
+            return;
+        }
+
+        // Build extension map
+        _map = new TreeMap<Character, Extension>();
+        if (hasExtension) {
+            for (Entry<CaseInsensitiveChar, String> ext : extensions.entrySet()) {
+                char key = AsciiUtil.toLower(ext.getKey().value());
+                String value = ext.getValue();
+
+                if (LanguageTag.isPrivateusePrefixChar(key)) {
+                    // we need to exclude special variant in privuateuse, e.g. "x-abc-lvariant-DEF"
+                    value = InternalLocaleBuilder.removePrivateuseVariant(value);
+                    if (value == null) {
+                        continue;
+                    }
+                }
+
+                Extension e = new Extension(key, AsciiUtil.toLowerString(value));
+                _map.put(Character.valueOf(key), e);
+            }
+        }
+
+        if (hasUAttributes || hasUKeywords) {
+            TreeSet<String> uaset = null;
+            TreeMap<String, String> ukmap = null;
+
+            if (hasUAttributes) {
+                uaset = new TreeSet<String>();
+                for (CaseInsensitiveString cis : uattributes) {
+                    uaset.add(AsciiUtil.toLowerString(cis.value()));
+                }
+            }
+
+            if (hasUKeywords) {
+                ukmap = new TreeMap<String, String>();
+                for (Entry<CaseInsensitiveString, String> kwd : ukeywords.entrySet()) {
+                    String key = AsciiUtil.toLowerString(kwd.getKey().value());
+                    String type = AsciiUtil.toLowerString(kwd.getValue());
+                    ukmap.put(key, type);
+                }
+            }
+
+            UnicodeLocaleExtension ule = new UnicodeLocaleExtension(uaset, ukmap);
+            _map.put(Character.valueOf(UnicodeLocaleExtension.SINGLETON), ule);
+        }
+
+        if (_map.size() == 0) {
+            // this could happen when only privuateuse with special variant
+            _map = EMPTY_MAP;
+            _id = "";
+        } else {
+            _id = toID(_map);
+        }
+    }
+
+    public Set<Character> getKeys() {
+        return Collections.unmodifiableSet(_map.keySet());
+    }
+
+    public Extension getExtension(Character key) {
+        return _map.get(Character.valueOf(AsciiUtil.toLower(key.charValue())));
+    }
+
+    public String getExtensionValue(Character key) {
+        Extension ext = _map.get(Character.valueOf(AsciiUtil.toLower(key.charValue())));
+        if (ext == null) {
+            return null;
+        }
+        return ext.getValue();
+    }
+
+    public Set<String> getUnicodeLocaleAttributes() {
+        Extension ext = _map.get(Character.valueOf(UnicodeLocaleExtension.SINGLETON));
+        if (ext == null) {
+            return Collections.emptySet();
+        }
+        assert (ext instanceof UnicodeLocaleExtension);
+        return ((UnicodeLocaleExtension)ext).getUnicodeLocaleAttributes();
+    }
+
+    public Set<String> getUnicodeLocaleKeys() {
+        Extension ext = _map.get(Character.valueOf(UnicodeLocaleExtension.SINGLETON));
+        if (ext == null) {
+            return Collections.emptySet();
+        }
+        assert (ext instanceof UnicodeLocaleExtension);
+        return ((UnicodeLocaleExtension)ext).getUnicodeLocaleKeys();
+    }
+
+    public String getUnicodeLocaleType(String unicodeLocaleKey) {
+        Extension ext = _map.get(Character.valueOf(UnicodeLocaleExtension.SINGLETON));
+        if (ext == null) {
+            return null;
+        }
+        assert (ext instanceof UnicodeLocaleExtension);
+        return ((UnicodeLocaleExtension)ext).getUnicodeLocaleType(AsciiUtil.toLowerString(unicodeLocaleKey));
+    }
+
+    public boolean isEmpty() {
+        return _map.isEmpty();
+    }
+
+    public static boolean isValidKey(char c) {
+        return LanguageTag.isExtensionSingletonChar(c) || LanguageTag.isPrivateusePrefixChar(c);
+    }
+
+    public static boolean isValidUnicodeLocaleKey(String ukey) {
+        return UnicodeLocaleExtension.isKey(ukey);
+    }
+
+    private static String toID(SortedMap<Character, Extension> map) {
+        StringBuilder buf = new StringBuilder();
+        Extension privuse = null;
+        for (Entry<Character, Extension> entry : map.entrySet()) {
+            char singleton = entry.getKey().charValue();
+            Extension extension = entry.getValue();
+            if (LanguageTag.isPrivateusePrefixChar(singleton)) {
+                privuse = extension;
+            } else {
+                if (buf.length() > 0) {
+                    buf.append(LanguageTag.SEP);
+                }
+                buf.append(extension);
+            }
+        }
+        if (privuse != null) {
+            if (buf.length() > 0) {
+                buf.append(LanguageTag.SEP);
+            }
+            buf.append(privuse);
+        }
+        return buf.toString();
+    }
+
+
+    public String toString() {
+        return _id;
+    }
+
+    public String getID() {
+        return _id;
+    }
+
+    public int hashCode() {
+        return _id.hashCode();
+    }
+
+    public boolean equals(Object other) {
+        if (this == other) {
+            return true;
+        }
+        if (!(other instanceof LocaleExtensions)) {
+            return false;
+        }
+        return this._id.equals(((LocaleExtensions)other)._id);
+    }
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/locale/LocaleObjectCache.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/locale/LocaleObjectCache.java
new file mode 100644
index 0000000..d75519c
--- /dev/null
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/locale/LocaleObjectCache.java
@@ -0,0 +1,83 @@
+/*
+ *******************************************************************************
+ * Copyright (C) 2009-2011, International Business Machines Corporation and    *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+package com.ibm.icu.impl.locale;
+
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.SoftReference;
+import java.util.concurrent.ConcurrentHashMap;
+
+public abstract class LocaleObjectCache<K, V> {
+    private ConcurrentHashMap<K, CacheEntry<K, V>> _map;
+    private ReferenceQueue<V> _queue = new ReferenceQueue<V>();
+
+    public LocaleObjectCache() {
+        this(16, 0.75f, 16);
+    }
+
+    public LocaleObjectCache(int initialCapacity, float loadFactor, int concurrencyLevel) {
+        _map = new ConcurrentHashMap<K, CacheEntry<K, V>>(initialCapacity, loadFactor, concurrencyLevel);
+    }
+
+    public V get(K key) {
+        V value = null;
+
+        cleanStaleEntries();
+        CacheEntry<K, V> entry = _map.get(key);
+        if (entry != null) {
+            value = entry.get();
+        }
+        if (value == null) {
+            key = normalizeKey(key);
+            V newVal = createObject(key);
+            if (key == null || newVal == null) {
+                // subclass must return non-null key/value object
+                return null;
+            }
+
+            CacheEntry<K, V> newEntry = new CacheEntry<K, V>(key, newVal, _queue);
+
+            while (value == null) {
+                cleanStaleEntries();
+                entry = _map.putIfAbsent(key, newEntry);
+                if (entry == null) {
+                    value = newVal;
+                    break;
+                } else {
+                    value = entry.get();
+                }
+            }
+        }
+        return value;
+    }
+
+    @SuppressWarnings("unchecked")
+    private void cleanStaleEntries() {
+        CacheEntry<K, V> entry;
+        while ((entry = (CacheEntry<K, V>)_queue.poll()) != null) {
+            _map.remove(entry.getKey());
+        }
+    }
+
+    protected abstract V createObject(K key);
+
+    protected K normalizeKey(K key) {
+        return key;
+    }
+
+    private static class CacheEntry<K, V> extends SoftReference<V> {
+        private K _key;
+
+        CacheEntry(K key, V value, ReferenceQueue<V> queue) {
+            super(value, queue);
+            _key = key;
+        }
+
+        K getKey() {
+            return _key;
+        }
+    }
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/locale/LocaleSyntaxException.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/locale/LocaleSyntaxException.java
new file mode 100644
index 0000000..bceba10
--- /dev/null
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/locale/LocaleSyntaxException.java
@@ -0,0 +1,27 @@
+/*
+ *******************************************************************************
+ * Copyright (C) 2009-2011, International Business Machines Corporation and    *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+package com.ibm.icu.impl.locale;
+
+public class LocaleSyntaxException extends Exception {
+
+    private static final long serialVersionUID = 1L;
+
+    private int _index = -1;
+
+    public LocaleSyntaxException(String msg) {
+        this(msg, 0);
+    }
+
+    public LocaleSyntaxException(String msg, int errorIndex) {
+        super(msg);
+        _index = errorIndex;
+    }
+
+    public int getErrorIndex() {
+        return _index;
+    }
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/locale/ParseStatus.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/locale/ParseStatus.java
new file mode 100644
index 0000000..6eb5d82
--- /dev/null
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/locale/ParseStatus.java
@@ -0,0 +1,35 @@
+/*
+ *******************************************************************************
+ * Copyright (C) 2010-2011, International Business Machines Corporation and    *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+package com.ibm.icu.impl.locale;
+
+public class ParseStatus {
+    int _parseLength = 0;
+    int _errorIndex = -1;
+    String _errorMsg = null;
+
+    public void reset() {
+        _parseLength = 0;
+        _errorIndex = -1;
+        _errorMsg = null;
+    }
+
+    public boolean isError() {
+        return (_errorIndex >= 0);
+    }
+
+    public int getErrorIndex() {
+        return _errorIndex;
+    }
+
+    public int getParseLength() {
+        return _parseLength;
+    }
+
+    public String getErrorMessage() {
+        return _errorMsg;
+    }
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/locale/StringTokenIterator.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/locale/StringTokenIterator.java
new file mode 100644
index 0000000..b25146d
--- /dev/null
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/locale/StringTokenIterator.java
@@ -0,0 +1,93 @@
+/*
+ *******************************************************************************
+ * Copyright (C) 2009-2011, International Business Machines Corporation and    *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+package com.ibm.icu.impl.locale;
+
+public class StringTokenIterator {
+    private String _text;
+    private String _dlms;
+
+    private String _token;
+    private int _start;
+    private int _end;
+    private boolean _done;
+
+    public StringTokenIterator(String text, String dlms) {
+        _text = text;
+        _dlms = dlms;
+        setStart(0);
+    }
+
+    public String first() {
+        setStart(0);
+        return _token;
+    }
+
+    public String current() {
+        return _token;
+    }
+
+    public int currentStart() {
+        return _start;
+    }
+
+    public int currentEnd() {
+        return _end;
+    }
+
+    public boolean isDone() {
+        return _done;
+    }
+
+    public String next() {
+        if (hasNext()) {
+            _start = _end + 1;
+            _end = nextDelimiter(_start);
+            _token = _text.substring(_start, _end);
+        } else {
+            _start = _end;
+            _token = null;
+            _done = true;
+        }
+        return _token;
+    }
+
+    public boolean hasNext() {
+        return (_end < _text.length());
+    }
+
+    public StringTokenIterator setStart(int offset) {
+        if (offset > _text.length()) {
+            throw new IndexOutOfBoundsException();
+        }
+        _start = offset;
+        _end = nextDelimiter(_start);
+        _token = _text.substring(_start, _end);
+        _done = false;
+        return this;
+    }
+
+    public StringTokenIterator setText(String text) {
+        _text = text;
+        setStart(0);
+        return this;
+    }
+
+    private int nextDelimiter(int start) {
+        int idx = start;
+        outer: while (idx < _text.length()) {
+            char c = _text.charAt(idx);
+            for (int i = 0; i < _dlms.length(); i++) {
+                if (c == _dlms.charAt(i)) {
+                    break outer;
+                }
+            }
+            idx++;
+        }
+        return idx;
+    }
+}
+
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/locale/UnicodeLocaleExtension.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/locale/UnicodeLocaleExtension.java
new file mode 100644
index 0000000..8f9dd9d
--- /dev/null
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/locale/UnicodeLocaleExtension.java
@@ -0,0 +1,102 @@
+/*
+ *******************************************************************************
+ * Copyright (C) 2009-2011, International Business Machines Corporation and    *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+package com.ibm.icu.impl.locale;
+
+import java.util.Collections;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.SortedSet;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+public class UnicodeLocaleExtension extends Extension {
+    public static final char SINGLETON = 'u';
+
+    private static final SortedSet<String> EMPTY_SORTED_SET = new TreeSet<String>();
+    private static final SortedMap<String, String> EMPTY_SORTED_MAP = new TreeMap<String, String>();
+
+    private SortedSet<String> _attributes = EMPTY_SORTED_SET;
+    private SortedMap<String, String> _keywords = EMPTY_SORTED_MAP;
+
+    public static final UnicodeLocaleExtension CA_JAPANESE;
+    public static final UnicodeLocaleExtension NU_THAI;
+
+    static {
+        CA_JAPANESE = new UnicodeLocaleExtension();
+        CA_JAPANESE._keywords = new TreeMap<String, String>();
+        CA_JAPANESE._keywords.put("ca", "japanese");
+        CA_JAPANESE._value = "ca-japanese";
+
+        NU_THAI = new UnicodeLocaleExtension();
+        NU_THAI._keywords = new TreeMap<String, String>();
+        NU_THAI._keywords.put("nu", "thai");
+        NU_THAI._value = "nu-thai";
+    }
+
+    private UnicodeLocaleExtension() {
+        super(SINGLETON);
+    }
+
+    UnicodeLocaleExtension(SortedSet<String> attributes, SortedMap<String, String> keywords) {
+        this();
+        if (attributes != null && attributes.size() > 0) {
+            _attributes = attributes;
+        }
+        if (keywords != null && keywords.size() > 0) {
+            _keywords = keywords;
+        }
+
+        if (_attributes.size() > 0 || _keywords.size() > 0) {
+            StringBuilder sb = new StringBuilder();
+            for (String attribute : _attributes) {
+                sb.append(LanguageTag.SEP).append(attribute);
+            }
+            for (Entry<String, String> keyword : _keywords.entrySet()) {
+                String key = keyword.getKey();
+                String value = keyword.getValue();
+
+                sb.append(LanguageTag.SEP).append(key);
+                if (value.length() > 0) {
+                    sb.append(LanguageTag.SEP).append(value);
+                }
+            }
+            _value = sb.substring(1);   // skip leading '-'
+        }
+    }
+
+    public Set<String> getUnicodeLocaleAttributes() {
+        return Collections.unmodifiableSet(_attributes);
+    }
+
+    public Set<String> getUnicodeLocaleKeys() {
+        return Collections.unmodifiableSet(_keywords.keySet());
+    }
+
+    public String getUnicodeLocaleType(String unicodeLocaleKey) {
+        return _keywords.get(unicodeLocaleKey);
+    }
+
+    public static boolean isSingletonChar(char c) {
+        return (SINGLETON == AsciiUtil.toLower(c));
+    }
+
+    public static boolean isAttribute(String s) {
+        // 3*8alphanum
+        return (s.length() >= 3) && (s.length() <= 8) && AsciiUtil.isAlphaNumericString(s);
+    }
+
+    public static boolean isKey(String s) {
+        // 2alphanum
+        return (s.length() == 2) && AsciiUtil.isAlphaNumericString(s);
+    }
+
+    public static boolean isTypeSubtag(String s) {
+        // 3*8alphanum
+        return (s.length() >= 3) && (s.length() <= 8) && AsciiUtil.isAlphaNumericString(s);
+    }
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/math/BigDecimal.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/math/BigDecimal.java
index 3dfa95b..a901503 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/math/BigDecimal.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/math/BigDecimal.java
@@ -1,3880 +1,3880 @@
-/* Generated from 'BigDecimal.nrx' 8 Sep 2000 11:10:50 [v2.00] */
-/* Options: Binary Comments Crossref Format Java Logo Strictargs Strictcase Trace2 Verbose3 */
-package com.ibm.icu.math;
-
-import java.math.BigInteger;
-
-/* ------------------------------------------------------------------ */
-/* BigDecimal -- Decimal arithmetic for Java                          */
-/* ------------------------------------------------------------------ */
-/* Copyright IBM Corporation, 1996-2011.  All Rights Reserved.       */
-/*                                                                    */
-/* The BigDecimal class provides immutable arbitrary-precision        */
-/* floating point (including integer) decimal numbers.                */
-/*                                                                    */
-/* As the numbers are decimal, there is an exact correspondence       */
-/* between an instance of a BigDecimal object and its String          */
-/* representation; the BigDecimal class provides direct conversions   */
-/* to and from String and character array objects, and well as        */
-/* conversions to and from the Java primitive types (which may not    */
-/* be exact).                                                         */
-/* ------------------------------------------------------------------ */
-/* Notes:                                                             */
-/*                                                                    */
-/* 1. A BigDecimal object is never changed in value once constructed; */
-/*    this avoids the need for locking.  Note in particular that the  */
-/*    mantissa array may be shared between many BigDecimal objects,   */
-/*    so that once exposed it must not be altered.                    */
-/*                                                                    */
-/* 2. This class looks at MathContext class fields directly (for      */
-/*    performance).  It must not and does not change them.            */
-/*                                                                    */
-/* 3. Exponent checking is delayed until finish(), as we know         */
-/*    intermediate calculations cannot cause 31-bit overflow.         */
-/*    [This assertion depends on MAX_DIGITS in MathContext.]          */
-/*                                                                    */
-/* 4. Comments for the public API now follow the javadoc conventions. */
-/*    The NetRexx -comments option is used to pass these comments     */
-/*    through to the generated Java code (with -format, if desired).  */
-/*                                                                    */
-/* 5. System.arraycopy is faster than explicit loop as follows        */
-/*      Mean length 4:  equal                                         */
-/*      Mean length 8:  x2                                            */
-/*      Mean length 16: x3                                            */
-/*      Mean length 24: x4                                            */
-/*    From prior experience, we expect mean length a little below 8,  */
-/*    but arraycopy is still the one to use, in general, until later  */
-/*    measurements suggest otherwise.                                 */
-/*                                                                    */
-/* 6. 'DMSRCN' referred to below is the original (1981) IBM S/370     */
-/*    assembler code implementation of the algorithms below; it is    */
-/*    now called IXXRCN and is available with the OS/390 and VM/ESA   */
-/*    operating systems.                                              */
-/* ------------------------------------------------------------------ */
-/* Change History:                                                    */
-/* 1997.09.02 Initial version (derived from netrexx.lang classes)     */
-/* 1997.09.12 Add lostDigits checking                                 */
-/* 1997.10.06 Change mantissa to a byte array                         */
-/* 1997.11.22 Rework power [did not prepare arguments, etc.]          */
-/* 1997.12.13 multiply did not prepare arguments                      */
-/* 1997.12.14 add did not prepare and align arguments correctly       */
-/* 1998.05.02 0.07 packaging changes suggested by Sun and Oracle      */
-/* 1998.05.21 adjust remainder operator finalization                  */
-/* 1998.06.04 rework to pass MathContext to finish() and round()      */
-/* 1998.06.06 change format to use round(); support rounding modes    */
-/* 1998.06.25 rename to BigDecimal and begin merge                    */
-/*            zero can now have trailing zeros (i.e., exp\=0)         */
-/* 1998.06.28 new methods: movePointXxxx, scale, toBigInteger         */
-/*                         unscaledValue, valueof                     */
-/* 1998.07.01 improve byteaddsub to allow array reuse, etc.           */
-/* 1998.07.01 make null testing explicit to avoid JIT bug [Win32]     */
-/* 1998.07.07 scaled division  [divide(BigDecimal, int, int)]         */
-/* 1998.07.08 setScale, faster equals                                 */
-/* 1998.07.11 allow 1E6 (no sign) <sigh>; new double/float conversion */
-/* 1998.10.12 change package to com.ibm.icu.math                          */
-/* 1998.12.14 power operator no longer rounds RHS [to match ANSI]     */
-/*            add toBigDecimal() and BigDecimal(java.math.BigDecimal) */
-/* 1998.12.29 improve byteaddsub by using table lookup                */
-/* 1999.02.04 lostdigits=0 behaviour rounds instead of digits+1 guard */
-/* 1999.02.05 cleaner code for BigDecimal(char[])                     */
-/* 1999.02.06 add javadoc comments                                    */
-/* 1999.02.11 format() changed from 7 to 2 method form                */
-/* 1999.03.05 null pointer checking is no longer explicit             */
-/* 1999.03.05 simplify; changes from discussion with J. Bloch:        */
-/*            null no longer permitted for MathContext; drop boolean, */
-/*            byte, char, float, short constructor, deprecate double  */
-/*            constructor, no blanks in string constructor, add       */
-/*            offset and length version of char[] constructor;        */
-/*            add valueOf(double); drop booleanValue, charValue;      */
-/*            add ...Exact versions of remaining convertors           */
-/* 1999.03.13 add toBigIntegerExact                                   */
-/* 1999.03.13 1.00 release to IBM Centre for Java Technology          */
-/* 1999.05.27 1.01 correct 0-0.2 bug under scaled arithmetic          */
-/* 1999.06.29 1.02 constructors should not allow exponent > 9 digits  */
-/* 1999.07.03 1.03 lost digits should not be checked if digits=0      */
-/* 1999.07.06      lost digits Exception message changed              */
-/* 1999.07.10 1.04 more work on 0-0.2 (scaled arithmetic)             */
-/* 1999.07.17      improve messages from pow method                   */
-/* 1999.08.08      performance tweaks                                 */
-/* 1999.08.15      fastpath in multiply                               */
-/* 1999.11.05 1.05 fix problem in intValueExact [e.g., 5555555555]    */
-/* 1999.12.22 1.06 remove multiply fastpath, and improve performance  */
-/* 2000.01.01      copyright update [Y2K has arrived]                 */
-/* 2000.06.18 1.08 no longer deprecate BigDecimal(double)             */
-/* ------------------------------------------------------------------ */
-
-/**
- * The <code>BigDecimal</code> class implements immutable arbitrary-precision decimal numbers. The methods of the
- * <code>BigDecimal</code> class provide operations for fixed and floating point arithmetic, comparison, format
- * conversions, and hashing.
- * <p>
- * As the numbers are decimal, there is an exact correspondence between an instance of a <code>BigDecimal</code> object
- * and its <code>String</code> representation; the <code>BigDecimal</code> class provides direct conversions to and from
- * <code>String</code> and character array (<code>char[]</code>) objects, as well as conversions to and from the Java
- * primitive types (which may not be exact) and <code>BigInteger</code>.
- * <p>
- * In the descriptions of constructors and methods in this documentation, the value of a <code>BigDecimal</code> number
- * object is shown as the result of invoking the <code>toString()</code> method on the object. The internal
- * representation of a decimal number is neither defined nor exposed, and is not permitted to affect the result of any
- * operation.
- * <p>
- * The floating point arithmetic provided by this class is defined by the ANSI X3.274-1996 standard, and is also
- * documented at <code>http://www2.hursley.ibm.com/decimal</code> <br>
- * <i>[This URL will change.]</i>
- * 
- * <h3>Operator methods</h3>
- * <p>
- * Operations on <code>BigDecimal</code> numbers are controlled by a {@link MathContext} object, which provides the
- * context (precision and other information) for the operation. Methods that can take a <code>MathContext</code>
- * parameter implement the standard arithmetic operators for <code>BigDecimal</code> objects and are known as
- * <i>operator methods</i>. The default settings provided by the constant {@link MathContext#DEFAULT} (<code>digits=9,
- * form=SCIENTIFIC, lostDigits=false, roundingMode=ROUND_HALF_UP</code>) perform general-purpose floating point
- * arithmetic to nine digits of precision. The <code>MathContext</code> parameter must not be <code>null</code>.
- * <p>
- * Each operator method also has a version provided which does not take a <code>MathContext</code> parameter. For this
- * version of each method, the context settings used are <code>digits=0,
- * form=PLAIN, lostDigits=false, roundingMode=ROUND_HALF_UP</code>; these settings perform fixed point arithmetic with
- * unlimited precision, as defined for the original BigDecimal class in Java 1.1 and Java 1.2.
- * <p>
- * For monadic operators, only the optional <code>MathContext</code> parameter is present; the operation acts upon the
- * current object.
- * <p>
- * For dyadic operators, a <code>BigDecimal</code> parameter is always present; it must not be <code>null</code>. The
- * operation acts with the current object being the left-hand operand and the <code>BigDecimal</code> parameter being
- * the right-hand operand.
- * <p>
- * For example, adding two <code>BigDecimal</code> objects referred to by the names <code>award</code> and
- * <code>extra</code> could be written as any of:
- * <p>
- * <code>
- *     award.add(extra)
- * <br>award.add(extra, MathContext.DEFAULT)
- * <br>award.add(extra, acontext)
- * </code>
- * <p>
- * (where <code>acontext</code> is a <code>MathContext</code> object), which would return a <code>BigDecimal</code>
- * object whose value is the result of adding <code>award</code> and <code>extra</code> under the appropriate context
- * settings.
- * <p>
- * When a <code>BigDecimal</code> operator method is used, a set of rules define what the result will be (and, by
- * implication, how the result would be represented as a character string). These rules are defined in the BigDecimal
- * arithmetic documentation (see the URL above), but in summary:
- * <ul>
- * <li>Results are normally calculated with up to some maximum number of significant digits. For example, if the
- * <code>MathContext</code> parameter for an operation were <code>MathContext.DEFAULT</code> then the result would be
- * rounded to 9 digits; the division of 2 by 3 would then result in 0.666666667. <br>
- * You can change the default of 9 significant digits by providing the method with a suitable <code>MathContext</code>
- * object. This lets you calculate using as many digits as you need -- thousands, if necessary. Fixed point (scaled)
- * arithmetic is indicated by using a <code>digits</code> setting of 0 (or omitting the <code>MathContext</code>
- * parameter). <br>
- * Similarly, you can change the algorithm used for rounding from the default "classic" algorithm.
- * <li>
- * In standard arithmetic (that is, when the <code>form</code> setting is not <code>PLAIN</code>), a zero result is
- * always expressed as the single digit <code>'0'</code> (that is, with no sign, decimal point, or exponent part).
- * <li>
- * Except for the division and power operators in standard arithmetic, trailing zeros are preserved (this is in contrast
- * to binary floating point operations and most electronic calculators, which lose the information about trailing zeros
- * in the fractional part of results). <br>
- * So, for example:
- * <p>
- * <code>
- *     new BigDecimal("2.40").add(     new BigDecimal("2"))      =&gt; "4.40"
- * <br>new BigDecimal("2.40").subtract(new BigDecimal("2"))      =&gt; "0.40"
- * <br>new BigDecimal("2.40").multiply(new BigDecimal("2"))      =&gt; "4.80"
- * <br>new BigDecimal("2.40").divide(  new BigDecimal("2"), def) =&gt; "1.2"
- * </code>
- * <p>
- * where the value on the right of the <code>=&gt;</code> would be the result of the operation, expressed as a
- * <code>String</code>, and <code>def</code> (in this and following examples) refers to <code>MathContext.DEFAULT</code>
- * ). This preservation of trailing zeros is desirable for most calculations (including financial calculations). If
- * necessary, trailing zeros may be easily removed using division by 1.
- * <li>
- * In standard arithmetic, exponential form is used for a result depending on its value and the current setting of
- * <code>digits</code> (the default is 9 digits). If the number of places needed before the decimal point exceeds the
- * <code>digits</code> setting, or the absolute value of the number is less than <code>0.000001</code>, then the number
- * will be expressed in exponential notation; thus
- * <p>
- * <code>
- *   new BigDecimal("1e+6").multiply(new BigDecimal("1e+6"), def)
- * </code>
- * <p>
- * results in <code>1E+12</code> instead of <code>1000000000000</code>, and
- * <p>
- * <code>
- *   new BigDecimal("1").divide(new BigDecimal("3E+10"), def)
- * </code>
- * <p>
- * results in <code>3.33333333E-11</code> instead of <code>0.0000000000333333333</code>.
- * <p>
- * The form of the exponential notation (scientific or engineering) is determined by the <code>form</code> setting.
- * <eul>
- * <p>
- * The names of methods in this class follow the conventions established by <code>java.lang.Number</code>,
- * <code>java.math.BigInteger</code>, and <code>java.math.BigDecimal</code> in Java 1.1 and Java 1.2.
- * 
- * @see MathContext
- * @author Mike Cowlishaw
- * @stable ICU 2.0
- */
-
-public class BigDecimal extends java.lang.Number implements java.io.Serializable, java.lang.Comparable<BigDecimal> {
-    // private static final java.lang.String $0="BigDecimal.nrx";
-
-    /* ----- Constants ----- */
-    /* properties constant public */// useful to others
-    /**
-     * The <code>BigDecimal</code> constant "0".
-     * 
-     * @see #ONE
-     * @see #TEN
-     * @stable ICU 2.0
-     */
-    public static final com.ibm.icu.math.BigDecimal ZERO = new com.ibm.icu.math.BigDecimal((long) 0); // use long as we
-                                                                                                      // want the int
-                                                                                                      // constructor
-    // .. to be able to use this, for speed
-
-    /**
-     * The <code>BigDecimal</code> constant "1".
-     * 
-     * @see #TEN
-     * @see #ZERO
-     * @stable ICU 2.0
-     */
-    public static final com.ibm.icu.math.BigDecimal ONE = new com.ibm.icu.math.BigDecimal((long) 1); // use long as we
-                                                                                                     // want the int
-                                                                                                     // constructor
-    // .. to be able to use this, for speed
-
-    /**
-     * The <code>BigDecimal</code> constant "10".
-     * 
-     * @see #ONE
-     * @see #ZERO
-     * @stable ICU 2.0
-     */
-    public static final com.ibm.icu.math.BigDecimal TEN = new com.ibm.icu.math.BigDecimal(10);
-
-    // the rounding modes (copied here for upwards compatibility)
-    /**
-     * Rounding mode to round to a more positive number.
-     * 
-     * @see MathContext#ROUND_CEILING
-     * @stable ICU 2.0
-     */
-    public static final int ROUND_CEILING = com.ibm.icu.math.MathContext.ROUND_CEILING;
-
-    /**
-     * Rounding mode to round towards zero.
-     * 
-     * @see MathContext#ROUND_DOWN
-     * @stable ICU 2.0
-     */
-    public static final int ROUND_DOWN = com.ibm.icu.math.MathContext.ROUND_DOWN;
-
-    /**
-     * Rounding mode to round to a more negative number.
-     * 
-     * @see MathContext#ROUND_FLOOR
-     * @stable ICU 2.0
-     */
-    public static final int ROUND_FLOOR = com.ibm.icu.math.MathContext.ROUND_FLOOR;
-
-    /**
-     * Rounding mode to round to nearest neighbor, where an equidistant value is rounded down.
-     * 
-     * @see MathContext#ROUND_HALF_DOWN
-     * @stable ICU 2.0
-     */
-    public static final int ROUND_HALF_DOWN = com.ibm.icu.math.MathContext.ROUND_HALF_DOWN;
-
-    /**
-     * Rounding mode to round to nearest neighbor, where an equidistant value is rounded to the nearest even neighbor.
-     * 
-     * @see MathContext#ROUND_HALF_EVEN
-     * @stable ICU 2.0
-     */
-    public static final int ROUND_HALF_EVEN = com.ibm.icu.math.MathContext.ROUND_HALF_EVEN;
-
-    /**
-     * Rounding mode to round to nearest neighbor, where an equidistant value is rounded up.
-     * 
-     * @see MathContext#ROUND_HALF_UP
-     * @stable ICU 2.0
-     */
-    public static final int ROUND_HALF_UP = com.ibm.icu.math.MathContext.ROUND_HALF_UP;
-
-    /**
-     * Rounding mode to assert that no rounding is necessary.
-     * 
-     * @see MathContext#ROUND_UNNECESSARY
-     * @stable ICU 2.0
-     */
-    public static final int ROUND_UNNECESSARY = com.ibm.icu.math.MathContext.ROUND_UNNECESSARY;
-
-    /**
-     * Rounding mode to round away from zero.
-     * 
-     * @see MathContext#ROUND_UP
-     * @stable ICU 2.0
-     */
-    public static final int ROUND_UP = com.ibm.icu.math.MathContext.ROUND_UP;
-
-    /* properties constant private */// locals
-    private static final byte ispos = 1; // ind: indicates positive (must be 1)
-    private static final byte iszero = 0; // ind: indicates zero (must be 0)
-    private static final byte isneg = -1; // ind: indicates negative (must be -1)
-    // [later could add NaN, +/- infinity, here]
-
-    private static final int MinExp = -999999999; // minimum exponent allowed
-    private static final int MaxExp = 999999999; // maximum exponent allowed
-    private static final int MinArg = -999999999; // minimum argument integer
-    private static final int MaxArg = 999999999; // maximum argument integer
-
-    private static final com.ibm.icu.math.MathContext plainMC = new com.ibm.icu.math.MathContext(0,
-            com.ibm.icu.math.MathContext.PLAIN); // context for plain unlimited math
-
-    /* properties constant private unused */// present but not referenced
-    // Serialization version
-    private static final long serialVersionUID = 8245355804974198832L;
-
-    // private static final java.lang.String
-    // copyright=" Copyright (c) IBM Corporation 1996, 2000.  All rights reserved. ";
-
-    /* properties static private */
-    // Precalculated constant arrays (used by byteaddsub)
-    private static byte bytecar[] = new byte[(90 + 99) + 1]; // carry/borrow array
-    private static byte bytedig[] = diginit(); // next digit array
-
-    /* ----- Instance properties [all private and immutable] ----- */
-    /* properties private */
-
-    /**
-     * The indicator. This may take the values:
-     * <ul>
-     * <li>ispos -- the number is positive <li>iszero -- the number is zero <li>isneg -- the number is negative
-     * </ul>
-     * 
-     * @serial
-     */
-    private byte ind; // assumed undefined
-    // Note: some code below assumes IND = Sign [-1, 0, 1], at present.
-    // We only need two bits for this, but use a byte [also permits
-    // smooth future extension].
-
-    /**
-     * The formatting style. This may take the values:
-     * <ul>
-     * <li>MathContext.PLAIN -- no exponent needed <li>MathContext.SCIENTIFIC -- scientific notation required <li>
-     * MathContext.ENGINEERING -- engineering notation required
-     * </ul>
-     * <p>
-     * This property is an optimization; it allows us to defer number layout until it is actually needed as a string,
-     * hence avoiding unnecessary formatting.
-     * 
-     * @serial
-     */
-    private byte form = (byte) com.ibm.icu.math.MathContext.PLAIN; // assumed PLAIN
-    // We only need two bits for this, at present, but use a byte
-    // [again, to allow for smooth future extension]
-
-    /**
-     * The value of the mantissa.
-     * <p>
-     * Once constructed, this may become shared between several BigDecimal objects, so must not be altered.
-     * <p>
-     * For efficiency (speed), this is a byte array, with each byte taking a value of 0 -> 9.
-     * <p>
-     * If the first byte is 0 then the value of the number is zero (and mant.length=1, except when constructed from a
-     * plain number, for example, 0.000).
-     * 
-     * @serial
-     */
-    private byte mant[]; // assumed null
-
-    /**
-     * The exponent.
-     * <p>
-     * For fixed point arithmetic, scale is <code>-exp</code>, and can apply to zero.
-     * 
-     * Note that this property can have a value less than MinExp when the mantissa has more than one digit.
-     * 
-     * @serial
-     */
-    private int exp;
-
-    // assumed 0
-
-    /* ---------------------------------------------------------------- */
-    /* Constructors */
-    /* ---------------------------------------------------------------- */
-
-    /**
-     * Constructs a <code>BigDecimal</code> object from a <code>java.math.BigDecimal</code>.
-     * <p>
-     * Constructs a <code>BigDecimal</code> as though the parameter had been represented as a <code>String</code> (using
-     * its <code>toString</code> method) and the {@link #BigDecimal(java.lang.String)} constructor had then been used.
-     * The parameter must not be <code>null</code>.
-     * <p>
-     * <i>(Note: this constructor is provided only in the <code>com.ibm.icu.math</code> version of the BigDecimal class.
-     * It would not be present in a <code>java.math</code> version.)</i>
-     * 
-     * @param bd The <code>BigDecimal</code> to be translated.
-     * @stable ICU 2.0
-     */
-
-    public BigDecimal(java.math.BigDecimal bd) {
-        this(bd.toString());
-        return;
-    }
-
-    /**
-     * Constructs a <code>BigDecimal</code> object from a <code>BigInteger</code>, with scale 0.
-     * <p>
-     * Constructs a <code>BigDecimal</code> which is the exact decimal representation of the <code>BigInteger</code>,
-     * with a scale of zero. The value of the <code>BigDecimal</code> is identical to the value of the <code>BigInteger
-     * </code>. The parameter must not be <code>null</code>.
-     * <p>
-     * The <code>BigDecimal</code> will contain only decimal digits, prefixed with a leading minus sign (hyphen) if the
-     * <code>BigInteger</code> is negative. A leading zero will be present only if the <code>BigInteger</code> is zero.
-     * 
-     * @param bi The <code>BigInteger</code> to be converted.
-     * @stable ICU 2.0
-     */
-
-    public BigDecimal(java.math.BigInteger bi) {
-        this(bi.toString(10));
-        return;
-    }
-
-    // exp remains 0
-
-    /**
-     * Constructs a <code>BigDecimal</code> object from a <code>BigInteger</code> and a scale.
-     * <p>
-     * Constructs a <code>BigDecimal</code> which is the exact decimal representation of the <code>BigInteger</code>,
-     * scaled by the second parameter, which may not be negative. The value of the <code>BigDecimal</code> is the <code>
-     * BigInteger</code> divided by ten to the power of the scale. The <code>BigInteger</code> parameter must not be
-     * <code>null</code>.
-     * <p>
-     * The <code>BigDecimal</code> will contain only decimal digits, (with an embedded decimal point followed by <code>
-     * scale</code> decimal digits if the scale is positive), prefixed with a leading minus sign (hyphen) if the <code>
-     * BigInteger</code> is negative. A leading zero will be present only if the <code>BigInteger</code> is zero.
-     * 
-     * @param bi The <code>BigInteger</code> to be converted.
-     * @param scale The <code>int</code> specifying the scale.
-     * @throws NumberFormatException If the scale is negative.
-     * @stable ICU 2.0
-     */
-
-    public BigDecimal(java.math.BigInteger bi, int scale) {
-        this(bi.toString(10));
-        if (scale < 0)
-            throw new java.lang.NumberFormatException("Negative scale:" + " " + scale);
-        exp = -scale; // exponent is -scale
-        return;
-    }
-
-    /**
-     * Constructs a <code>BigDecimal</code> object from an array of characters.
-     * <p>
-     * Constructs a <code>BigDecimal</code> as though a <code>String</code> had been constructed from the character
-     * array and the {@link #BigDecimal(java.lang.String)} constructor had then been used. The parameter must not be
-     * <code>null</code>.
-     * <p>
-     * Using this constructor is faster than using the <code>BigDecimal(String)</code> constructor if the string is
-     * already available in character array form.
-     * 
-     * @param inchars The <code>char[]</code> array containing the number to be converted.
-     * @throws NumberFormatException If the parameter is not a valid number.
-     * @stable ICU 2.0
-     */
-
-    public BigDecimal(char inchars[]) {
-        this(inchars, 0, inchars.length);
-        return;
-    }
-
-    /**
-     * Constructs a <code>BigDecimal</code> object from an array of characters.
-     * <p>
-     * Constructs a <code>BigDecimal</code> as though a <code>String</code> had been constructed from the character
-     * array (or a subarray of that array) and the {@link #BigDecimal(java.lang.String)} constructor had then been used.
-     * The first parameter must not be <code>null</code>, and the subarray must be wholly contained within it.
-     * <p>
-     * Using this constructor is faster than using the <code>BigDecimal(String)</code> constructor if the string is
-     * already available within a character array.
-     * 
-     * @param inchars The <code>char[]</code> array containing the number to be converted.
-     * @param offset The <code>int</code> offset into the array of the start of the number to be converted.
-     * @param length The <code>int</code> length of the number.
-     * @throws NumberFormatException If the parameter is not a valid number for any reason.
-     * @stable ICU 2.0
-     */
-
-    public BigDecimal(char inchars[], int offset, int length) {
-        super();
-        boolean exotic;
-        boolean hadexp;
-        int d;
-        int dotoff;
-        int last;
-        int i = 0;
-        char si = 0;
-        boolean eneg = false;
-        int k = 0;
-        int elen = 0;
-        int j = 0;
-        char sj = 0;
-        int dvalue = 0;
-        int mag = 0;
-        // This is the primary constructor; all incoming strings end up
-        // here; it uses explicit (inline) parsing for speed and to avoid
-        // generating intermediate (temporary) objects of any kind.
-        // 1998.06.25: exponent form built only if E/e in string
-        // 1998.06.25: trailing zeros not removed for zero
-        // 1999.03.06: no embedded blanks; allow offset and length
-        if (length <= 0)
-            bad(inchars); // bad conversion (empty string)
-        // [bad offset will raise array bounds exception]
-
-        /* Handle and step past sign */
-        ind = ispos; // assume positive
-        if (inchars[offset] == ('-')) {
-            length--;
-            if (length == 0)
-                bad(inchars); // nothing after sign
-            ind = isneg;
-            offset++;
-        } else if (inchars[offset] == ('+')) {
-            length--;
-            if (length == 0)
-                bad(inchars); // nothing after sign
-            offset++;
-        }
-
-        /* We're at the start of the number */
-        exotic = false; // have extra digits
-        hadexp = false; // had explicit exponent
-        d = 0; // count of digits found
-        dotoff = -1; // offset where dot was found
-        last = -1; // last character of mantissa
-        {
-            int $1 = length;
-            i = offset;
-            i: for (; $1 > 0; $1--, i++) {
-                si = inchars[i];
-                if (si >= '0') // test for Arabic digit
-                    if (si <= '9') {
-                        last = i;
-                        d++; // still in mantissa
-                        continue i;
-                    }
-                if (si == '.') { // record and ignore
-                    if (dotoff >= 0)
-                        bad(inchars); // two dots
-                    dotoff = i - offset; // offset into mantissa
-                    continue i;
-                }
-                if (si != 'e')
-                    if (si != 'E') { // expect an extra digit
-                        if ((!(Character.isDigit(si))))
-                            bad(inchars); // not a number
-                        // defer the base 10 check until later to avoid extra method call
-                        exotic = true; // will need conversion later
-                        last = i;
-                        d++; // still in mantissa
-                        continue i;
-                    }
-                /* Found 'e' or 'E' -- now process explicit exponent */
-                // 1998.07.11: sign no longer required
-                if ((i - offset) > (length - 2))
-                    bad(inchars); // no room for even one digit
-                eneg = false;
-                if ((inchars[i + 1]) == ('-')) {
-                    eneg = true;
-                    k = i + 2;
-                } else if ((inchars[i + 1]) == ('+'))
-                    k = i + 2;
-                else
-                    k = i + 1;
-                // k is offset of first expected digit
-                elen = length - ((k - offset)); // possible number of digits
-                if ((elen == 0) | (elen > 9))
-                    bad(inchars); // 0 or more than 9 digits
-                {
-                    int $2 = elen;
-                    j = k;
-                    for (; $2 > 0; $2--, j++) {
-                        sj = inchars[j];
-                        if (sj < '0')
-                            bad(inchars); // always bad
-                        if (sj > '9') { // maybe an exotic digit
-                            if ((!(Character.isDigit(sj))))
-                                bad(inchars); // not a number
-                            dvalue = Character.digit(sj, 10); // check base
-                            if (dvalue < 0)
-                                bad(inchars); // not base 10
-                        } else
-                            dvalue = ((int) (sj)) - ((int) ('0'));
-                        exp = (exp * 10) + dvalue;
-                    }
-                }/* j */
-                if (eneg)
-                    exp = -exp; // was negative
-                hadexp = true; // remember we had one
-                break i; // we are done
-            }
-        }/* i */
-
-        /* Here when all inspected */
-        if (d == 0)
-            bad(inchars); // no mantissa digits
-        if (dotoff >= 0)
-            exp = (exp + dotoff) - d; // adjust exponent if had dot
-
-        /* strip leading zeros/dot (leave final if all 0's) */
-        {
-            int $3 = last - 1;
-            i = offset;
-            i: for (; i <= $3; i++) {
-                si = inchars[i];
-                if (si == '0') {
-                    offset++;
-                    dotoff--;
-                    d--;
-                } else if (si == '.') {
-                    offset++; // step past dot
-                    dotoff--;
-                } else if (si <= '9')
-                    break i;/* non-0 */
-                else {/* exotic */
-                    if ((Character.digit(si, 10)) != 0)
-                        break i; // non-0 or bad
-                    // is 0 .. strip like '0'
-                    offset++;
-                    dotoff--;
-                    d--;
-                }
-            }
-        }/* i */
-
-        /* Create the mantissa array */
-        mant = new byte[d]; // we know the length
-        j = offset; // input offset
-        if (exotic) {
-            do { // slow: check for exotica
-                {
-                    int $4 = d;
-                    i = 0;
-                    for (; $4 > 0; $4--, i++) {
-                        if (i == dotoff)
-                            j++; // at dot
-                        sj = inchars[j];
-                        if (sj <= '9')
-                            mant[i] = (byte) (((int) (sj)) - ((int) ('0')));/* easy */
-                        else {
-                            dvalue = Character.digit(sj, 10);
-                            if (dvalue < 0)
-                                bad(inchars); // not a number after all
-                            mant[i] = (byte) dvalue;
-                        }
-                        j++;
-                    }
-                }/* i */
-            } while (false);
-        }/* exotica */
-        else {
-            do {
-                {
-                    int $5 = d;
-                    i = 0;
-                    for (; $5 > 0; $5--, i++) {
-                        if (i == dotoff)
-                            j++;
-                        mant[i] = (byte) (((int) (inchars[j])) - ((int) ('0')));
-                        j++;
-                    }
-                }/* i */
-            } while (false);
-        }/* simple */
-
-        /* Looks good. Set the sign indicator and form, as needed. */
-        // Trailing zeros are preserved
-        // The rule here for form is:
-        // If no E-notation, then request plain notation
-        // Otherwise act as though add(0,DEFAULT) and request scientific notation
-        // [form is already PLAIN]
-        if (mant[0] == 0) {
-            ind = iszero; // force to show zero
-            // negative exponent is significant (e.g., -3 for 0.000) if plain
-            if (exp > 0)
-                exp = 0; // positive exponent can be ignored
-            if (hadexp) { // zero becomes single digit from add
-                mant = ZERO.mant;
-                exp = 0;
-            }
-        } else { // non-zero
-            // [ind was set earlier]
-            // now determine form
-            if (hadexp) {
-                form = (byte) com.ibm.icu.math.MathContext.SCIENTIFIC;
-                // 1999.06.29 check for overflow
-                mag = (exp + mant.length) - 1; // true exponent in scientific notation
-                if ((mag < MinExp) | (mag > MaxExp))
-                    bad(inchars);
-            }
-        }
-        // say 'BD(c[]): mant[0] mantlen exp ind form:' mant[0] mant.length exp ind form
-        return;
-    }
-
-    /**
-     * Constructs a <code>BigDecimal</code> object directly from a <code>double</code>.
-     * <p>
-     * Constructs a <code>BigDecimal</code> which is the exact decimal representation of the 64-bit signed binary
-     * floating point parameter.
-     * <p>
-     * Note that this constructor it an exact conversion; it does not give the same result as converting <code>num
-     * </code> to a <code>String</code> using the <code>Double.toString()</code> method and then using the
-     * {@link #BigDecimal(java.lang.String)} constructor. To get that result, use the static {@link #valueOf(double)}
-     * method to construct a <code>BigDecimal</code> from a <code>double</code>.
-     * 
-     * @param num The <code>double</code> to be converted.
-     * @throws NumberFormatException If the parameter is infinite or not a number.
-     * @stable ICU 2.0
-     */
-
-    public BigDecimal(double num) {
-        // 1999.03.06: use exactly the old algorithm
-        // 2000.01.01: note that this constructor does give an exact result,
-        // so perhaps it should not be deprecated
-        // 2000.06.18: no longer deprecated
-        this((new java.math.BigDecimal(num)).toString());
-        return;
-    }
-
-    /**
-     * Constructs a <code>BigDecimal</code> object directly from a <code>int</code>.
-     * <p>
-     * Constructs a <code>BigDecimal</code> which is the exact decimal representation of the 32-bit signed binary
-     * integer parameter. The <code>BigDecimal</code> will contain only decimal digits, prefixed with a leading minus
-     * sign (hyphen) if the parameter is negative. A leading zero will be present only if the parameter is zero.
-     * 
-     * @param num The <code>int</code> to be converted.
-     * @stable ICU 2.0
-     */
-
-    public BigDecimal(int num) {
-        super();
-        int mun;
-        int i = 0;
-        // We fastpath commoners
-        if (num <= 9)
-            if (num >= (-9)) {
-                do {
-                    // very common single digit case
-                    {/* select */
-                        if (num == 0) {
-                            mant = ZERO.mant;
-                            ind = iszero;
-                        } else if (num == 1) {
-                            mant = ONE.mant;
-                            ind = ispos;
-                        } else if (num == (-1)) {
-                            mant = ONE.mant;
-                            ind = isneg;
-                        } else {
-                            {
-                                mant = new byte[1];
-                                if (num > 0) {
-                                    mant[0] = (byte) num;
-                                    ind = ispos;
-                                } else { // num<-1
-                                    mant[0] = (byte) -num;
-                                    ind = isneg;
-                                }
-                            }
-                        }
-                    }
-                    return;
-                } while (false);
-            }/* singledigit */
-
-        /* We work on negative numbers so we handle the most negative number */
-        if (num > 0) {
-            ind = ispos;
-            num = -num;
-        } else
-            ind = isneg;/* negative */// [0 case already handled]
-        // [it is quicker, here, to pre-calculate the length with
-        // one loop, then allocate exactly the right length of byte array,
-        // then re-fill it with another loop]
-        mun = num; // working copy
-        {
-            i = 9;
-            i: for (;; i--) {
-                mun = mun / 10;
-                if (mun == 0)
-                    break i;
-            }
-        }/* i */
-        // i is the position of the leftmost digit placed
-        mant = new byte[10 - i];
-        {
-            i = (10 - i) - 1;
-            i: for (;; i--) {
-                mant[i] = (byte) -(((byte) (num % 10)));
-                num = num / 10;
-                if (num == 0)
-                    break i;
-            }
-        }/* i */
-        return;
-    }
-
-    /**
-     * Constructs a <code>BigDecimal</code> object directly from a <code>long</code>.
-     * <p>
-     * Constructs a <code>BigDecimal</code> which is the exact decimal representation of the 64-bit signed binary
-     * integer parameter. The <code>BigDecimal</code> will contain only decimal digits, prefixed with a leading minus
-     * sign (hyphen) if the parameter is negative. A leading zero will be present only if the parameter is zero.
-     * 
-     * @param num The <code>long</code> to be converted.
-     * @stable ICU 2.0
-     */
-
-    public BigDecimal(long num) {
-        super();
-        long mun;
-        int i = 0;
-        // Not really worth fastpathing commoners in this constructor [also,
-        // we use this to construct the static constants].
-        // This is much faster than: this(String.valueOf(num).toCharArray())
-        /* We work on negative num so we handle the most negative number */
-        if (num > 0) {
-            ind = ispos;
-            num = -num;
-        } else if (num == 0)
-            ind = iszero;
-        else
-            ind = isneg;/* negative */
-        mun = num;
-        {
-            i = 18;
-            i: for (;; i--) {
-                mun = mun / 10;
-                if (mun == 0)
-                    break i;
-            }
-        }/* i */
-        // i is the position of the leftmost digit placed
-        mant = new byte[19 - i];
-        {
-            i = (19 - i) - 1;
-            i: for (;; i--) {
-                mant[i] = (byte) -(((byte) (num % 10)));
-                num = num / 10;
-                if (num == 0)
-                    break i;
-            }
-        }/* i */
-        return;
-    }
-
-    /**
-     * Constructs a <code>BigDecimal</code> object from a <code>String</code>.
-     * <p>
-     * Constructs a <code>BigDecimal</code> from the parameter, which must not be <code>null</code> and must represent a
-     * valid <i>number</i>, as described formally in the documentation referred to {@link BigDecimal above}.
-     * <p>
-     * In summary, numbers in <code>String</code> form must have at least one digit, may have a leading sign, may have a
-     * decimal point, and exponential notation may be used. They follow conventional syntax, and may not contain blanks.
-     * <p>
-     * Some valid strings from which a <code>BigDecimal</code> might be constructed are:
-     * 
-     * <pre>
-     * 
-     * "0" -- Zero "12" -- A whole number "-76" -- A signed whole number "12.70" -- Some decimal places "+0.003" -- Plus
-     * sign is allowed "17." -- The same as 17 ".5" -- The same as 0.5 "4E+9" -- Exponential notation "0.73e-7" --
-     * Exponential notation
-     * 
-     * </pre>
-     * <p>
-     * (Exponential notation means that the number includes an optional sign and a power of ten following an
-     * '</code>E</code>' that indicates how the decimal point will be shifted. Thus the <code>"4E+9"</code> above is
-     * just a short way of writing <code>4000000000</code>, and the <code>"0.73e-7"</code> is short for <code>
-     * 0.000000073</code>.)
-     * <p>
-     * The <code>BigDecimal</code> constructed from the String is in a standard form, with no blanks, as though the
-     * {@link #add(BigDecimal)} method had been used to add zero to the number with unlimited precision. If the string
-     * uses exponential notation (that is, includes an <code>e</code> or an <code>E</code>), then the <code>BigDecimal
-     * </code> number will be expressed in scientific notation (where the power of ten is adjusted so there is a single
-     * non-zero digit to the left of the decimal point); in this case if the number is zero then it will be expressed as
-     * the single digit 0, and if non-zero it will have an exponent unless that exponent would be 0. The exponent must
-     * fit in nine digits both before and after it is expressed in scientific notation.
-     * <p>
-     * Any digits in the parameter must be decimal; that is, <code>Character.digit(c, 10)</code> (where </code>c</code>
-     * is the character in question) would not return -1.
-     * 
-     * @param string The <code>String</code> to be converted.
-     * @throws NumberFormatException If the parameter is not a valid number.
-     * @stable ICU 2.0
-     */
-
-    public BigDecimal(java.lang.String string) {
-        this(string.toCharArray(), 0, string.length());
-        return;
-    }
-
-    /* <sgml> Make a default BigDecimal object for local use. </sgml> */
-
-    private BigDecimal() {
-        super();
-        return;
-    }
-
-    /* ---------------------------------------------------------------- */
-    /* Operator methods [methods which take a context parameter] */
-    /* ---------------------------------------------------------------- */
-
-    /**
-     * Returns a plain <code>BigDecimal</code> whose value is the absolute value of this <code>BigDecimal</code>.
-     * <p>
-     * The same as {@link #abs(MathContext)}, where the context is <code>new MathContext(0, MathContext.PLAIN)</code>.
-     * <p>
-     * The length of the decimal part (the scale) of the result will be <code>this.scale()</code>
-     * 
-     * @return A <code>BigDecimal</code> whose value is the absolute value of this <code>BigDecimal</code>.
-     * @stable ICU 2.0
-     */
-
-    public com.ibm.icu.math.BigDecimal abs() {
-        return this.abs(plainMC);
-    }
-
-    /**
-     * Returns a <code>BigDecimal</code> whose value is the absolute value of this <code>BigDecimal</code>.
-     * <p>
-     * If the current object is zero or positive, then the same result as invoking the {@link #plus(MathContext)} method
-     * with the same parameter is returned. Otherwise, the same result as invoking the {@link #negate(MathContext)}
-     * method with the same parameter is returned.
-     * 
-     * @param set The <code>MathContext</code> arithmetic settings.
-     * @return A <code>BigDecimal</code> whose value is the absolute value of this <code>BigDecimal</code>.
-     * @stable ICU 2.0
-     */
-
-    public com.ibm.icu.math.BigDecimal abs(com.ibm.icu.math.MathContext set) {
-        if (this.ind == isneg)
-            return this.negate(set);
-        return this.plus(set);
-    }
-
-    /**
-     * Returns a plain <code>BigDecimal</code> whose value is <code>this+rhs</code>, using fixed point arithmetic.
-     * <p>
-     * The same as {@link #add(BigDecimal, MathContext)}, where the <code>BigDecimal</code> is <code>rhs</code>, and the
-     * context is <code>new MathContext(0, MathContext.PLAIN)</code>.
-     * <p>
-     * The length of the decimal part (the scale) of the result will be the maximum of the scales of the two operands.
-     * 
-     * @param rhs The <code>BigDecimal</code> for the right hand side of the addition.
-     * @return A <code>BigDecimal</code> whose value is <code>this+rhs</code>, using fixed point arithmetic.
-     * @stable ICU 2.0
-     */
-
-    public com.ibm.icu.math.BigDecimal add(com.ibm.icu.math.BigDecimal rhs) {
-        return this.add(rhs, plainMC);
-    }
-
-    /**
-     * Returns a <code>BigDecimal</code> whose value is <code>this+rhs</code>.
-     * <p>
-     * Implements the addition (<b><code>+</code></b>) operator (as defined in the decimal documentation, see
-     * {@link BigDecimal class header}), and returns the result as a <code>BigDecimal</code> object.
-     * 
-     * @param rhs The <code>BigDecimal</code> for the right hand side of the addition.
-     * @param set The <code>MathContext</code> arithmetic settings.
-     * @return A <code>BigDecimal</code> whose value is <code>this+rhs</code>.
-     * @stable ICU 2.0
-     */
-
-    public com.ibm.icu.math.BigDecimal add(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) {
-        com.ibm.icu.math.BigDecimal lhs;
-        int reqdig;
-        com.ibm.icu.math.BigDecimal res;
-        byte usel[];
-        int usellen;
-        byte user[];
-        int userlen;
-        int newlen = 0;
-        int tlen = 0;
-        int mult = 0;
-        byte t[] = null;
-        int ia = 0;
-        int ib = 0;
-        int ea = 0;
-        int eb = 0;
-        byte ca = 0;
-        byte cb = 0;
-        /* determine requested digits and form */
-        if (set.lostDigits)
-            checkdigits(rhs, set.digits);
-        lhs = this; // name for clarity and proxy
-
-        /* Quick exit for add floating 0 */
-        // plus() will optimize to return same object if possible
-        if (lhs.ind == 0)
-            if (set.form != com.ibm.icu.math.MathContext.PLAIN)
-                return rhs.plus(set);
-        if (rhs.ind == 0)
-            if (set.form != com.ibm.icu.math.MathContext.PLAIN)
-                return lhs.plus(set);
-
-        /* Prepare numbers (round, unless unlimited precision) */
-        reqdig = set.digits; // local copy (heavily used)
-        if (reqdig > 0) {
-            if (lhs.mant.length > reqdig)
-                lhs = clone(lhs).round(set);
-            if (rhs.mant.length > reqdig)
-                rhs = clone(rhs).round(set);
-            // [we could reuse the new LHS for result in this case]
-        }
-
-        res = new com.ibm.icu.math.BigDecimal(); // build result here
-
-        /*
-         * Now see how much we have to pad or truncate lhs or rhs in order to align the numbers. If one number is much
-         * larger than the other, then the smaller cannot affect the answer [but we may still need to pad with up to
-         * DIGITS trailing zeros].
-         */
-        // Note sign may be 0 if digits (reqdig) is 0
-        // usel and user will be the byte arrays passed to the adder; we'll
-        // use them on all paths except quick exits
-        usel = lhs.mant;
-        usellen = lhs.mant.length;
-        user = rhs.mant;
-        userlen = rhs.mant.length;
-        {
-            do {/* select */
-                if (lhs.exp == rhs.exp) {/* no padding needed */
-                    // This is the most common, and fastest, path
-                    res.exp = lhs.exp;
-                } else if (lhs.exp > rhs.exp) { // need to pad lhs and/or truncate rhs
-                    newlen = (usellen + lhs.exp) - rhs.exp;
-                    /*
-                     * If, after pad, lhs would be longer than rhs by digits+1 or more (and digits>0) then rhs cannot
-                     * affect answer, so we only need to pad up to a length of DIGITS+1.
-                     */
-                    if (newlen >= ((userlen + reqdig) + 1))
-                        if (reqdig > 0) {
-                            // LHS is sufficient
-                            res.mant = usel;
-                            res.exp = lhs.exp;
-                            res.ind = lhs.ind;
-                            if (usellen < reqdig) { // need 0 padding
-                                res.mant = extend(lhs.mant, reqdig);
-                                res.exp = res.exp - ((reqdig - usellen));
-                            }
-                            return res.finish(set, false);
-                        }
-                    // RHS may affect result
-                    res.exp = rhs.exp; // expected final exponent
-                    if (newlen > (reqdig + 1))
-                        if (reqdig > 0) {
-                            // LHS will be max; RHS truncated
-                            tlen = (newlen - reqdig) - 1; // truncation length
-                            userlen = userlen - tlen;
-                            res.exp = res.exp + tlen;
-                            newlen = reqdig + 1;
-                        }
-                    if (newlen > usellen)
-                        usellen = newlen; // need to pad LHS
-                } else { // need to pad rhs and/or truncate lhs
-                    newlen = (userlen + rhs.exp) - lhs.exp;
-                    if (newlen >= ((usellen + reqdig) + 1))
-                        if (reqdig > 0) {
-                            // RHS is sufficient
-                            res.mant = user;
-                            res.exp = rhs.exp;
-                            res.ind = rhs.ind;
-                            if (userlen < reqdig) { // need 0 padding
-                                res.mant = extend(rhs.mant, reqdig);
-                                res.exp = res.exp - ((reqdig - userlen));
-                            }
-                            return res.finish(set, false);
-                        }
-                    // LHS may affect result
-                    res.exp = lhs.exp; // expected final exponent
-                    if (newlen > (reqdig + 1))
-                        if (reqdig > 0) {
-                            // RHS will be max; LHS truncated
-                            tlen = (newlen - reqdig) - 1; // truncation length
-                            usellen = usellen - tlen;
-                            res.exp = res.exp + tlen;
-                            newlen = reqdig + 1;
-                        }
-                    if (newlen > userlen)
-                        userlen = newlen; // need to pad RHS
-                }
-            } while (false);
-        }/* padder */
-
-        /* OK, we have aligned mantissas. Now add or subtract. */
-        // 1998.06.27 Sign may now be 0 [e.g., 0.000] .. treat as positive
-        // 1999.05.27 Allow for 00 on lhs [is not larger than 2 on rhs]
-        // 1999.07.10 Allow for 00 on rhs [is not larger than 2 on rhs]
-        if (lhs.ind == iszero)
-            res.ind = ispos;
-        else
-            res.ind = lhs.ind; // likely sign, all paths
-        if (((lhs.ind == isneg) ? 1 : 0) == ((rhs.ind == isneg) ? 1 : 0)) // same sign, 0 non-negative
-            mult = 1;
-        else {
-            do { // different signs, so subtraction is needed
-                mult = -1; // will cause subtract
-                /*
-                 * Before we can subtract we must determine which is the larger, as our add/subtract routine only
-                 * handles non-negative results so we may need to swap the operands.
-                 */
-                {
-                    do {/* select */
-                        if (rhs.ind == iszero) {
-                            // original A bigger
-                        } else if ((usellen < userlen) | (lhs.ind == iszero)) { // original B bigger
-                            t = usel;
-                            usel = user;
-                            user = t; // swap
-                            tlen = usellen;
-                            usellen = userlen;
-                            userlen = tlen; // ..
-                            res.ind = (byte) -res.ind; // and set sign
-                        } else if (usellen > userlen) {
-                            // original A bigger
-                        } else {
-                            {/* logical lengths the same */// need compare
-                                /* may still need to swap: compare the strings */
-                                ia = 0;
-                                ib = 0;
-                                ea = usel.length - 1;
-                                eb = user.length - 1;
-                                {
-                                    compare: for (;;) {
-                                        if (ia <= ea)
-                                            ca = usel[ia];
-                                        else {
-                                            if (ib > eb) {/* identical */
-                                                if (set.form != com.ibm.icu.math.MathContext.PLAIN)
-                                                    return ZERO;
-                                                // [if PLAIN we must do the subtract, in case of 0.000 results]
-                                                break compare;
-                                            }
-                                            ca = (byte) 0;
-                                        }
-                                        if (ib <= eb)
-                                            cb = user[ib];
-                                        else
-                                            cb = (byte) 0;
-                                        if (ca != cb) {
-                                            if (ca < cb) {/* swap needed */
-                                                t = usel;
-                                                usel = user;
-                                                user = t; // swap
-                                                tlen = usellen;
-                                                usellen = userlen;
-                                                userlen = tlen; // ..
-                                                res.ind = (byte) -res.ind;
-                                            }
-                                            break compare;
-                                        }
-                                        /* mantissas the same, so far */
-                                        ia++;
-                                        ib++;
-                                    }
-                                }/* compare */
-                            } // lengths the same
-                        }
-                    } while (false);
-                }/* swaptest */
-            } while (false);
-        }/* signdiff */
-
-        /* here, A is > B if subtracting */
-        // add [A+B*1] or subtract [A+(B*-1)]
-        res.mant = byteaddsub(usel, usellen, user, userlen, mult, false);
-        // [reuse possible only after chop; accounting makes not worthwhile]
-
-        // Finish() rounds before stripping leading 0's, then sets form, etc.
-        return res.finish(set, false);
-    }
-
-    /**
-     * Compares this <code>BigDecimal</code> to another, using unlimited precision.
-     * <p>
-     * The same as {@link #compareTo(BigDecimal, MathContext)}, where the <code>BigDecimal</code> is <code>rhs</code>,
-     * and the context is <code>new MathContext(0, MathContext.PLAIN)</code>.
-     * 
-     * @param rhs The <code>BigDecimal</code> for the right hand side of the comparison.
-     * @return An <code>int</code> whose value is -1, 0, or 1 as <code>this</code> is numerically less than, equal to,
-     *         or greater than <code>rhs</code>.
-     * @stable ICU 2.0
-     */
-
-    public int compareTo(com.ibm.icu.math.BigDecimal rhs) {
-        return this.compareTo(rhs, plainMC);
-    }
-
-    /**
-     * Compares this <code>BigDecimal</code> to another.
-     * <p>
-     * Implements numeric comparison, (as defined in the decimal documentation, see {@link BigDecimal class header}),
-     * and returns a result of type <code>int</code>.
-     * <p>
-     * The result will be:
-     * <table cellpadding=2>
-     * <tr>
-     * <td align=right><b>-1</b></td> <td>if the current object is less than the first parameter</td>
-     * </tr>
-     * <tr>
-     * <td align=right><b>0</b></td> <td>if the current object is equal to the first parameter</td>
-     * </tr>
-     * <tr>
-     * <td align=right><b>1</b></td> <td>if the current object is greater than the first parameter.</td>
-     * </tr>
-     * </table>
-     * <p>
-     * A {@link #compareTo(BigDecimal)} method is also provided.
-     * 
-     * @param rhs The <code>BigDecimal</code> for the right hand side of the comparison.
-     * @param set The <code>MathContext</code> arithmetic settings.
-     * @return An <code>int</code> whose value is -1, 0, or 1 as <code>this</code> is numerically less than, equal to,
-     *         or greater than <code>rhs</code>.
-     * @stable ICU 2.0
-     */
-
-    public int compareTo(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) {
-        int thislength = 0;
-        int i = 0;
-        com.ibm.icu.math.BigDecimal newrhs;
-        // rhs=null will raise NullPointerException, as per Comparable interface
-        if (set.lostDigits)
-            checkdigits(rhs, set.digits);
-        // [add will recheck in slowpath cases .. but would report -rhs]
-        if ((this.ind == rhs.ind) & (this.exp == rhs.exp)) {
-            /* sign & exponent the same [very common] */
-            thislength = this.mant.length;
-            if (thislength < rhs.mant.length)
-                return (byte) -this.ind;
-            if (thislength > rhs.mant.length)
-                return this.ind;
-            /*
-             * lengths are the same; we can do a straight mantissa compare unless maybe rounding [rounding is very
-             * unusual]
-             */
-            if ((thislength <= set.digits) | (set.digits == 0)) {
-                {
-                    int $6 = thislength;
-                    i = 0;
-                    for (; $6 > 0; $6--, i++) {
-                        if (this.mant[i] < rhs.mant[i])
-                            return (byte) -this.ind;
-                        if (this.mant[i] > rhs.mant[i])
-                            return this.ind;
-                    }
-                }/* i */
-                return 0; // identical
-            }
-            /* drop through for full comparison */
-        } else {
-            /* More fastpaths possible */
-            if (this.ind < rhs.ind)
-                return -1;
-            if (this.ind > rhs.ind)
-                return 1;
-        }
-        /* carry out a subtract to make the comparison */
-        newrhs = clone(rhs); // safe copy
-        newrhs.ind = (byte) -newrhs.ind; // prepare to subtract
-        return this.add(newrhs, set).ind; // add, and return sign of result
-    }
-
-    /**
-     * Returns a plain <code>BigDecimal</code> whose value is <code>this/rhs</code>, using fixed point arithmetic.
-     * <p>
-     * The same as {@link #divide(BigDecimal, int)}, where the <code>BigDecimal</code> is <code>rhs</code>, and the
-     * rounding mode is {@link MathContext#ROUND_HALF_UP}.
-     * 
-     * The length of the decimal part (the scale) of the result will be the same as the scale of the current object, if
-     * the latter were formatted without exponential notation.
-     * 
-     * @param rhs The <code>BigDecimal</code> for the right hand side of the division.
-     * @return A plain <code>BigDecimal</code> whose value is <code>this/rhs</code>, using fixed point arithmetic.
-     * @throws ArithmeticException If <code>rhs</code> is zero.
-     * @stable ICU 2.0
-     */
-
-    public com.ibm.icu.math.BigDecimal divide(com.ibm.icu.math.BigDecimal rhs) {
-        return this.dodivide('D', rhs, plainMC, -1);
-    }
-
-    /**
-     * Returns a plain <code>BigDecimal</code> whose value is <code>this/rhs</code>, using fixed point arithmetic and a
-     * rounding mode.
-     * <p>
-     * The same as {@link #divide(BigDecimal, int, int)}, where the <code>BigDecimal</code> is <code>rhs</code>, and the
-     * second parameter is <code>this.scale()</code>, and the third is <code>round</code>.
-     * <p>
-     * The length of the decimal part (the scale) of the result will therefore be the same as the scale of the current
-     * object, if the latter were formatted without exponential notation.
-     * <p>
-     * 
-     * @param rhs The <code>BigDecimal</code> for the right hand side of the division.
-     * @param round The <code>int</code> rounding mode to be used for the division (see the {@link MathContext} class).
-     * @return A plain <code>BigDecimal</code> whose value is <code>this/rhs</code>, using fixed point arithmetic and
-     *         the specified rounding mode.
-     * @throws IllegalArgumentException if <code>round</code> is not a valid rounding mode.
-     * @throws ArithmeticException if <code>rhs</code> is zero.
-     * @throws ArithmeticException if <code>round</code> is {@link MathContext#ROUND_UNNECESSARY} and <code>this.scale()</code> is insufficient to represent the result exactly.
-     * @stable ICU 2.0
-     */
-
-    public com.ibm.icu.math.BigDecimal divide(com.ibm.icu.math.BigDecimal rhs, int round) {
-        com.ibm.icu.math.MathContext set;
-        set = new com.ibm.icu.math.MathContext(0, com.ibm.icu.math.MathContext.PLAIN, false, round); // [checks round,
-                                                                                                     // too]
-        return this.dodivide('D', rhs, set, -1); // take scale from LHS
-    }
-
-    /**
-     * Returns a plain <code>BigDecimal</code> whose value is <code>this/rhs</code>, using fixed point arithmetic and a
-     * given scale and rounding mode.
-     * <p>
-     * The same as {@link #divide(BigDecimal, MathContext)}, where the <code>BigDecimal</code> is <code>rhs</code>,
-     * <code>new MathContext(0, MathContext.PLAIN, false, round)</code>, except that the length of the decimal part (the
-     * scale) to be used for the result is explicit rather than being taken from <code>this</code>.
-     * <p>
-     * The length of the decimal part (the scale) of the result will be the same as the scale of the current object, if
-     * the latter were formatted without exponential notation.
-     * <p>
-     * 
-     * @param rhs The <code>BigDecimal</code> for the right hand side of the division.
-     * @param scale The <code>int</code> scale to be used for the result.
-     * @param round The <code>int</code> rounding mode to be used for the division (see the {@link MathContext} class).
-     * @return A plain <code>BigDecimal</code> whose value is <code>this/rhs</code>, using fixed point arithmetic and
-     *         the specified rounding mode.
-     * @throws IllegalArgumentException if <code>round</code> is not a valid rounding mode.
-     * @throws ArithmeticException if <code>rhs</code> is zero.
-     * @throws ArithmeticException if <code>scale</code> is negative.
-     * @throws ArithmeticException if <code>round</code> is {@link MathContext#ROUND_UNNECESSARY} and <code>scale</code> is insufficient
-     *             to represent the result exactly.
-     * @stable ICU 2.0
-     */
-
-    public com.ibm.icu.math.BigDecimal divide(com.ibm.icu.math.BigDecimal rhs, int scale, int round) {
-        com.ibm.icu.math.MathContext set;
-        if (scale < 0)
-            throw new java.lang.ArithmeticException("Negative scale:" + " " + scale);
-        set = new com.ibm.icu.math.MathContext(0, com.ibm.icu.math.MathContext.PLAIN, false, round); // [checks round]
-        return this.dodivide('D', rhs, set, scale);
-    }
-
-    /**
-     * Returns a <code>BigDecimal</code> whose value is <code>this/rhs</code>.
-     * <p>
-     * Implements the division (<b><code>/</code></b>) operator (as defined in the decimal documentation, see
-     * {@link BigDecimal class header}), and returns the result as a <code>BigDecimal</code> object.
-     * 
-     * @param rhs The <code>BigDecimal</code> for the right hand side of the division.
-     * @param set The <code>MathContext</code> arithmetic settings.
-     * @return A <code>BigDecimal</code> whose value is <code>this/rhs</code>.
-     * @throws ArithmeticException if <code>rhs</code> is zero.
-     * @stable ICU 2.0
-     */
-
-    public com.ibm.icu.math.BigDecimal divide(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) {
-        return this.dodivide('D', rhs, set, -1);
-    }
-
-    /**
-     * Returns a plain <code>BigDecimal</code> whose value is the integer part of <code>this/rhs</code>.
-     * <p>
-     * The same as {@link #divideInteger(BigDecimal, MathContext)}, where the <code>BigDecimal</code> is <code>rhs
-     * </code>, and the context is <code>new MathContext(0, MathContext.PLAIN)</code>.
-     * 
-     * @param rhs The <code>BigDecimal</code> for the right hand side of the integer division.
-     * @return A <code>BigDecimal</code> whose value is the integer part of <code>this/rhs</code>.
-     * @throws ArithmeticException if <code>rhs</code> is zero.
-     * @stable ICU 2.0
-     */
-
-    public com.ibm.icu.math.BigDecimal divideInteger(com.ibm.icu.math.BigDecimal rhs) {
-        // scale 0 to drop .000 when plain
-        return this.dodivide('I', rhs, plainMC, 0);
-    }
-
-    /**
-     * Returns a <code>BigDecimal</code> whose value is the integer part of <code>this/rhs</code>.
-     * <p>
-     * Implements the integer division operator (as defined in the decimal documentation, see {@link BigDecimal class
-     * header}), and returns the result as a <code>BigDecimal</code> object.
-     * 
-     * @param rhs The <code>BigDecimal</code> for the right hand side of the integer division.
-     * @param set The <code>MathContext</code> arithmetic settings.
-     * @return A <code>BigDecimal</code> whose value is the integer part of <code>this/rhs</code>.
-     * @throws ArithmeticException if <code>rhs</code> is zero.
-     * @throws ArithmeticException if the result will not fit in the number of digits specified for the context.
-     * @stable ICU 2.0
-     */
-
-    public com.ibm.icu.math.BigDecimal divideInteger(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) {
-        // scale 0 to drop .000 when plain
-        return this.dodivide('I', rhs, set, 0);
-    }
-
-    /**
-     * Returns a plain <code>BigDecimal</code> whose value is the maximum of <code>this</code> and <code>rhs</code>.
-     * <p>
-     * The same as {@link #max(BigDecimal, MathContext)}, where the <code>BigDecimal</code> is <code>rhs</code>, and the
-     * context is <code>new MathContext(0, MathContext.PLAIN)</code>.
-     * 
-     * @param rhs The <code>BigDecimal</code> for the right hand side of the comparison.
-     * @return A <code>BigDecimal</code> whose value is the maximum of <code>this</code> and <code>rhs</code>.
-     * @stable ICU 2.0
-     */
-
-    public com.ibm.icu.math.BigDecimal max(com.ibm.icu.math.BigDecimal rhs) {
-        return this.max(rhs, plainMC);
-    }
-
-    /**
-     * Returns a <code>BigDecimal</code> whose value is the maximum of <code>this</code> and <code>rhs</code>.
-     * <p>
-     * Returns the larger of the current object and the first parameter.
-     * <p>
-     * If calling the {@link #compareTo(BigDecimal, MathContext)} method with the same parameters would return <code>1
-     * </code> or <code>0</code>, then the result of calling the {@link #plus(MathContext)} method on the current object
-     * (using the same <code>MathContext</code> parameter) is returned. Otherwise, the result of calling the
-     * {@link #plus(MathContext)} method on the first parameter object (using the same <code>MathContext</code>
-     * parameter) is returned.
-     * 
-     * @param rhs The <code>BigDecimal</code> for the right hand side of the comparison.
-     * @param set The <code>MathContext</code> arithmetic settings.
-     * @return A <code>BigDecimal</code> whose value is the maximum of <code>this</code> and <code>rhs</code>.
-     * @stable ICU 2.0
-     */
-
-    public com.ibm.icu.math.BigDecimal max(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) {
-        if ((this.compareTo(rhs, set)) >= 0)
-            return this.plus(set);
-        else
-            return rhs.plus(set);
-    }
-
-    /**
-     * Returns a plain <code>BigDecimal</code> whose value is the minimum of <code>this</code> and <code>rhs</code>.
-     * <p>
-     * The same as {@link #min(BigDecimal, MathContext)}, where the <code>BigDecimal</code> is <code>rhs</code>, and the
-     * context is <code>new MathContext(0, MathContext.PLAIN)</code>.
-     * 
-     * @param rhs The <code>BigDecimal</code> for the right hand side of the comparison.
-     * @return A <code>BigDecimal</code> whose value is the minimum of <code>this</code> and <code>rhs</code>.
-     * @stable ICU 2.0
-     */
-
-    public com.ibm.icu.math.BigDecimal min(com.ibm.icu.math.BigDecimal rhs) {
-        return this.min(rhs, plainMC);
-    }
-
-    /**
-     * Returns a <code>BigDecimal</code> whose value is the minimum of <code>this</code> and <code>rhs</code>.
-     * <p>
-     * Returns the smaller of the current object and the first parameter.
-     * <p>
-     * If calling the {@link #compareTo(BigDecimal, MathContext)} method with the same parameters would return <code>-1
-     * </code> or <code>0</code>, then the result of calling the {@link #plus(MathContext)} method on the current object
-     * (using the same <code>MathContext</code> parameter) is returned. Otherwise, the result of calling the
-     * {@link #plus(MathContext)} method on the first parameter object (using the same <code>MathContext</code>
-     * parameter) is returned.
-     * 
-     * @param rhs The <code>BigDecimal</code> for the right hand side of the comparison.
-     * @param set The <code>MathContext</code> arithmetic settings.
-     * @return A <code>BigDecimal</code> whose value is the minimum of <code>this</code> and <code>rhs</code>.
-     * @stable ICU 2.0
-     */
-
-    public com.ibm.icu.math.BigDecimal min(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) {
-        if ((this.compareTo(rhs, set)) <= 0)
-            return this.plus(set);
-        else
-            return rhs.plus(set);
-    }
-
-    /**
-     * Returns a plain <code>BigDecimal</code> whose value is <code>this*rhs</code>, using fixed point arithmetic.
-     * <p>
-     * The same as {@link #add(BigDecimal, MathContext)}, where the <code>BigDecimal</code> is <code>rhs</code>, and the
-     * context is <code>new MathContext(0, MathContext.PLAIN)</code>.
-     * <p>
-     * The length of the decimal part (the scale) of the result will be the sum of the scales of the operands, if they
-     * were formatted without exponential notation.
-     * 
-     * @param rhs The <code>BigDecimal</code> for the right hand side of the multiplication.
-     * @return A <code>BigDecimal</code> whose value is <code>this*rhs</code>, using fixed point arithmetic.
-     * @stable ICU 2.0
-     */
-
-    public com.ibm.icu.math.BigDecimal multiply(com.ibm.icu.math.BigDecimal rhs) {
-        return this.multiply(rhs, plainMC);
-    }
-
-    /**
-     * Returns a <code>BigDecimal</code> whose value is <code>this*rhs</code>.
-     * <p>
-     * Implements the multiplication (<b><code> </code></b>) operator (as defined in the decimal documentation, see
-     * {@link BigDecimal class header}), and returns the result as a <code>BigDecimal</code> object.
-     * 
-     * @param rhs The <code>BigDecimal</code> for the right hand side of the multiplication.
-     * @param set The <code>MathContext</code> arithmetic settings.
-     * @return A <code>BigDecimal</code> whose value is <code>this*rhs</code>.
-     * @stable ICU 2.0
-     */
-
-    public com.ibm.icu.math.BigDecimal multiply(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) {
-        com.ibm.icu.math.BigDecimal lhs;
-        int padding;
-        int reqdig;
-        byte multer[] = null;
-        byte multand[] = null;
-        int multandlen;
-        int acclen = 0;
-        com.ibm.icu.math.BigDecimal res;
-        byte acc[];
-        int n = 0;
-        byte mult = 0;
-        if (set.lostDigits)
-            checkdigits(rhs, set.digits);
-        lhs = this; // name for clarity and proxy
-
-        /* Prepare numbers (truncate, unless unlimited precision) */
-        padding = 0; // trailing 0's to add
-        reqdig = set.digits; // local copy
-        if (reqdig > 0) {
-            if (lhs.mant.length > reqdig)
-                lhs = clone(lhs).round(set);
-            if (rhs.mant.length > reqdig)
-                rhs = clone(rhs).round(set);
-            // [we could reuse the new LHS for result in this case]
-        } else {/* unlimited */
-            // fixed point arithmetic will want every trailing 0; we add these
-            // after the calculation rather than before, for speed.
-            if (lhs.exp > 0)
-                padding = padding + lhs.exp;
-            if (rhs.exp > 0)
-                padding = padding + rhs.exp;
-        }
-
-        // For best speed, as in DMSRCN, we use the shorter number as the
-        // multiplier and the longer as the multiplicand.
-        // 1999.12.22: We used to special case when the result would fit in
-        // a long, but with Java 1.3 this gave no advantage.
-        if (lhs.mant.length < rhs.mant.length) {
-            multer = lhs.mant;
-            multand = rhs.mant;
-        } else {
-            multer = rhs.mant;
-            multand = lhs.mant;
-        }
-
-        /* Calculate how long result byte array will be */
-        multandlen = (multer.length + multand.length) - 1; // effective length
-        // optimize for 75% of the cases where a carry is expected...
-        if ((multer[0] * multand[0]) > 9)
-            acclen = multandlen + 1;
-        else
-            acclen = multandlen;
-
-        /* Now the main long multiplication loop */
-        res = new com.ibm.icu.math.BigDecimal(); // where we'll build result
-        acc = new byte[acclen]; // accumulator, all zeros
-        // 1998.07.01: calculate from left to right so that accumulator goes
-        // to likely final length on first addition; this avoids a one-digit
-        // extension (and object allocation) each time around the loop.
-        // Initial number therefore has virtual zeros added to right.
-        {
-            int $7 = multer.length;
-            n = 0;
-            for (; $7 > 0; $7--, n++) {
-                mult = multer[n];
-                if (mult != 0) { // [optimization]
-                    // accumulate [accumulator is reusable array]
-                    acc = byteaddsub(acc, acc.length, multand, multandlen, mult, true);
-                }
-                // divide multiplicand by 10 for next digit to right
-                multandlen--; // 'virtual length'
-            }
-        }/* n */
-
-        res.ind = (byte) (lhs.ind * rhs.ind); // final sign
-        res.exp = (lhs.exp + rhs.exp) - padding; // final exponent
-        // [overflow is checked by finish]
-
-        /* add trailing zeros to the result, if necessary */
-        if (padding == 0)
-            res.mant = acc;
-        else
-            res.mant = extend(acc, acc.length + padding); // add trailing 0s
-        return res.finish(set, false);
-    }
-
-    /**
-     * Returns a plain <code>BigDecimal</code> whose value is <code>-this</code>.
-     * <p>
-     * The same as {@link #negate(MathContext)}, where the context is <code>new MathContext(0, MathContext.PLAIN)</code>
-     * .
-     * <p>
-     * The length of the decimal part (the scale) of the result will be be <code>this.scale()</code>
-     * 
-     * 
-     * @return A <code>BigDecimal</code> whose value is <code>-this</code>.
-     * @stable ICU 2.0
-     */
-
-    public com.ibm.icu.math.BigDecimal negate() {
-        return this.negate(plainMC);
-    }
-
-    /**
-     * Returns a <code>BigDecimal</code> whose value is <code>-this</code>.
-     * <p>
-     * Implements the negation (Prefix <b><code>-</code></b>) operator (as defined in the decimal documentation, see
-     * {@link BigDecimal class header}), and returns the result as a <code>BigDecimal</code> object.
-     * 
-     * @param set The <code>MathContext</code> arithmetic settings.
-     * @return A <code>BigDecimal</code> whose value is <code>-this</code>.
-     * @stable ICU 2.0
-     */
-
-    public com.ibm.icu.math.BigDecimal negate(com.ibm.icu.math.MathContext set) {
-        com.ibm.icu.math.BigDecimal res;
-        // Originally called minus(), changed to matched Java precedents
-        // This simply clones, flips the sign, and possibly rounds
-        if (set.lostDigits)
-            checkdigits((com.ibm.icu.math.BigDecimal) null, set.digits);
-        res = clone(this); // safe copy
-        res.ind = (byte) -res.ind;
-        return res.finish(set, false);
-    }
-
-    /**
-     * Returns a plain <code>BigDecimal</code> whose value is <code>+this</code>. Note that <code>this</code> is not
-     * necessarily a plain <code>BigDecimal</code>, but the result will always be.
-     * <p>
-     * The same as {@link #plus(MathContext)}, where the context is <code>new MathContext(0, MathContext.PLAIN)</code>.
-     * <p>
-     * The length of the decimal part (the scale) of the result will be be <code>this.scale()</code>
-     * 
-     * @return A <code>BigDecimal</code> whose value is <code>+this</code>.
-     * @stable ICU 2.0
-     */
-
-    public com.ibm.icu.math.BigDecimal plus() {
-        return this.plus(plainMC);
-    }
-
-    /**
-     * Returns a <code>BigDecimal</code> whose value is <code>+this</code>.
-     * <p>
-     * Implements the plus (Prefix <b><code>+</code></b>) operator (as defined in the decimal documentation, see
-     * {@link BigDecimal class header}), and returns the result as a <code>BigDecimal</code> object.
-     * <p>
-     * This method is useful for rounding or otherwise applying a context to a decimal value.
-     * 
-     * @param set The <code>MathContext</code> arithmetic settings.
-     * @return A <code>BigDecimal</code> whose value is <code>+this</code>.
-     * @stable ICU 2.0
-     */
-
-    public com.ibm.icu.math.BigDecimal plus(com.ibm.icu.math.MathContext set) {
-        // This clones and forces the result to the new settings
-        // May return same object
-        if (set.lostDigits)
-            checkdigits((com.ibm.icu.math.BigDecimal) null, set.digits);
-        // Optimization: returns same object for some common cases
-        if (set.form == com.ibm.icu.math.MathContext.PLAIN)
-            if (this.form == com.ibm.icu.math.MathContext.PLAIN) {
-                if (this.mant.length <= set.digits)
-                    return this;
-                if (set.digits == 0)
-                    return this;
-            }
-        return clone(this).finish(set, false);
-    }
-
-    /**
-     * Returns a plain <code>BigDecimal</code> whose value is <code>this**rhs</code>, using fixed point arithmetic.
-     * <p>
-     * The same as {@link #pow(BigDecimal, MathContext)}, where the <code>BigDecimal</code> is <code>rhs</code>, and the
-     * context is <code>new MathContext(0, MathContext.PLAIN)</code>.
-     * <p>
-     * The parameter is the power to which the <code>this</code> will be raised; it must be in the range 0 through
-     * 999999999, and must have a decimal part of zero. Note that these restrictions may be removed in the future, so
-     * they should not be used as a test for a whole number.
-     * <p>
-     * In addition, the power must not be negative, as no <code>MathContext</code> is used and so the result would then
-     * always be 0.
-     * 
-     * @param rhs The <code>BigDecimal</code> for the right hand side of the operation (the power).
-     * @return A <code>BigDecimal</code> whose value is <code>this**rhs</code>, using fixed point arithmetic.
-     * @throws ArithmeticException if <code>rhs</code> is out of range or is not a whole number.
-     * @stable ICU 2.0
-     */
-
-    public com.ibm.icu.math.BigDecimal pow(com.ibm.icu.math.BigDecimal rhs) {
-        return this.pow(rhs, plainMC);
-    }
-
-    // The name for this method is inherited from the precedent set by the
-    // BigInteger and Math classes.
-
-    /**
-     * Returns a <code>BigDecimal</code> whose value is <code>this**rhs</code>.
-     * <p>
-     * Implements the power (<b><code> </code></b>) operator (as defined in the decimal documentation, see
-     * {@link BigDecimal class header}), and returns the result as a <code>BigDecimal</code> object.
-     * <p>
-     * The first parameter is the power to which the <code>this</code> will be raised; it must be in the range
-     * -999999999 through 999999999, and must have a decimal part of zero. Note that these restrictions may be removed
-     * in the future, so they should not be used as a test for a whole number.
-     * <p>
-     * If the <code>digits</code> setting of the <code>MathContext</code> parameter is 0, the power must be zero or
-     * positive.
-     * 
-     * @param rhs The <code>BigDecimal</code> for the right hand side of the operation (the power).
-     * @param set The <code>MathContext</code> arithmetic settings.
-     * @return A <code>BigDecimal</code> whose value is <code>this**rhs</code>.
-     * @throws ArithmeticException if <code>rhs</code> is out of range or is not a whole number.
-     * @stable ICU 2.0
-     */
-
-    public com.ibm.icu.math.BigDecimal pow(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) {
-        int n;
-        com.ibm.icu.math.BigDecimal lhs;
-        int reqdig;
-        int workdigits = 0;
-        int L = 0;
-        com.ibm.icu.math.MathContext workset;
-        com.ibm.icu.math.BigDecimal res;
-        boolean seenbit;
-        int i = 0;
-        if (set.lostDigits)
-            checkdigits(rhs, set.digits);
-        n = rhs.intcheck(MinArg, MaxArg); // check RHS by the rules
-        lhs = this; // clarified name
-
-        reqdig = set.digits; // local copy (heavily used)
-        if (reqdig == 0) {
-            if (rhs.ind == isneg)
-                throw new java.lang.ArithmeticException("Negative power:" + " " + rhs.toString());
-            workdigits = 0;
-        } else {/* non-0 digits */
-            if ((rhs.mant.length + rhs.exp) > reqdig)
-                throw new java.lang.ArithmeticException("Too many digits:" + " " + rhs.toString());
-
-            /* Round the lhs to DIGITS if need be */
-            if (lhs.mant.length > reqdig)
-                lhs = clone(lhs).round(set);
-
-            /* L for precision calculation [see ANSI X3.274-1996] */
-            L = rhs.mant.length + rhs.exp; // length without decimal zeros/exp
-            workdigits = (reqdig + L) + 1; // calculate the working DIGITS
-        }
-
-        /* Create a copy of set for working settings */
-        // Note: no need to check for lostDigits again.
-        // 1999.07.17 Note: this construction must follow RHS check
-        workset = new com.ibm.icu.math.MathContext(workdigits, set.form, false, set.roundingMode);
-
-        res = ONE; // accumulator
-        if (n == 0)
-            return res; // x**0 == 1
-        if (n < 0)
-            n = -n; // [rhs.ind records the sign]
-        seenbit = false; // set once we've seen a 1-bit
-        {
-            i = 1;
-            i: for (;; i++) { // for each bit [top bit ignored]
-                n = n + n; // shift left 1 bit
-                if (n < 0) { // top bit is set
-                    seenbit = true; // OK, we're off
-                    res = res.multiply(lhs, workset); // acc=acc*x
-                }
-                if (i == 31)
-                    break i; // that was the last bit
-                if ((!seenbit))
-                    continue i; // we don't have to square 1
-                res = res.multiply(res, workset); // acc=acc*acc [square]
-            }
-        }/* i */// 32 bits
-        if (rhs.ind < 0) // was a **-n [hence digits>0]
-            res = ONE.divide(res, workset); // .. so acc=1/acc
-        return res.finish(set, true); // round and strip [original digits]
-    }
-
-    /**
-     * Returns a plain <code>BigDecimal</code> whose value is the remainder of <code>this/rhs</code>, using fixed point
-     * arithmetic.
-     * <p>
-     * The same as {@link #remainder(BigDecimal, MathContext)}, where the <code>BigDecimal</code> is <code>rhs</code>,
-     * and the context is <code>new MathContext(0, MathContext.PLAIN)</code>.
-     * <p>
-     * This is not the modulo operator -- the result may be negative.
-     * 
-     * @param rhs The <code>BigDecimal</code> for the right hand side of the remainder operation.
-     * @return A <code>BigDecimal</code> whose value is the remainder of <code>this/rhs</code>, using fixed point
-     *         arithmetic.
-     * @throws ArithmeticException if <code>rhs</code> is zero.
-     * @stable ICU 2.0
-     */
-
-    public com.ibm.icu.math.BigDecimal remainder(com.ibm.icu.math.BigDecimal rhs) {
-        return this.dodivide('R', rhs, plainMC, -1);
-    }
-
-    /**
-     * Returns a <code>BigDecimal</code> whose value is the remainder of <code>this/rhs</code>.
-     * <p>
-     * Implements the remainder operator (as defined in the decimal documentation, see {@link BigDecimal class header}),
-     * and returns the result as a <code>BigDecimal</code> object.
-     * <p>
-     * This is not the modulo operator -- the result may be negative.
-     * 
-     * @param rhs The <code>BigDecimal</code> for the right hand side of the remainder operation.
-     * @param set The <code>MathContext</code> arithmetic settings.
-     * @return A <code>BigDecimal</code> whose value is the remainder of <code>this+rhs</code>.
-     * @throws ArithmeticException if <code>rhs</code> is zero.
-     * @throws ArithmeticException  if the integer part of the result will not fit in the number of digits specified for the context.
-     * @stable ICU 2.0
-     */
-
-    public com.ibm.icu.math.BigDecimal remainder(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) {
-        return this.dodivide('R', rhs, set, -1);
-    }
-
-    /**
-     * Returns a plain <code>BigDecimal</code> whose value is <code>this-rhs</code>, using fixed point arithmetic.
-     * <p>
-     * The same as {@link #subtract(BigDecimal, MathContext)}, where the <code>BigDecimal</code> is <code>rhs</code>,
-     * and the context is <code>new MathContext(0, MathContext.PLAIN)</code>.
-     * <p>
-     * The length of the decimal part (the scale) of the result will be the maximum of the scales of the two operands.
-     * 
-     * @param rhs The <code>BigDecimal</code> for the right hand side of the subtraction.
-     * @return A <code>BigDecimal</code> whose value is <code>this-rhs</code>, using fixed point arithmetic.
-     * @stable ICU 2.0
-     */
-
-    public com.ibm.icu.math.BigDecimal subtract(com.ibm.icu.math.BigDecimal rhs) {
-        return this.subtract(rhs, plainMC);
-    }
-
-    /**
-     * Returns a <code>BigDecimal</code> whose value is <code>this-rhs</code>.
-     * <p>
-     * Implements the subtraction (<b><code>-</code></b>) operator (as defined in the decimal documentation, see
-     * {@link BigDecimal class header}), and returns the result as a <code>BigDecimal</code> object.
-     * 
-     * @param rhs The <code>BigDecimal</code> for the right hand side of the subtraction.
-     * @param set The <code>MathContext</code> arithmetic settings.
-     * @return A <code>BigDecimal</code> whose value is <code>this-rhs</code>.
-     * @stable ICU 2.0
-     */
-
-    public com.ibm.icu.math.BigDecimal subtract(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) {
-        com.ibm.icu.math.BigDecimal newrhs;
-        if (set.lostDigits)
-            checkdigits(rhs, set.digits);
-        // [add will recheck .. but would report -rhs]
-        /* carry out the subtraction */
-        // we could fastpath -0, but it is too rare.
-        newrhs = clone(rhs); // safe copy
-        newrhs.ind = (byte) -newrhs.ind; // prepare to subtract
-        return this.add(newrhs, set); // arithmetic
-    }
-
-    /* ---------------------------------------------------------------- */
-    /* Other methods */
-    /* ---------------------------------------------------------------- */
-
-    /**
-     * Converts this <code>BigDecimal</code> to a <code>byte</code>. If the <code>BigDecimal</code> has a non-zero
-     * decimal part or is out of the possible range for a <code>byte</code> (8-bit signed integer) result then an <code>
-     * ArithmeticException</code> is thrown.
-     * 
-     * @return A <code>byte</code> equal in value to <code>this</code>.
-     * @throws ArithmeticException if <code>this</code> has a non-zero decimal part, or will not fit in a <code>byte</code>.
-     * @stable ICU 2.0
-     */
-
-    public byte byteValueExact() {
-        int num;
-        num = this.intValueExact(); // will check decimal part too
-        if ((num > 127) | (num < (-128)))
-            throw new java.lang.ArithmeticException("Conversion overflow:" + " " + this.toString());
-        return (byte) num;
-    }
-
-    /**
-     * Converts this <code>BigDecimal</code> to a <code>double</code>. If the <code>BigDecimal</code> is out of the
-     * possible range for a <code>double</code> (64-bit signed floating point) result then an <code>ArithmeticException
-     * </code> is thrown.
-     * <p>
-     * The double produced is identical to result of expressing the <code>BigDecimal</code> as a <code>String</code> and
-     * then converting it using the <code>Double(String)</code> constructor; this can result in values of <code>
-     * Double.NEGATIVE_INFINITY</code> or <code>Double.POSITIVE_INFINITY</code>.
-     * 
-     * @return A <code>double</code> corresponding to <code>this</code>.
-     * @stable ICU 2.0
-     */
-
-    public double doubleValue() {
-        // We go via a String [as does BigDecimal in JDK 1.2]
-        // Next line could possibly raise NumberFormatException
-        return java.lang.Double.valueOf(this.toString()).doubleValue();
-    }
-
-    /**
-     * Compares this <code>BigDecimal</code> with <code>rhs</code> for equality.
-     * <p>
-     * If the parameter is <code>null</code>, or is not an instance of the BigDecimal type, or is not exactly equal to
-     * the current <code>BigDecimal</code> object, then <i>false</i> is returned. Otherwise, <i>true</i> is returned.
-     * <p>
-     * "Exactly equal", here, means that the <code>String</code> representations of the <code>BigDecimal</code> numbers
-     * are identical (they have the same characters in the same sequence).
-     * <p>
-     * The {@link #compareTo(BigDecimal, MathContext)} method should be used for more general comparisons.
-     * 
-     * @param obj The <code>Object</code> for the right hand side of the comparison.
-     * @return A <code>boolean</code> whose value <i>true</i> if and only if the operands have identical string
-     *         representations.
-     * @throws ClassCastException if <code>rhs</code> cannot be cast to a <code>BigDecimal</code> object.
-     * @stable ICU 2.0
-     * @see #compareTo(BigDecimal)
-     * @see #compareTo(BigDecimal, MathContext)
-     */
-
-    public boolean equals(java.lang.Object obj) {
-        com.ibm.icu.math.BigDecimal rhs;
-        int i = 0;
-        char lca[] = null;
-        char rca[] = null;
-        // We are equal iff toString of both are exactly the same
-        if (obj == null)
-            return false; // not equal
-        if ((!(((obj instanceof com.ibm.icu.math.BigDecimal)))))
-            return false; // not a decimal
-        rhs = (com.ibm.icu.math.BigDecimal) obj; // cast; we know it will work
-        if (this.ind != rhs.ind)
-            return false; // different signs never match
-        if (((this.mant.length == rhs.mant.length) & (this.exp == rhs.exp)) & (this.form == rhs.form))
-
-        { // mantissas say all
-            // here with equal-length byte arrays to compare
-            {
-                int $8 = this.mant.length;
-                i = 0;
-                for (; $8 > 0; $8--, i++) {
-                    if (this.mant[i] != rhs.mant[i])
-                        return false;
-                }
-            }/* i */
-        } else { // need proper layout
-            lca = this.layout(); // layout to character array
-            rca = rhs.layout();
-            if (lca.length != rca.length)
-                return false; // mismatch
-            // here with equal-length character arrays to compare
-            {
-                int $9 = lca.length;
-                i = 0;
-                for (; $9 > 0; $9--, i++) {
-                    if (lca[i] != rca[i])
-                        return false;
-                }
-            }/* i */
-        }
-        return true; // arrays have identical content
-    }
-
-    /**
-     * Converts this <code>BigDecimal</code> to a <code>float</code>. If the <code>BigDecimal</code> is out of the
-     * possible range for a <code>float</code> (32-bit signed floating point) result then an <code>ArithmeticException
-     * </code> is thrown.
-     * <p>
-     * The float produced is identical to result of expressing the <code>BigDecimal</code> as a <code>String</code> and
-     * then converting it using the <code>Float(String)</code> constructor; this can result in values of <code>
-     * Float.NEGATIVE_INFINITY</code> or <code>Float.POSITIVE_INFINITY</code>.
-     * 
-     * @return A <code>float</code> corresponding to <code>this</code>.
-     * @stable ICU 2.0
-     */
-
-    public float floatValue() {
-        return java.lang.Float.valueOf(this.toString()).floatValue();
-    }
-
-    /**
-     * Returns the <code>String</code> representation of this <code>BigDecimal</code>, modified by layout parameters.
-     * <p>
-     * <i>This method is provided as a primitive for use by more sophisticated classes, such as <code>DecimalFormat
-     * </code>, that can apply locale-sensitive editing of the result. The level of formatting that it provides is a
-     * necessary part of the BigDecimal class as it is sensitive to and must follow the calculation and rounding rules
-     * for BigDecimal arithmetic. However, if the function is provided elsewhere, it may be removed from this class.
-     * </i>
-     * <p>
-     * The parameters, for both forms of the <code>format</code> method are all of type <code>int</code>. A value of -1
-     * for any parameter indicates that the default action or value for that parameter should be used.
-     * <p>
-     * The parameters, <code>before</code> and <code>after</code>, specify the number of characters to be used for the
-     * integer part and decimal part of the result respectively. Exponential notation is not used. If either parameter
-     * is -1 (which indicates the default action), the number of characters used will be exactly as many as are needed
-     * for that part.
-     * <p>
-     * <code>before</code> must be a positive number; if it is larger than is needed to contain the integer part, that
-     * part is padded on the left with blanks to the requested length. If <code>before</code> is not large enough to
-     * contain the integer part of the number (including the sign, for negative numbers) an exception is thrown.
-     * <p>
-     * <code>after</code> must be a non-negative number; if it is not the same size as the decimal part of the number,
-     * the number will be rounded (or extended with zeros) to fit. Specifying 0 for <code>after</code> will cause the
-     * number to be rounded to an integer (that is, it will have no decimal part or decimal point). The rounding method
-     * will be the default, <code>MathContext.ROUND_HALF_UP</code>.
-     * <p>
-     * Other rounding methods, and the use of exponential notation, can be selected by using
-     * {@link #format(int,int,int,int,int,int)}. Using the two-parameter form of the method has exactly the same effect
-     * as using the six-parameter form with the final four parameters all being -1.
-     * 
-     * @param before The <code>int</code> specifying the number of places before the decimal point. Use -1 for 'as many as are needed'.
-     * @param after The <code>int</code> specifying the number of places after the decimal point. Use -1 for 'as many as are needed'.
-     * @return A <code>String</code> representing this <code>BigDecimal</code>, laid out according to the specified parameters
-     * @throws ArithmeticException if the number cannot be laid out as requested.
-     * @throws IllegalArgumentException if a parameter is out of range.
-     * @stable ICU 2.0
-     * @see #toString
-     * @see #toCharArray
-     */
-
-    public java.lang.String format(int before, int after) {
-        return format(before, after, -1, -1, com.ibm.icu.math.MathContext.SCIENTIFIC, ROUND_HALF_UP);
-    }
-
-    /**
-     * Returns the <code>String</code> representation of this <code>BigDecimal</code>, modified by layout parameters and
-     * allowing exponential notation.
-     * <p>
-     * <i>This method is provided as a primitive for use by more sophisticated classes, such as <code>DecimalFormat
-     * </code>, that can apply locale-sensitive editing of the result. The level of formatting that it provides is a
-     * necessary part of the BigDecimal class as it is sensitive to and must follow the calculation and rounding rules
-     * for BigDecimal arithmetic. However, if the function is provided elsewhere, it may be removed from this class.
-     * </i>
-     * <p>
-     * The parameters are all of type <code>int</code>. A value of -1 for any parameter indicates that the default
-     * action or value for that parameter should be used.
-     * <p>
-     * The first two parameters (<code>before</code> and <code>after</code>) specify the number of characters to be used
-     * for the integer part and decimal part of the result respectively, as defined for {@link #format(int,int)}. If
-     * either of these is -1 (which indicates the default action), the number of characters used will be exactly as many
-     * as are needed for that part.
-     * <p>
-     * The remaining parameters control the use of exponential notation and rounding. Three (<code>explaces</code>,
-     * <code>exdigits</code>, and <code>exform</code>) control the exponent part of the result. As before, the default
-     * action for any of these parameters may be selected by using the value -1.
-     * <p>
-     * <code>explaces</code> must be a positive number; it sets the number of places (digits after the sign of the
-     * exponent) to be used for any exponent part, the default (when <code>explaces</code> is -1) being to use as many
-     * as are needed. If <code>explaces</code> is not -1, space is always reserved for an exponent; if one is not needed
-     * (for example, if the exponent will be 0) then <code>explaces</code>+2 blanks are appended to the result. <!--
-     * (This preserves vertical alignment of similarly formatted numbers in a monospace font.) --> If <code>explaces
-     * </code> is not -1 and is not large enough to contain the exponent, an exception is thrown.
-     * <p>
-     * <code>exdigits</code> sets the trigger point for use of exponential notation. If, before any rounding, the number
-     * of places needed before the decimal point exceeds <code>exdigits</code>, or if the absolute value of the result
-     * is less than <code>0.000001</code>, then exponential form will be used, provided that <code>exdigits</code> was
-     * specified. When <code>exdigits</code> is -1, exponential notation will never be used. If 0 is specified for
-     * <code>exdigits</code>, exponential notation is always used unless the exponent would be 0.
-     * <p>
-     * <code>exform</code> sets the form for exponential notation (if needed). It may be either
-     * {@link MathContext#SCIENTIFIC} or {@link MathContext#ENGINEERING}. If the latter, engineering, form is requested,
-     * up to three digits (plus sign, if negative) may be needed for the integer part of the result (<code>before</code>
-     * ). Otherwise, only one digit (plus sign, if negative) is needed.
-     * <p>
-     * Finally, the sixth argument, <code>exround</code>, selects the rounding algorithm to be used, and must be one of
-     * the values indicated by a public constant in the {@link MathContext} class whose name starts with <code>ROUND_
-     * </code>. The default (<code>ROUND_HALF_UP</code>) may also be selected by using the value -1, as before.
-     * <p>
-     * The special value <code>MathContext.ROUND_UNNECESSARY</code> may be used to detect whether non-zero digits are
-     * discarded -- if <code>exround</code> has this value than if non-zero digits would be discarded (rounded) during
-     * formatting then an <code>ArithmeticException</code> is thrown.
-     * 
-     * @param before The <code>int</code> specifying the number of places before the decimal point. Use -1 for 'as many as
-     *            are needed'.
-     * @param after The <code>int</code> specifying the number of places after the decimal point. Use -1 for 'as many as
-     *            are needed'.
-     * @param explaces The <code>int</code> specifying the number of places to be used for any exponent. Use -1 for 'as many
-     *            as are needed'.
-     * @param exdigits The <code>int</code> specifying the trigger (digits before the decimal point) which if exceeded causes
-     *            exponential notation to be used. Use 0 to force exponential notation. Use -1 to force plain notation
-     *            (no exponential notation).
-     * @param exformint The <code>int</code> specifying the form of exponential notation to be used (
-     *            {@link MathContext#SCIENTIFIC} or {@link MathContext#ENGINEERING}).
-     * @param exround The <code>int</code> specifying the rounding mode to use. Use -1 for the default,
-     *            {@link MathContext#ROUND_HALF_UP}.
-     * @return A <code>String</code> representing this <code>BigDecimal</code>, laid out according to the specified
-     *         parameters
-     * @throws ArithmeticException if the number cannot be laid out as requested.
-     * @throws IllegalArgumentException if a parameter is out of range.
-     * @see #toString
-     * @see #toCharArray
-     * @stable ICU 2.0
-     */
-
-    public java.lang.String format(int before, int after, int explaces, int exdigits, int exformint, int exround) {
-        com.ibm.icu.math.BigDecimal num;
-        int mag = 0;
-        int thisafter = 0;
-        int lead = 0;
-        byte newmant[] = null;
-        int chop = 0;
-        int need = 0;
-        int oldexp = 0;
-        char a[];
-        int p = 0;
-        char newa[] = null;
-        int i = 0;
-        int places = 0;
-
-        /* Check arguments */
-        if ((before < (-1)) | (before == 0))
-            badarg("format", 1, java.lang.String.valueOf(before));
-        if (after < (-1))
-            badarg("format", 2, java.lang.String.valueOf(after));
-        if ((explaces < (-1)) | (explaces == 0))
-            badarg("format", 3, java.lang.String.valueOf(explaces));
-        if (exdigits < (-1))
-            badarg("format", 4, java.lang.String.valueOf(explaces));
-        {/* select */
-            if (exformint == com.ibm.icu.math.MathContext.SCIENTIFIC) {
-            } else if (exformint == com.ibm.icu.math.MathContext.ENGINEERING) {
-            } else if (exformint == (-1))
-                exformint = com.ibm.icu.math.MathContext.SCIENTIFIC;
-            // note PLAIN isn't allowed
-            else {
-                badarg("format", 5, java.lang.String.valueOf(exformint));
-            }
-        }
-        // checking the rounding mode is done by trying to construct a
-        // MathContext object with that mode; it will fail if bad
-        if (exround != ROUND_HALF_UP) {
-            try { // if non-default...
-                if (exround == (-1))
-                    exround = ROUND_HALF_UP;
-                else
-                    new com.ibm.icu.math.MathContext(9, com.ibm.icu.math.MathContext.SCIENTIFIC, false, exround);
-            } catch (java.lang.IllegalArgumentException $10) {
-                badarg("format", 6, java.lang.String.valueOf(exround));
-            }
-        }
-
-        num = clone(this); // make private copy
-
-        /*
-         * Here: num is BigDecimal to format before is places before point [>0] after is places after point [>=0]
-         * explaces is exponent places [>0] exdigits is exponent digits [>=0] exformint is exponent form [one of two]
-         * exround is rounding mode [one of eight] 'before' through 'exdigits' are -1 if not specified
-         */
-
-        /* determine form */
-        {
-            do {/* select */
-                if (exdigits == (-1))
-                    num.form = (byte) com.ibm.icu.math.MathContext.PLAIN;
-                else if (num.ind == iszero)
-                    num.form = (byte) com.ibm.icu.math.MathContext.PLAIN;
-                else {
-                    // determine whether triggers
-                    mag = num.exp + num.mant.length;
-                    if (mag > exdigits)
-                        num.form = (byte) exformint;
-                    else if (mag < (-5))
-                        num.form = (byte) exformint;
-                    else
-                        num.form = (byte) com.ibm.icu.math.MathContext.PLAIN;
-                }
-            } while (false);
-        }/* setform */
-
-        /*
-         * If 'after' was specified then we may need to adjust the mantissa. This is a little tricky, as we must conform
-         * to the rules of exponential layout if necessary (e.g., we cannot end up with 10.0 if scientific).
-         */
-        if (after >= 0) {
-            setafter: for (;;) {
-                // calculate the current after-length
-                {/* select */
-                    if (num.form == com.ibm.icu.math.MathContext.PLAIN)
-                        thisafter = -num.exp; // has decimal part
-                    else if (num.form == com.ibm.icu.math.MathContext.SCIENTIFIC)
-                        thisafter = num.mant.length - 1;
-                    else { // engineering
-                        lead = (((num.exp + num.mant.length) - 1)) % 3; // exponent to use
-                        if (lead < 0)
-                            lead = 3 + lead; // negative exponent case
-                        lead++; // number of leading digits
-                        if (lead >= num.mant.length)
-                            thisafter = 0;
-                        else
-                            thisafter = num.mant.length - lead;
-                    }
-                }
-                if (thisafter == after)
-                    break setafter; // we're in luck
-                if (thisafter < after) { // need added trailing zeros
-                    // [thisafter can be negative]
-                    newmant = extend(num.mant, (num.mant.length + after) - thisafter);
-                    num.mant = newmant;
-                    num.exp = num.exp - ((after - thisafter)); // adjust exponent
-                    if (num.exp < MinExp)
-                        throw new java.lang.ArithmeticException("Exponent Overflow:" + " " + num.exp);
-                    break setafter;
-                }
-                // We have too many digits after the decimal point; this could
-                // cause a carry, which could change the mantissa...
-                // Watch out for implied leading zeros in PLAIN case
-                chop = thisafter - after; // digits to lop [is >0]
-                if (chop > num.mant.length) { // all digits go, no chance of carry
-                    // carry on with zero
-                    num.mant = ZERO.mant;
-                    num.ind = iszero;
-                    num.exp = 0;
-                    continue setafter; // recheck: we may need trailing zeros
-                }
-                // we have a digit to inspect from existing mantissa
-                // round the number as required
-                need = num.mant.length - chop; // digits to end up with [may be 0]
-                oldexp = num.exp; // save old exponent
-                num.round(need, exround);
-                // if the exponent grew by more than the digits we chopped, then
-                // we must have had a carry, so will need to recheck the layout
-                if ((num.exp - oldexp) == chop)
-                    break setafter; // number did not have carry
-                // mantissa got extended .. so go around and check again
-            }
-        }/* setafter */
-
-        a = num.layout(); // lay out, with exponent if required, etc.
-
-        /* Here we have laid-out number in 'a' */
-        // now apply 'before' and 'explaces' as needed
-        if (before > 0) {
-            // look for '.' or 'E'
-            {
-                int $11 = a.length;
-                p = 0;
-                p: for (; $11 > 0; $11--, p++) {
-                    if (a[p] == '.')
-                        break p;
-                    if (a[p] == 'E')
-                        break p;
-                }
-            }/* p */
-            // p is now offset of '.', 'E', or character after end of array
-            // that is, the current length of before part
-            if (p > before)
-                badarg("format", 1, java.lang.String.valueOf(before)); // won't fit
-            if (p < before) { // need leading blanks
-                newa = new char[(a.length + before) - p];
-                {
-                    int $12 = before - p;
-                    i = 0;
-                    for (; $12 > 0; $12--, i++) {
-                        newa[i] = ' ';
-                    }
-                }/* i */
-                java.lang.System.arraycopy((java.lang.Object) a, 0, (java.lang.Object) newa, i, a.length);
-                a = newa;
-            }
-            // [if p=before then it's just the right length]
-        }
-
-        if (explaces > 0) {
-            // look for 'E' [cannot be at offset 0]
-            {
-                int $13 = a.length - 1;
-                p = a.length - 1;
-                p: for (; $13 > 0; $13--, p--) {
-                    if (a[p] == 'E')
-                        break p;
-                }
-            }/* p */
-            // p is now offset of 'E', or 0
-            if (p == 0) { // no E part; add trailing blanks
-                newa = new char[(a.length + explaces) + 2];
-                java.lang.System.arraycopy((java.lang.Object) a, 0, (java.lang.Object) newa, 0, a.length);
-                {
-                    int $14 = explaces + 2;
-                    i = a.length;
-                    for (; $14 > 0; $14--, i++) {
-                        newa[i] = ' ';
-                    }
-                }/* i */
-                a = newa;
-            } else {/* found E */// may need to insert zeros
-                places = (a.length - p) - 2; // number so far
-                if (places > explaces)
-                    badarg("format", 3, java.lang.String.valueOf(explaces));
-                if (places < explaces) { // need to insert zeros
-                    newa = new char[(a.length + explaces) - places];
-                    java.lang.System.arraycopy((java.lang.Object) a, 0, (java.lang.Object) newa, 0, p + 2); // through E
-                                                                                                            // and sign
-                    {
-                        int $15 = explaces - places;
-                        i = p + 2;
-                        for (; $15 > 0; $15--, i++) {
-                            newa[i] = '0';
-                        }
-                    }/* i */
-                    java.lang.System.arraycopy((java.lang.Object) a, p + 2, (java.lang.Object) newa, i, places); // remainder
-                                                                                                                 // of
-                                                                                                                 // exponent
-                    a = newa;
-                }
-                // [if places=explaces then it's just the right length]
-            }
-        }
-        return new java.lang.String(a);
-    }
-
-    /**
-     * Returns the hashcode for this <code>BigDecimal</code>. This hashcode is suitable for use by the <code>
-     * java.util.Hashtable</code> class.
-     * <p>
-     * Note that two <code>BigDecimal</code> objects are only guaranteed to produce the same hashcode if they are
-     * exactly equal (that is, the <code>String</code> representations of the <code>BigDecimal</code> numbers are
-     * identical -- they have the same characters in the same sequence).
-     * 
-     * @return An <code>int</code> that is the hashcode for <code>this</code>.
-     * @stable ICU 2.0
-     */
-
-    public int hashCode() {
-        // Maybe calculate ourselves, later. If so, note that there can be
-        // more than one internal representation for a given toString() result.
-        return this.toString().hashCode();
-    }
-
-    /**
-     * Converts this <code>BigDecimal</code> to an <code>int</code>. If the <code>BigDecimal</code> has a non-zero
-     * decimal part it is discarded. If the <code>BigDecimal</code> is out of the possible range for an <code>int</code>
-     * (32-bit signed integer) result then only the low-order 32 bits are used. (That is, the number may be
-     * <i>decapitated</i>.) To avoid unexpected errors when these conditions occur, use the {@link #intValueExact}
-     * method.
-     * 
-     * @return An <code>int</code> converted from <code>this</code>, truncated and decapitated if necessary.
-     * @stable ICU 2.0
-     */
-
-    public int intValue() {
-        return toBigInteger().intValue();
-    }
-
-    /**
-     * Converts this <code>BigDecimal</code> to an <code>int</code>. If the <code>BigDecimal</code> has a non-zero
-     * decimal part or is out of the possible range for an <code>int</code> (32-bit signed integer) result then an
-     * <code>ArithmeticException</code> is thrown.
-     * 
-     * @return An <code>int</code> equal in value to <code>this</code>.
-     * @throws ArithmeticException if <code>this</code> has a non-zero decimal part, or will not fit in an <code>int</code>.
-     * @stable ICU 2.0
-     */
-
-    public int intValueExact() {
-        int lodigit;
-        int useexp = 0;
-        int result;
-        int i = 0;
-        int topdig = 0;
-        // This does not use longValueExact() as the latter can be much
-        // slower.
-        // intcheck (from pow) relies on this to check decimal part
-        if (ind == iszero)
-            return 0; // easy, and quite common
-        /* test and drop any trailing decimal part */
-        lodigit = mant.length - 1;
-        if (exp < 0) {
-            lodigit = lodigit + exp; // reduces by -(-exp)
-            /* all decimal places must be 0 */
-            if ((!(allzero(mant, lodigit + 1))))
-                throw new java.lang.ArithmeticException("Decimal part non-zero:" + " " + this.toString());
-            if (lodigit < 0)
-                return 0; // -1<this<1
-            useexp = 0;
-        } else {/* >=0 */
-            if ((exp + lodigit) > 9) // early exit
-                throw new java.lang.ArithmeticException("Conversion overflow:" + " " + this.toString());
-            useexp = exp;
-        }
-        /* convert the mantissa to binary, inline for speed */
-        result = 0;
-        {
-            int $16 = lodigit + useexp;
-            i = 0;
-            for (; i <= $16; i++) {
-                result = result * 10;
-                if (i <= lodigit)
-                    result = result + mant[i];
-            }
-        }/* i */
-
-        /* Now, if the risky length, check for overflow */
-        if ((lodigit + useexp) == 9) {
-            // note we cannot just test for -ve result, as overflow can move a
-            // zero into the top bit [consider 5555555555]
-            topdig = result / 1000000000; // get top digit, preserving sign
-            if (topdig != mant[0]) { // digit must match and be positive
-                // except in the special case ...
-                if (result == java.lang.Integer.MIN_VALUE) // looks like the special
-                    if (ind == isneg) // really was negative
-                        if (mant[0] == 2)
-                            return result; // really had top digit 2
-                throw new java.lang.ArithmeticException("Conversion overflow:" + " " + this.toString());
-            }
-        }
-
-        /* Looks good */
-        if (ind == ispos)
-            return result;
-        return -result;
-    }
-
-    /**
-     * Converts this <code>BigDecimal</code> to a <code>long</code>. If the <code>BigDecimal</code> has a non-zero
-     * decimal part it is discarded. If the <code>BigDecimal</code> is out of the possible range for a <code>long</code>
-     * (64-bit signed integer) result then only the low-order 64 bits are used. (That is, the number may be
-     * <i>decapitated</i>.) To avoid unexpected errors when these conditions occur, use the {@link #longValueExact}
-     * method.
-     * 
-     * @return A <code>long</code> converted from <code>this</code>, truncated and decapitated if necessary.
-     * @stable ICU 2.0
-     */
-
-    public long longValue() {
-        return toBigInteger().longValue();
-    }
-
-    /**
-     * Converts this <code>BigDecimal</code> to a <code>long</code>. If the <code>BigDecimal</code> has a non-zero
-     * decimal part or is out of the possible range for a <code>long</code> (64-bit signed integer) result then an
-     * <code>ArithmeticException</code> is thrown.
-     * 
-     * @return A <code>long</code> equal in value to <code>this</code>.
-     * @throws ArithmeticException if <code>this</code> has a non-zero decimal part, or will not fit in a <code>long</code>.
-     * @stable ICU 2.0
-     */
-
-    public long longValueExact() {
-        int lodigit;
-        int cstart = 0;
-        int useexp = 0;
-        long result;
-        int i = 0;
-        long topdig = 0;
-        // Identical to intValueExact except for result=long, and exp>=20 test
-        if (ind == 0)
-            return 0; // easy, and quite common
-        lodigit = mant.length - 1; // last included digit
-        if (exp < 0) {
-            lodigit = lodigit + exp; // -(-exp)
-            /* all decimal places must be 0 */
-            if (lodigit < 0)
-                cstart = 0;
-            else
-                cstart = lodigit + 1;
-            if ((!(allzero(mant, cstart))))
-                throw new java.lang.ArithmeticException("Decimal part non-zero:" + " " + this.toString());
-            if (lodigit < 0)
-                return 0; // -1<this<1
-            useexp = 0;
-        } else {/* >=0 */
-            if ((exp + mant.length) > 18) // early exit
-                throw new java.lang.ArithmeticException("Conversion overflow:" + " " + this.toString());
-            useexp = exp;
-        }
-
-        /* convert the mantissa to binary, inline for speed */
-        // note that we could safely use the 'test for wrap to negative'
-        // algorithm here, but instead we parallel the intValueExact
-        // algorithm for ease of checking and maintenance.
-        result = (long) 0;
-        {
-            int $17 = lodigit + useexp;
-            i = 0;
-            for (; i <= $17; i++) {
-                result = result * 10;
-                if (i <= lodigit)
-                    result = result + mant[i];
-            }
-        }/* i */
-
-        /* Now, if the risky length, check for overflow */
-        if ((lodigit + useexp) == 18) {
-            topdig = result / 1000000000000000000L; // get top digit, preserving sign
-            if (topdig != mant[0]) { // digit must match and be positive
-                // except in the special case ...
-                if (result == java.lang.Long.MIN_VALUE) // looks like the special
-                    if (ind == isneg) // really was negative
-                        if (mant[0] == 9)
-                            return result; // really had top digit 9
-                throw new java.lang.ArithmeticException("Conversion overflow:" + " " + this.toString());
-            }
-        }
-
-        /* Looks good */
-        if (ind == ispos)
-            return result;
-        return -result;
-    }
-
-    /**
-     * Returns a plain <code>BigDecimal</code> whose decimal point has been moved to the left by a specified number of
-     * positions. The parameter, <code>n</code>, specifies the number of positions to move the decimal point. That is,
-     * if <code>n</code> is 0 or positive, the number returned is given by:
-     * <p>
-     * <code> this.multiply(TEN.pow(new BigDecimal(-n))) </code>
-     * <p>
-     * <code>n</code> may be negative, in which case the method returns the same result as <code>movePointRight(-n)
-     * </code>.
-     * 
-     * @param n The <code>int</code> specifying the number of places to move the decimal point leftwards.
-     * @return A <code>BigDecimal</code> derived from <code>this</code>, with the decimal point moved <code>n</code>
-     *         places to the left.
-     * @stable ICU 2.0
-     */
-
-    public com.ibm.icu.math.BigDecimal movePointLeft(int n) {
-        com.ibm.icu.math.BigDecimal res;
-        // very little point in optimizing for shift of 0
-        res = clone(this);
-        res.exp = res.exp - n;
-        return res.finish(plainMC, false); // finish sets form and checks exponent
-    }
-
-    /**
-     * Returns a plain <code>BigDecimal</code> whose decimal point has been moved to the right by a specified number of
-     * positions. The parameter, <code>n</code>, specifies the number of positions to move the decimal point. That is,
-     * if <code>n</code> is 0 or positive, the number returned is given by:
-     * <p>
-     * <code> this.multiply(TEN.pow(new BigDecimal(n))) </code>
-     * <p>
-     * <code>n</code> may be negative, in which case the method returns the same result as <code>movePointLeft(-n)
-     * </code>.
-     * 
-     * @param n The <code>int</code> specifying the number of places to move the decimal point rightwards.
-     * @return A <code>BigDecimal</code> derived from <code>this</code>, with the decimal point moved <code>n</code>
-     *         places to the right.
-     * @stable ICU 2.0
-     */
-
-    public com.ibm.icu.math.BigDecimal movePointRight(int n) {
-        com.ibm.icu.math.BigDecimal res;
-        res = clone(this);
-        res.exp = res.exp + n;
-        return res.finish(plainMC, false);
-    }
-
-    /**
-     * Returns the scale of this <code>BigDecimal</code>. Returns a non-negative <code>int</code> which is the scale of
-     * the number. The scale is the number of digits in the decimal part of the number if the number were formatted
-     * without exponential notation.
-     * 
-     * @return An <code>int</code> whose value is the scale of this <code>BigDecimal</code>.
-     * @stable ICU 2.0
-     */
-
-    public int scale() {
-        if (exp >= 0)
-            return 0; // scale can never be negative
-        return -exp;
-    }
-
-    /**
-     * Returns a plain <code>BigDecimal</code> with a given scale.
-     * <p>
-     * If the given scale (which must be zero or positive) is the same as or greater than the length of the decimal part
-     * (the scale) of this <code>BigDecimal</code> then trailing zeros will be added to the decimal part as necessary.
-     * <p>
-     * If the given scale is less than the length of the decimal part (the scale) of this <code>BigDecimal</code> then
-     * trailing digits will be removed, and in this case an <code>ArithmeticException</code> is thrown if any discarded
-     * digits are non-zero.
-     * <p>
-     * The same as {@link #setScale(int, int)}, where the first parameter is the scale, and the second is <code>
-     * MathContext.ROUND_UNNECESSARY</code>.
-     * 
-     * @param scale The <code>int</code> specifying the scale of the resulting <code>BigDecimal</code>.
-     * @return A plain <code>BigDecimal</code> with the given scale.
-     * @throws ArithmeticException if <code>scale</code> is negative.
-     * @throws ArithmeticException if reducing scale would discard non-zero digits.
-     * @stable ICU 2.0
-     */
-
-    public com.ibm.icu.math.BigDecimal setScale(int scale) {
-        return setScale(scale, ROUND_UNNECESSARY);
-    }
-
-    /**
-     * Returns a plain <code>BigDecimal</code> with a given scale.
-     * <p>
-     * If the given scale (which must be zero or positive) is the same as or greater than the length of the decimal part
-     * (the scale) of this <code>BigDecimal</code> then trailing zeros will be added to the decimal part as necessary.
-     * <p>
-     * If the given scale is less than the length of the decimal part (the scale) of this <code>BigDecimal</code> then
-     * trailing digits will be removed, and the rounding mode given by the second parameter is used to determine if the
-     * remaining digits are affected by a carry. In this case, an <code>IllegalArgumentException</code> is thrown if
-     * <code>round</code> is not a valid rounding mode.
-     * <p>
-     * If <code>round</code> is <code>MathContext.ROUND_UNNECESSARY</code>, an <code>ArithmeticException</code> is
-     * thrown if any discarded digits are non-zero.
-     * 
-     * @param scale The <code>int</code> specifying the scale of the resulting <code>BigDecimal</code>.
-     * @param round The <code>int</code> rounding mode to be used for the division (see the {@link MathContext} class).
-     * @return A plain <code>BigDecimal</code> with the given scale.
-     * @throws IllegalArgumentException if <code>round</code> is not a valid rounding mode.
-     * @throws ArithmeticException if <code>scale</code> is negative.
-     * @throws ArithmeticException if <code>round</code> is <code>MathContext.ROUND_UNNECESSARY</code>, and reducing scale would discard
-     *             non-zero digits.
-     * @stable ICU 2.0
-     */
-
-    public com.ibm.icu.math.BigDecimal setScale(int scale, int round) {
-        int ourscale;
-        com.ibm.icu.math.BigDecimal res;
-        int padding = 0;
-        int newlen = 0;
-        // at present this naughtily only checks the round value if it is
-        // needed (used), for speed
-        ourscale = this.scale();
-        if (ourscale == scale) // already correct scale
-            if (this.form == com.ibm.icu.math.MathContext.PLAIN) // .. and form
-                return this;
-        res = clone(this); // need copy
-        if (ourscale <= scale) { // simply zero-padding/changing form
-            // if ourscale is 0 we may have lots of 0s to add
-            if (ourscale == 0)
-                padding = res.exp + scale;
-            else
-                padding = scale - ourscale;
-            res.mant = extend(res.mant, res.mant.length + padding);
-            res.exp = -scale; // as requested
-        } else {/* ourscale>scale: shortening, probably */
-            if (scale < 0)
-                throw new java.lang.ArithmeticException("Negative scale:" + " " + scale);
-            // [round() will raise exception if invalid round]
-            newlen = res.mant.length - ((ourscale - scale)); // [<=0 is OK]
-            res = res.round(newlen, round); // round to required length
-            // This could have shifted left if round (say) 0.9->1[.0]
-            // Repair if so by adding a zero and reducing exponent
-            if (res.exp != -scale) {
-                res.mant = extend(res.mant, res.mant.length + 1);
-                res.exp = res.exp - 1;
-            }
-        }
-        res.form = (byte) com.ibm.icu.math.MathContext.PLAIN; // by definition
-        return res;
-    }
-
-    /**
-     * Converts this <code>BigDecimal</code> to a <code>short</code>. If the <code>BigDecimal</code> has a non-zero
-     * decimal part or is out of the possible range for a <code>short</code> (16-bit signed integer) result then an
-     * <code>ArithmeticException</code> is thrown.
-     * 
-     * @return A <code>short</code> equal in value to <code>this</code>.
-     * @throws ArithmeticException if <code>this</code> has a non-zero decimal part, or will not fit in a <code>short</code>.
-     * @stable ICU 2.0
-     */
-
-    public short shortValueExact() {
-        int num;
-        num = this.intValueExact(); // will check decimal part too
-        if ((num > 32767) | (num < (-32768)))
-            throw new java.lang.ArithmeticException("Conversion overflow:" + " " + this.toString());
-        return (short) num;
-    }
-
-    /**
-     * Returns the sign of this <code>BigDecimal</code>, as an <code>int</code>. This returns the <i>signum</i> function
-     * value that represents the sign of this <code>BigDecimal</code>. That is, -1 if the <code>BigDecimal</code> is
-     * negative, 0 if it is numerically equal to zero, or 1 if it is positive.
-     * 
-     * @return An <code>int</code> which is -1 if the <code>BigDecimal</code> is negative, 0 if it is numerically equal
-     *         to zero, or 1 if it is positive.
-     * @stable ICU 2.0
-     */
-
-    public int signum() {
-        return (int) this.ind; // [note this assumes values for ind.]
-    }
-
-    /**
-     * Converts this <code>BigDecimal</code> to a <code>java.math.BigDecimal</code>.
-     * <p>
-     * This is an exact conversion; the result is the same as if the <code>BigDecimal</code> were formatted as a plain
-     * number without any rounding or exponent and then the <code>java.math.BigDecimal(java.lang.String)</code>
-     * constructor were used to construct the result.
-     * <p>
-     * <i>(Note: this method is provided only in the <code>com.ibm.icu.math</code> version of the BigDecimal class. It
-     * would not be present in a <code>java.math</code> version.)</i>
-     * 
-     * @return The <code>java.math.BigDecimal</code> equal in value to this <code>BigDecimal</code>.
-     * @stable ICU 2.0
-     */
-
-    public java.math.BigDecimal toBigDecimal() {
-        return new java.math.BigDecimal(this.unscaledValue(), this.scale());
-    }
-
-    /**
-     * Converts this <code>BigDecimal</code> to a <code>java.math.BigInteger</code>.
-     * <p>
-     * Any decimal part is truncated (discarded). If an exception is desired should the decimal part be non-zero, use
-     * {@link #toBigIntegerExact()}.
-     * 
-     * @return The <code>java.math.BigInteger</code> equal in value to the integer part of this <code>BigDecimal</code>.
-     * @stable ICU 2.0
-     */
-
-    public java.math.BigInteger toBigInteger() {
-        com.ibm.icu.math.BigDecimal res = null;
-        int newlen = 0;
-        byte newmant[] = null;
-        {/* select */
-            if ((exp >= 0) & (form == com.ibm.icu.math.MathContext.PLAIN))
-                res = this; // can layout simply
-            else if (exp >= 0) {
-                res = clone(this); // safe copy
-                res.form = (byte) com.ibm.icu.math.MathContext.PLAIN; // .. and request PLAIN
-            } else {
-                { // exp<0; scale to be truncated
-                    // we could use divideInteger, but we may as well be quicker
-                    if (-this.exp >= this.mant.length)
-                        res = ZERO; // all blows away
-                    else {
-                        res = clone(this); // safe copy
-                        newlen = res.mant.length + res.exp;
-                        newmant = new byte[newlen]; // [shorter]
-                        java.lang.System.arraycopy((java.lang.Object) res.mant, 0, (java.lang.Object) newmant, 0,
-                                newlen);
-                        res.mant = newmant;
-                        res.form = (byte) com.ibm.icu.math.MathContext.PLAIN;
-                        res.exp = 0;
-                    }
-                }
-            }
-        }
-        return new BigInteger(new java.lang.String(res.layout()));
-    }
-
-    /**
-     * Converts this <code>BigDecimal</code> to a <code>java.math.BigInteger</code>.
-     * <p>
-     * An exception is thrown if the decimal part (if any) is non-zero.
-     * 
-     * @return The <code>java.math.BigInteger</code> equal in value to the integer part of this <code>BigDecimal</code>.
-     * @throws ArithmeticException if <code>this</code> has a non-zero decimal part.
-     * @stable ICU 2.0
-     */
-
-    public java.math.BigInteger toBigIntegerExact() {
-        /* test any trailing decimal part */
-        if (exp < 0) { // possible decimal part
-            /* all decimal places must be 0; note exp<0 */
-            if ((!(allzero(mant, mant.length + exp))))
-                throw new java.lang.ArithmeticException("Decimal part non-zero:" + " " + this.toString());
-        }
-        return toBigInteger();
-    }
-
-    /**
-     * Returns the <code>BigDecimal</code> as a character array. The result of this method is the same as using the
-     * sequence <code>toString().toCharArray()</code>, but avoids creating the intermediate <code>String</code> and
-     * <code>char[]</code> objects.
-     * 
-     * @return The <code>char[]</code> array corresponding to this <code>BigDecimal</code>.
-     * @stable ICU 2.0
-     */
-
-    public char[] toCharArray() {
-        return layout();
-    }
-
-    /**
-     * Returns the <code>BigDecimal</code> as a <code>String</code>. This returns a <code>String</code> that exactly
-     * represents this <code>BigDecimal</code>, as defined in the decimal documentation (see {@link BigDecimal class
-     * header}).
-     * <p>
-     * By definition, using the {@link #BigDecimal(String)} constructor on the result <code>String</code> will create a
-     * <code>BigDecimal</code> that is exactly equal to the original <code>BigDecimal</code>.
-     * 
-     * @return The <code>String</code> exactly corresponding to this <code>BigDecimal</code>.
-     * @see #format(int, int)
-     * @see #format(int, int, int, int, int, int)
-     * @see #toCharArray()
-     * @stable ICU 2.0
-     */
-
-    public java.lang.String toString() {
-        return new java.lang.String(layout());
-    }
-
-    /**
-     * Returns the number as a <code>BigInteger</code> after removing the scale. That is, the number is expressed as a
-     * plain number, any decimal point is then removed (retaining the digits of any decimal part), and the result is
-     * then converted to a <code>BigInteger</code>.
-     * 
-     * @return The <code>java.math.BigInteger</code> equal in value to this <code>BigDecimal</code> multiplied by ten to
-     *         the power of <code>this.scale()</code>.
-     * @stable ICU 2.0
-     */
-
-    public java.math.BigInteger unscaledValue() {
-        com.ibm.icu.math.BigDecimal res = null;
-        if (exp >= 0)
-            res = this;
-        else {
-            res = clone(this); // safe copy
-            res.exp = 0; // drop scale
-        }
-        return res.toBigInteger();
-    }
-
-    /**
-     * Translates a <code>double</code> to a <code>BigDecimal</code>.
-     * <p>
-     * Returns a <code>BigDecimal</code> which is the decimal representation of the 64-bit signed binary floating point
-     * parameter. If the parameter is infinite, or is not a number (NaN), a <code>NumberFormatException</code> is
-     * thrown.
-     * <p>
-     * The number is constructed as though <code>num</code> had been converted to a <code>String</code> using the <code>
-     * Double.toString()</code> method and the {@link #BigDecimal(java.lang.String)} constructor had then been used.
-     * This is typically not an exact conversion.
-     * 
-     * @param dub The <code>double</code> to be translated.
-     * @return The <code>BigDecimal</code> equal in value to <code>dub</code>.
-     * @throws NumberFormatException if the parameter is infinite or not a number.
-     * @stable ICU 2.0
-     */
-
-    public static com.ibm.icu.math.BigDecimal valueOf(double dub) {
-        // Reminder: a zero double returns '0.0', so we cannot fastpath to
-        // use the constant ZERO. This might be important enough to justify
-        // a factory approach, a cache, or a few private constants, later.
-        return new com.ibm.icu.math.BigDecimal((new java.lang.Double(dub)).toString());
-    }
-
-    /**
-     * Translates a <code>long</code> to a <code>BigDecimal</code>. That is, returns a plain <code>BigDecimal</code>
-     * whose value is equal to the given <code>long</code>.
-     * 
-     * @param lint The <code>long</code> to be translated.
-     * @return The <code>BigDecimal</code> equal in value to <code>lint</code>.
-     * @stable ICU 2.0
-     */
-
-    public static com.ibm.icu.math.BigDecimal valueOf(long lint) {
-        return valueOf(lint, 0);
-    }
-
-    /**
-     * Translates a <code>long</code> to a <code>BigDecimal</code> with a given scale. That is, returns a plain <code>
-     * BigDecimal</code> whose unscaled value is equal to the given <code>long</code>, adjusted by the second parameter,
-     * <code>scale</code>.
-     * <p>
-     * The result is given by:
-     * <p>
-     * <code> (new BigDecimal(lint)).divide(TEN.pow(new BigDecimal(scale))) </code>
-     * <p>
-     * A <code>NumberFormatException</code> is thrown if <code>scale</code> is negative.
-     * 
-     * @param lint The <code>long</code> to be translated.
-     * @param scale The <code>int</code> scale to be applied.
-     * @return The <code>BigDecimal</code> equal in value to <code>lint</code>.
-     * @throws NumberFormatException if the scale is negative.
-     * @stable ICU 2.0
-     */
-
-    public static com.ibm.icu.math.BigDecimal valueOf(long lint, int scale) {
-        com.ibm.icu.math.BigDecimal res = null;
-        {/* select */
-            if (lint == 0)
-                res = ZERO;
-            else if (lint == 1)
-                res = ONE;
-            else if (lint == 10)
-                res = TEN;
-            else {
-                res = new com.ibm.icu.math.BigDecimal(lint);
-            }
-        }
-        if (scale == 0)
-            return res;
-        if (scale < 0)
-            throw new java.lang.NumberFormatException("Negative scale:" + " " + scale);
-        res = clone(res); // safe copy [do not mutate]
-        res.exp = -scale; // exponent is -scale
-        return res;
-    }
-
-    /* ---------------------------------------------------------------- */
-    /* Private methods */
-    /* ---------------------------------------------------------------- */
-
-    /*
-     * <sgml> Return char array value of a BigDecimal (conversion from BigDecimal to laid-out canonical char array).
-     * <p>The mantissa will either already have been rounded (following an operation) or will be of length appropriate
-     * (in the case of construction from an int, for example). <p>We must not alter the mantissa, here. <p>'form'
-     * describes whether we are to use exponential notation (and if so, which), or if we are to lay out as a plain/pure
-     * numeric. </sgml>
-     */
-
-    private char[] layout() {
-        char cmant[];
-        int i = 0;
-        StringBuilder sb = null;
-        int euse = 0;
-        int sig = 0;
-        char csign = 0;
-        char rec[] = null;
-        int needsign;
-        int mag;
-        int len = 0;
-        cmant = new char[mant.length]; // copy byte[] to a char[]
-        {
-            int $18 = mant.length;
-            i = 0;
-            for (; $18 > 0; $18--, i++) {
-                cmant[i] = (char) (mant[i] + ((int) ('0')));
-            }
-        }/* i */
-
-        if (form != com.ibm.icu.math.MathContext.PLAIN) {/* exponential notation needed */
-            sb = new StringBuilder(cmant.length + 15); // -x.xxxE+999999999
-            if (ind == isneg)
-                sb.append('-');
-            euse = (exp + cmant.length) - 1; // exponent to use
-            /* setup sig=significant digits and copy to result */
-            if (form == com.ibm.icu.math.MathContext.SCIENTIFIC) { // [default]
-                sb.append(cmant[0]); // significant character
-                if (cmant.length > 1) // have decimal part
-                    sb.append('.').append(cmant, 1, cmant.length - 1);
-            } else {
-                do {
-                    sig = euse % 3; // common
-                    if (sig < 0)
-                        sig = 3 + sig; // negative exponent
-                    euse = euse - sig;
-                    sig++;
-                    if (sig >= cmant.length) { // zero padding may be needed
-                        sb.append(cmant, 0, cmant.length);
-                        {
-                            int $19 = sig - cmant.length;
-                            for (; $19 > 0; $19--) {
-                                sb.append('0');
-                            }
-                        }
-                    } else { // decimal point needed
-                        sb.append(cmant, 0, sig).append('.').append(cmant, sig, cmant.length - sig);
-                    }
-                } while (false);
-            }/* engineering */
-            if (euse != 0) {
-                if (euse < 0) {
-                    csign = '-';
-                    euse = -euse;
-                } else
-                    csign = '+';
-                sb.append('E').append(csign).append(euse);
-            }
-            rec = new char[sb.length()];
-            int srcEnd = sb.length();
-            if (0 != srcEnd) {
-                sb.getChars(0, srcEnd, rec, 0);
-            }
-            return rec;
-        }
-
-        /* Here for non-exponential (plain) notation */
-        if (exp == 0) {/* easy */
-            if (ind >= 0)
-                return cmant; // non-negative integer
-            rec = new char[cmant.length + 1];
-            rec[0] = '-';
-            java.lang.System.arraycopy((java.lang.Object) cmant, 0, (java.lang.Object) rec, 1, cmant.length);
-            return rec;
-        }
-
-        /* Need a '.' and/or some zeros */
-        needsign = (ind == isneg) ? 1 : 0; // space for sign? 0 or 1
-
-        /*
-         * MAG is the position of the point in the mantissa (index of the character it follows)
-         */
-        mag = exp + cmant.length;
-
-        if (mag < 1) {/* 0.00xxxx form */
-            len = (needsign + 2) - exp; // needsign+2+(-mag)+cmant.length
-            rec = new char[len];
-            if (needsign != 0)
-                rec[0] = '-';
-            rec[needsign] = '0';
-            rec[needsign + 1] = '.';
-            {
-                int $20 = -mag;
-                i = needsign + 2;
-                for (; $20 > 0; $20--, i++) { // maybe none
-                    rec[i] = '0';
-                }
-            }/* i */
-            java.lang.System.arraycopy((java.lang.Object) cmant, 0, (java.lang.Object) rec, (needsign + 2) - mag,
-                    cmant.length);
-            return rec;
-        }
-
-        if (mag > cmant.length) {/* xxxx0000 form */
-            len = needsign + mag;
-            rec = new char[len];
-            if (needsign != 0)
-                rec[0] = '-';
-            java.lang.System.arraycopy((java.lang.Object) cmant, 0, (java.lang.Object) rec, needsign, cmant.length);
-            {
-                int $21 = mag - cmant.length;
-                i = needsign + cmant.length;
-                for (; $21 > 0; $21--, i++) { // never 0
-                    rec[i] = '0';
-                }
-            }/* i */
-            return rec;
-        }
-
-        /* decimal point is in the middle of the mantissa */
-        len = (needsign + 1) + cmant.length;
-        rec = new char[len];
-        if (needsign != 0)
-            rec[0] = '-';
-        java.lang.System.arraycopy((java.lang.Object) cmant, 0, (java.lang.Object) rec, needsign, mag);
-        rec[needsign + mag] = '.';
-        java.lang.System.arraycopy((java.lang.Object) cmant, mag, (java.lang.Object) rec, (needsign + mag) + 1,
-                cmant.length - mag);
-        return rec;
-    }
-
-    /*
-     * <sgml> Checks a BigDecimal argument to ensure it's a true integer in a given range. <p>If OK, returns it as an
-     * int. </sgml>
-     */
-    // [currently only used by pow]
-    private int intcheck(int min, int max) {
-        int i;
-        i = this.intValueExact(); // [checks for non-0 decimal part]
-        // Use same message as though intValueExact failed due to size
-        if ((i < min) | (i > max))
-            throw new java.lang.ArithmeticException("Conversion overflow:" + " " + i);
-        return i;
-    }
-
-    /* <sgml> Carry out division operations. </sgml> */
-    /*
-     * Arg1 is operation code: D=divide, I=integer divide, R=remainder Arg2 is the rhs. Arg3 is the context. Arg4 is
-     * explicit scale iff code='D' or 'I' (-1 if none).
-     * 
-     * Underlying algorithm (complications for Remainder function and scaled division are omitted for clarity):
-     * 
-     * Test for x/0 and then 0/x Exp =Exp1 - Exp2 Exp =Exp +len(var1) -len(var2) Sign=Sign1 Sign2 Pad accumulator (Var1)
-     * to double-length with 0's (pad1) Pad Var2 to same length as Var1 B2B=1st two digits of var2, +1 to allow for
-     * roundup have=0 Do until (have=digits+1 OR residue=0) if exp<0 then if integer divide/residue then leave
-     * this_digit=0 Do forever compare numbers if <0 then leave inner_loop if =0 then (- quick exit without subtract -)
-     * do this_digit=this_digit+1; output this_digit leave outer_loop; end Compare lengths of numbers (mantissae): If
-     * same then CA=first_digit_of_Var1 else CA=first_two_digits_of_Var1 mult=ca10/b2b -- Good and safe guess at divisor
-     * if mult=0 then mult=1 this_digit=this_digit+mult subtract end inner_loop if have\=0 | this_digit\=0 then do
-     * output this_digit have=have+1; end var2=var2/10 exp=exp-1 end outer_loop exp=exp+1 -- set the proper exponent if
-     * have=0 then generate answer=0 Return to FINISHED Result defined by MATHV1
-     * 
-     * For extended commentary, see DMSRCN.
-     */
-
-    private com.ibm.icu.math.BigDecimal dodivide(char code, com.ibm.icu.math.BigDecimal rhs,
-            com.ibm.icu.math.MathContext set, int scale) {
-        com.ibm.icu.math.BigDecimal lhs;
-        int reqdig;
-        int newexp;
-        com.ibm.icu.math.BigDecimal res;
-        int newlen;
-        byte var1[];
-        int var1len;
-        byte var2[];
-        int var2len;
-        int b2b;
-        int have;
-        int thisdigit = 0;
-        int i = 0;
-        byte v2 = 0;
-        int ba = 0;
-        int mult = 0;
-        int start = 0;
-        int padding = 0;
-        int d = 0;
-        byte newvar1[] = null;
-        byte lasthave = 0;
-        int actdig = 0;
-        byte newmant[] = null;
-
-        if (set.lostDigits)
-            checkdigits(rhs, set.digits);
-        lhs = this; // name for clarity
-
-        // [note we must have checked lostDigits before the following checks]
-        if (rhs.ind == 0)
-            throw new java.lang.ArithmeticException("Divide by 0"); // includes 0/0
-        if (lhs.ind == 0) { // 0/x => 0 [possibly with .0s]
-            if (set.form != com.ibm.icu.math.MathContext.PLAIN)
-                return ZERO;
-            if (scale == (-1))
-                return lhs;
-            return lhs.setScale(scale);
-        }
-
-        /* Prepare numbers according to BigDecimal rules */
-        reqdig = set.digits; // local copy (heavily used)
-        if (reqdig > 0) {
-            if (lhs.mant.length > reqdig)
-                lhs = clone(lhs).round(set);
-            if (rhs.mant.length > reqdig)
-                rhs = clone(rhs).round(set);
-        } else {/* scaled divide */
-            if (scale == (-1))
-                scale = lhs.scale();
-            // set reqdig to be at least large enough for the computation
-            reqdig = lhs.mant.length; // base length
-            // next line handles both positive lhs.exp and also scale mismatch
-            if (scale != -lhs.exp)
-                reqdig = (reqdig + scale) + lhs.exp;
-            reqdig = (reqdig - ((rhs.mant.length - 1))) - rhs.exp; // reduce by RHS effect
-            if (reqdig < lhs.mant.length)
-                reqdig = lhs.mant.length; // clamp
-            if (reqdig < rhs.mant.length)
-                reqdig = rhs.mant.length; // ..
-        }
-
-        /* precalculate exponent */
-        newexp = ((lhs.exp - rhs.exp) + lhs.mant.length) - rhs.mant.length;
-        /* If new exponent -ve, then some quick exits are possible */
-        if (newexp < 0)
-            if (code != 'D') {
-                if (code == 'I')
-                    return ZERO; // easy - no integer part
-                /* Must be 'R'; remainder is [finished clone of] input value */
-                return clone(lhs).finish(set, false);
-            }
-
-        /* We need slow division */
-        res = new com.ibm.icu.math.BigDecimal(); // where we'll build result
-        res.ind = (byte) (lhs.ind * rhs.ind); // final sign (for D/I)
-        res.exp = newexp; // initial exponent (for D/I)
-        res.mant = new byte[reqdig + 1]; // where build the result
-
-        /* Now [virtually pad the mantissae with trailing zeros */
-        // Also copy the LHS, which will be our working array
-        newlen = (reqdig + reqdig) + 1;
-        var1 = extend(lhs.mant, newlen); // always makes longer, so new safe array
-        var1len = newlen; // [remaining digits are 0]
-
-        var2 = rhs.mant;
-        var2len = newlen;
-
-        /* Calculate first two digits of rhs (var2), +1 for later estimations */
-        b2b = (var2[0] * 10) + 1;
-        if (var2.length > 1)
-            b2b = b2b + var2[1];
-
-        /* start the long-division loops */
-        have = 0;
-        {
-            outer: for (;;) {
-                thisdigit = 0;
-                /* find the next digit */
-                {
-                    inner: for (;;) {
-                        if (var1len < var2len)
-                            break inner; // V1 too low
-                        if (var1len == var2len) { // compare needed
-                            {
-                                compare: do { // comparison
-                                    {
-                                        int $22 = var1len;
-                                        i = 0;
-                                        for (; $22 > 0; $22--, i++) {
-                                            // var1len is always <= var1.length
-                                            if (i < var2.length)
-                                                v2 = var2[i];
-                                            else
-                                                v2 = (byte) 0;
-                                            if (var1[i] < v2)
-                                                break inner; // V1 too low
-                                            if (var1[i] > v2)
-                                                break compare; // OK to subtract
-                                        }
-                                    }/* i */
-                                    /*
-                                     * reach here if lhs and rhs are identical; subtraction will increase digit by one,
-                                     * and the residue will be 0 so we are done; leave the loop with residue set to 0
-                                     * (in case code is 'R' or ROUND_UNNECESSARY or a ROUND_HALF_xxxx is being checked)
-                                     */
-                                    thisdigit++;
-                                    res.mant[have] = (byte) thisdigit;
-                                    have++;
-                                    var1[0] = (byte) 0; // residue to 0 [this is all we'll test]
-                                    // var1len=1 -- [optimized out]
-                                    break outer;
-                                } while (false);
-                            }/* compare */
-                            /* prepare for subtraction. Estimate BA (lengths the same) */
-                            ba = (int) var1[0]; // use only first digit
-                        } // lengths the same
-                        else {/* lhs longer than rhs */
-                            /* use first two digits for estimate */
-                            ba = var1[0] * 10;
-                            if (var1len > 1)
-                                ba = ba + var1[1];
-                        }
-                        /* subtraction needed; V1>=V2 */
-                        mult = (ba * 10) / b2b;
-                        if (mult == 0)
-                            mult = 1;
-                        thisdigit = thisdigit + mult;
-                        // subtract; var1 reusable
-                        var1 = byteaddsub(var1, var1len, var2, var2len, -mult, true);
-                        if (var1[0] != 0)
-                            continue inner; // maybe another subtract needed
-                        /*
-                         * V1 now probably has leading zeros, remove leading 0's and try again. (It could be longer than
-                         * V2)
-                         */
-                        {
-                            int $23 = var1len - 2;
-                            start = 0;
-                            start: for (; start <= $23; start++) {
-                                if (var1[start] != 0)
-                                    break start;
-                                var1len--;
-                            }
-                        }/* start */
-                        if (start == 0)
-                            continue inner;
-                        // shift left
-                        java.lang.System.arraycopy((java.lang.Object) var1, start, (java.lang.Object) var1, 0, var1len);
-                    }
-                }/* inner */
-
-                /* We have the next digit */
-                if ((have != 0) | (thisdigit != 0)) { // put the digit we got
-                    res.mant[have] = (byte) thisdigit;
-                    have++;
-                    if (have == (reqdig + 1))
-                        break outer; // we have all we need
-                    if (var1[0] == 0)
-                        break outer; // residue now 0
-                }
-                /* can leave now if a scaled divide and exponent is small enough */
-                if (scale >= 0)
-                    if (-res.exp > scale)
-                        break outer;
-                /* can leave now if not Divide and no integer part left */
-                if (code != 'D')
-                    if (res.exp <= 0)
-                        break outer;
-                res.exp = res.exp - 1; // reduce the exponent
-                /*
-                 * to get here, V1 is less than V2, so divide V2 by 10 and go for the next digit
-                 */
-                var2len--;
-            }
-        }/* outer */
-
-        /* here when we have finished dividing, for some reason */
-        // have is the number of digits we collected in res.mant
-        if (have == 0)
-            have = 1; // res.mant[0] is 0; we always want a digit
-
-        if ((code == 'I') | (code == 'R')) {/* check for integer overflow needed */
-            if ((have + res.exp) > reqdig)
-                throw new java.lang.ArithmeticException("Integer overflow");
-
-            if (code == 'R') {
-                do {
-                    /* We were doing Remainder -- return the residue */
-                    if (res.mant[0] == 0) // no integer part was found
-                        return clone(lhs).finish(set, false); // .. so return lhs, canonical
-                    if (var1[0] == 0)
-                        return ZERO; // simple 0 residue
-                    res.ind = lhs.ind; // sign is always as LHS
-                    /*
-                     * Calculate the exponent by subtracting the number of padding zeros we added and adding the
-                     * original exponent
-                     */
-                    padding = ((reqdig + reqdig) + 1) - lhs.mant.length;
-                    res.exp = (res.exp - padding) + lhs.exp;
-
-                    /*
-                     * strip insignificant padding zeros from residue, and create/copy the resulting mantissa if need be
-                     */
-                    d = var1len;
-                    {
-                        i = d - 1;
-                        i: for (; i >= 1; i--) {
-                            if (!((res.exp < lhs.exp) & (res.exp < rhs.exp)))
-                                break;
-                            if (var1[i] != 0)
-                                break i;
-                            d--;
-                            res.exp = res.exp + 1;
-                        }
-                    }/* i */
-                    if (d < var1.length) {/* need to reduce */
-                        newvar1 = new byte[d];
-                        java.lang.System.arraycopy((java.lang.Object) var1, 0, (java.lang.Object) newvar1, 0, d); // shorten
-                        var1 = newvar1;
-                    }
-                    res.mant = var1;
-                    return res.finish(set, false);
-                } while (false);
-            }/* remainder */
-        }
-
-        else {/* 'D' -- no overflow check needed */
-            // If there was a residue then bump the final digit (iff 0 or 5)
-            // so that the residue is visible for ROUND_UP, ROUND_HALF_xxx and
-            // ROUND_UNNECESSARY checks (etc.) later.
-            // [if we finished early, the residue will be 0]
-            if (var1[0] != 0) { // residue not 0
-                lasthave = res.mant[have - 1];
-                if (((lasthave % 5)) == 0)
-                    res.mant[have - 1] = (byte) (lasthave + 1);
-            }
-        }
-
-        /* Here for Divide or Integer Divide */
-        // handle scaled results first ['I' always scale 0, optional for 'D']
-        if (scale >= 0) {
-            do {
-                // say 'scale have res.exp len' scale have res.exp res.mant.length
-                if (have != res.mant.length)
-                    // already padded with 0's, so just adjust exponent
-                    res.exp = res.exp - ((res.mant.length - have));
-                // calculate number of digits we really want [may be 0]
-                actdig = res.mant.length - (-res.exp - scale);
-                res.round(actdig, set.roundingMode); // round to desired length
-                // This could have shifted left if round (say) 0.9->1[.0]
-                // Repair if so by adding a zero and reducing exponent
-                if (res.exp != -scale) {
-                    res.mant = extend(res.mant, res.mant.length + 1);
-                    res.exp = res.exp - 1;
-                }
-                return res.finish(set, true); // [strip if not PLAIN]
-            } while (false);
-        }/* scaled */
-
-        // reach here only if a non-scaled
-        if (have == res.mant.length) { // got digits+1 digits
-            res.round(set);
-            have = reqdig;
-        } else {/* have<=reqdig */
-            if (res.mant[0] == 0)
-                return ZERO; // fastpath
-            // make the mantissa truly just 'have' long
-            // [we could let finish do this, during strip, if we adjusted
-            // the exponent; however, truncation avoids the strip loop]
-            newmant = new byte[have]; // shorten
-            java.lang.System.arraycopy((java.lang.Object) res.mant, 0, (java.lang.Object) newmant, 0, have);
-            res.mant = newmant;
-        }
-        return res.finish(set, true);
-    }
-
-    /* <sgml> Report a conversion exception. </sgml> */
-
-    private void bad(char s[]) {
-        throw new java.lang.NumberFormatException("Not a number:" + " " + java.lang.String.valueOf(s));
-    }
-
-    /*
-     * <sgml> Report a bad argument to a method. </sgml> Arg1 is method name Arg2 is argument position Arg3 is what was
-     * found
-     */
-
-    private void badarg(java.lang.String name, int pos, java.lang.String value) {
-        throw new java.lang.IllegalArgumentException("Bad argument" + " " + pos + " " + "to" + " " + name + ":" + " "
-                + value);
-    }
-
-    /*
-     * <sgml> Extend byte array to given length, padding with 0s. If no extension is required then return the same
-     * array. </sgml>
-     * 
-     * Arg1 is the source byte array Arg2 is the new length (longer)
-     */
-
-    private static final byte[] extend(byte inarr[], int newlen) {
-        byte newarr[];
-        if (inarr.length == newlen)
-            return inarr;
-        newarr = new byte[newlen];
-        java.lang.System.arraycopy((java.lang.Object) inarr, 0, (java.lang.Object) newarr, 0, inarr.length);
-        // 0 padding is carried out by the JVM on allocation initialization
-        return newarr;
-    }
-
-    /*
-     * <sgml> Add or subtract two >=0 integers in byte arrays <p>This routine performs the calculation: <pre> C=A+(BM)
-     * </pre> Where M is in the range -9 through +9 <p> If M<0 then A>=B must be true, so the result is always
-     * non-negative.
-     * 
-     * Leading zeros are not removed after a subtraction. The result is either the same length as the longer of A and B,
-     * or 1 longer than that (if a carry occurred).
-     * 
-     * A is not altered unless Arg6 is 1. B is never altered.
-     * 
-     * Arg1 is A Arg2 is A length to use (if longer than A, pad with 0's) Arg3 is B Arg4 is B length to use (if longer
-     * than B, pad with 0's) Arg5 is M, the multiplier Arg6 is 1 if A can be used to build the result (if it fits)
-     * 
-     * This routine is severely performance-critical;any change here must be measured (timed) to assure no performance
-     * degradation.
-     */
-    // 1996.02.20 -- enhanced version of DMSRCN algorithm (1981)
-    // 1997.10.05 -- changed to byte arrays (from char arrays)
-    // 1998.07.01 -- changed to allow destructive reuse of LHS
-    // 1998.07.01 -- changed to allow virtual lengths for the arrays
-    // 1998.12.29 -- use lookaside for digit/carry calculation
-    // 1999.08.07 -- avoid multiply when mult=1, and make db an int
-    // 1999.12.22 -- special case m=-1, also drop 0 special case
-    private static final byte[] byteaddsub(byte a[], int avlen, byte b[], int bvlen, int m, boolean reuse) {
-        int alength;
-        int blength;
-        int ap;
-        int bp;
-        int maxarr;
-        byte reb[];
-        boolean quickm;
-        int digit;
-        int op = 0;
-        int dp90 = 0;
-        byte newarr[];
-        int i = 0;
-
-        // We'll usually be right if we assume no carry
-        alength = a.length; // physical lengths
-        blength = b.length; // ..
-        ap = avlen - 1; // -> final (rightmost) digit
-        bp = bvlen - 1; // ..
-        maxarr = bp;
-        if (maxarr < ap)
-            maxarr = ap;
-        reb = (byte[]) null; // result byte array
-        if (reuse)
-            if ((maxarr + 1) == alength)
-                reb = a; // OK to reuse A
-        if (reb == null)
-            reb = new byte[maxarr + 1]; // need new array
-
-        quickm = false; // 1 if no multiply needed
-        if (m == 1)
-            quickm = true; // most common
-        else if (m == (-1))
-            quickm = true; // also common
-
-        digit = 0; // digit, with carry or borrow
-        {
-            op = maxarr;
-            op: for (; op >= 0; op--) {
-                if (ap >= 0) {
-                    if (ap < alength)
-                        digit = digit + a[ap]; // within A
-                    ap--;
-                }
-                if (bp >= 0) {
-                    if (bp < blength) { // within B
-                        if (quickm) {
-                            if (m > 0)
-                                digit = digit + b[bp]; // most common
-                            else
-                                digit = digit - b[bp]; // also common
-                        } else
-                            digit = digit + (b[bp] * m);
-                    }
-                    bp--;
-                }
-                /* result so far (digit) could be -90 through 99 */
-                if (digit < 10)
-                    if (digit >= 0) {
-                        do { // 0-9
-                            reb[op] = (byte) digit;
-                            digit = 0; // no carry
-                            continue op;
-                        } while (false);
-                    }/* quick */
-                dp90 = digit + 90;
-                reb[op] = bytedig[dp90]; // this digit
-                digit = bytecar[dp90]; // carry or borrow
-            }
-        }/* op */
-
-        if (digit == 0)
-            return reb; // no carry
-        // following line will become an Assert, later
-        // if digit<0 then signal ArithmeticException("internal.error ["digit"]")
-
-        /* We have carry -- need to make space for the extra digit */
-        newarr = (byte[]) null;
-        if (reuse)
-            if ((maxarr + 2) == a.length)
-                newarr = a; // OK to reuse A
-        if (newarr == null)
-            newarr = new byte[maxarr + 2];
-        newarr[0] = (byte) digit; // the carried digit ..
-        // .. and all the rest [use local loop for short numbers]
-        if (maxarr < 10) {
-            int $24 = maxarr + 1;
-            i = 0;
-            for (; $24 > 0; $24--, i++) {
-                newarr[i + 1] = reb[i];
-            }
-        }/* i */
-        else
-            java.lang.System.arraycopy((java.lang.Object) reb, 0, (java.lang.Object) newarr, 1, maxarr + 1);
-        return newarr;
-    }
-
-    /*
-     * <sgml> Initializer for digit array properties (lookaside). </sgml> Returns the digit array, and initializes the
-     * carry array.
-     */
-
-    private static final byte[] diginit() {
-        byte work[];
-        int op = 0;
-        int digit = 0;
-        work = new byte[(90 + 99) + 1];
-        {
-            op = 0;
-            op: for (; op <= (90 + 99); op++) {
-                digit = op - 90;
-                if (digit >= 0) {
-                    work[op] = (byte) (digit % 10);
-                    bytecar[op] = (byte) (digit / 10); // calculate carry
-                    continue op;
-                }
-                // borrowing...
-                digit = digit + 100; // yes, this is right [consider -50]
-                work[op] = (byte) (digit % 10);
-                bytecar[op] = (byte) ((digit / 10) - 10); // calculate borrow [NB: - after %]
-            }
-        }/* op */
-        return work;
-    }
-
-    /*
-     * <sgml> Create a copy of BigDecimal object for local use. <p>This does NOT make a copy of the mantissa array.
-     * </sgml> Arg1 is the BigDecimal to clone (non-null)
-     */
-
-    private static final com.ibm.icu.math.BigDecimal clone(com.ibm.icu.math.BigDecimal dec) {
-        com.ibm.icu.math.BigDecimal copy;
-        copy = new com.ibm.icu.math.BigDecimal();
-        copy.ind = dec.ind;
-        copy.exp = dec.exp;
-        copy.form = dec.form;
-        copy.mant = dec.mant;
-        return copy;
-    }
-
-    /*
-     * <sgml> Check one or two numbers for lost digits. </sgml> Arg1 is RHS (or null, if none) Arg2 is current DIGITS
-     * setting returns quietly or throws an exception
-     */
-
-    private void checkdigits(com.ibm.icu.math.BigDecimal rhs, int dig) {
-        if (dig == 0)
-            return; // don't check if digits=0
-        // first check lhs...
-        if (this.mant.length > dig)
-            if ((!(allzero(this.mant, dig))))
-                throw new java.lang.ArithmeticException("Too many digits:" + " " + this.toString());
-        if (rhs == null)
-            return; // monadic
-        if (rhs.mant.length > dig)
-            if ((!(allzero(rhs.mant, dig))))
-                throw new java.lang.ArithmeticException("Too many digits:" + " " + rhs.toString());
-    }
-
-    /*
-     * <sgml> Round to specified digits, if necessary. </sgml> Arg1 is requested MathContext [with length and rounding
-     * mode] returns this, for convenience
-     */
-
-    private com.ibm.icu.math.BigDecimal round(com.ibm.icu.math.MathContext set) {
-        return round(set.digits, set.roundingMode);
-    }
-
-    /*
-     * <sgml> Round to specified digits, if necessary. Arg1 is requested length (digits to round to) [may be <=0 when
-     * called from format, dodivide, etc.] Arg2 is rounding mode returns this, for convenience
-     * 
-     * ind and exp are adjusted, but not cleared for a mantissa of zero
-     * 
-     * The length of the mantissa returned will be Arg1, except when Arg1 is 0, in which case the returned mantissa
-     * length will be 1. </sgml>
-     */
-
-    private com.ibm.icu.math.BigDecimal round(int len, int mode) {
-        int adjust;
-        int sign;
-        byte oldmant[];
-        boolean reuse = false;
-        byte first = 0;
-        int increment;
-        byte newmant[] = null;
-        adjust = mant.length - len;
-        if (adjust <= 0)
-            return this; // nowt to do
-
-        exp = exp + adjust; // exponent of result
-        sign = (int) ind; // save [assumes -1, 0, 1]
-        oldmant = mant; // save
-        if (len > 0) {
-            // remove the unwanted digits
-            mant = new byte[len];
-            java.lang.System.arraycopy((java.lang.Object) oldmant, 0, (java.lang.Object) mant, 0, len);
-            reuse = true; // can reuse mantissa
-            first = oldmant[len]; // first of discarded digits
-        } else {/* len<=0 */
-            mant = ZERO.mant;
-            ind = iszero;
-            reuse = false; // cannot reuse mantissa
-            if (len == 0)
-                first = oldmant[0];
-            else
-                first = (byte) 0; // [virtual digit]
-        }
-
-        // decide rounding adjustment depending on mode, sign, and discarded digits
-        increment = 0; // bumper
-        {
-            do {/* select */
-                if (mode == ROUND_HALF_UP) { // default first [most common]
-                    if (first >= 5)
-                        increment = sign;
-                } else if (mode == ROUND_UNNECESSARY) { // default for setScale()
-                    // discarding any non-zero digits is an error
-                    if ((!(allzero(oldmant, len))))
-                        throw new java.lang.ArithmeticException("Rounding necessary");
-                } else if (mode == ROUND_HALF_DOWN) { // 0.5000 goes down
-                    if (first > 5)
-                        increment = sign;
-                    else if (first == 5)
-                        if ((!(allzero(oldmant, len + 1))))
-                            increment = sign;
-                } else if (mode == ROUND_HALF_EVEN) { // 0.5000 goes down if left digit even
-                    if (first > 5)
-                        increment = sign;
-                    else if (first == 5) {
-                        if ((!(allzero(oldmant, len + 1))))
-                            increment = sign;
-                        else /* 0.5000 */
-                        if ((((mant[mant.length - 1]) % 2)) == 1)
-                            increment = sign;
-                    }
-                } else if (mode == ROUND_DOWN) {
-                    // never increment
-                } else if (mode == ROUND_UP) { // increment if discarded non-zero
-                    if ((!(allzero(oldmant, len))))
-                        increment = sign;
-                } else if (mode == ROUND_CEILING) { // more positive
-                    if (sign > 0)
-                        if ((!(allzero(oldmant, len))))
-                            increment = sign;
-                } else if (mode == ROUND_FLOOR) { // more negative
-                    if (sign < 0)
-                        if ((!(allzero(oldmant, len))))
-                            increment = sign;
-                } else {
-                    throw new java.lang.IllegalArgumentException("Bad round value:" + " " + mode);
-                }
-            } while (false);
-        }/* modes */
-
-        if (increment != 0) {
-            do {
-                if (ind == iszero) {
-                    // we must not subtract from 0, but result is trivial anyway
-                    mant = ONE.mant;
-                    ind = (byte) increment;
-                } else {
-                    // mantissa is non-0; we can safely add or subtract 1
-                    if (ind == isneg)
-                        increment = -increment;
-                    newmant = byteaddsub(mant, mant.length, ONE.mant, 1, increment, reuse);
-                    if (newmant.length > mant.length) { // had a carry
-                        // drop rightmost digit and raise exponent
-                        exp++;
-                        // mant is already the correct length
-                        java.lang.System.arraycopy((java.lang.Object) newmant, 0, (java.lang.Object) mant, 0,
-                                mant.length);
-                    } else
-                        mant = newmant;
-                }
-            } while (false);
-        }/* bump */
-        // rounding can increase exponent significantly
-        if (exp > MaxExp)
-            throw new java.lang.ArithmeticException("Exponent Overflow:" + " " + exp);
-        return this;
-    }
-
-    /*
-     * <sgml> Test if rightmost digits are all 0. Arg1 is a mantissa array to test Arg2 is the offset of first digit to
-     * check [may be negative; if so, digits to left are 0's] returns 1 if all the digits starting at Arg2 are 0
-     * 
-     * Arg2 may be beyond array bounds, in which case 1 is returned </sgml>
-     */
-
-    private static final boolean allzero(byte array[], int start) {
-        int i = 0;
-        if (start < 0)
-            start = 0;
-        {
-            int $25 = array.length - 1;
-            i = start;
-            for (; i <= $25; i++) {
-                if (array[i] != 0)
-                    return false;
-            }
-        }/* i */
-        return true;
-    }
-
-    /*
-     * <sgml> Carry out final checks and canonicalization <p> This finishes off the current number by: 1. Rounding if
-     * necessary (NB: length includes leading zeros) 2. Stripping trailing zeros (if requested and \PLAIN) 3. Stripping
-     * leading zeros (always) 4. Selecting exponential notation (if required) 5. Converting a zero result to just '0'
-     * (if \PLAIN) In practice, these operations overlap and share code. It always sets form. </sgml> Arg1 is requested
-     * MathContext (length to round to, trigger, and FORM) Arg2 is 1 if trailing insignificant zeros should be removed
-     * after round (for division, etc.), provided that set.form isn't PLAIN. returns this, for convenience
-     */
-
-    private com.ibm.icu.math.BigDecimal finish(com.ibm.icu.math.MathContext set, boolean strip) {
-        int d = 0;
-        int i = 0;
-        byte newmant[] = null;
-        int mag = 0;
-        int sig = 0;
-        /* Round if mantissa too long and digits requested */
-        if (set.digits != 0)
-            if (this.mant.length > set.digits)
-                this.round(set);
-
-        /*
-         * If strip requested (and standard formatting), remove insignificant trailing zeros.
-         */
-        if (strip)
-            if (set.form != com.ibm.icu.math.MathContext.PLAIN) {
-                d = this.mant.length;
-                /* see if we need to drop any trailing zeros */
-                {
-                    i = d - 1;
-                    i: for (; i >= 1; i--) {
-                        if (this.mant[i] != 0)
-                            break i;
-                        d--;
-                        exp++;
-                    }
-                }/* i */
-                if (d < this.mant.length) {/* need to reduce */
-                    newmant = new byte[d];
-                    java.lang.System.arraycopy((java.lang.Object) this.mant, 0, (java.lang.Object) newmant, 0, d);
-                    this.mant = newmant;
-                }
-            }
-
-        form = (byte) com.ibm.icu.math.MathContext.PLAIN; // preset
-
-        /* Now check for leading- and all- zeros in mantissa */
-        {
-            int $26 = this.mant.length;
-            i = 0;
-            for (; $26 > 0; $26--, i++) {
-                if (this.mant[i] != 0) {
-                    // non-0 result; ind will be correct
-                    // remove leading zeros [e.g., after subtract]
-                    if (i > 0) {
-                        do {
-                            newmant = new byte[this.mant.length - i];
-                            java.lang.System.arraycopy((java.lang.Object) this.mant, i, (java.lang.Object) newmant, 0,
-                                    this.mant.length - i);
-                            this.mant = newmant;
-                        } while (false);
-                    }/* delead */
-                    // now determine form if not PLAIN
-                    mag = exp + mant.length;
-                    if (mag > 0) { // most common path
-                        if (mag > set.digits)
-                            if (set.digits != 0)
-                                form = (byte) set.form;
-                        if ((mag - 1) <= MaxExp)
-                            return this; // no overflow; quick return
-                    } else if (mag < (-5))
-                        form = (byte) set.form;
-                    /* check for overflow */
-                    mag--;
-                    if ((mag < MinExp) | (mag > MaxExp)) {
-                        overflow: do {
-                            // possible reprieve if form is engineering
-                            if (form == com.ibm.icu.math.MathContext.ENGINEERING) {
-                                sig = mag % 3; // leftover
-                                if (sig < 0)
-                                    sig = 3 + sig; // negative exponent
-                                mag = mag - sig; // exponent to use
-                                // 1999.06.29: second test here must be MaxExp
-                                if (mag >= MinExp)
-                                    if (mag <= MaxExp)
-                                        break overflow;
-                            }
-                            throw new java.lang.ArithmeticException("Exponent Overflow:" + " " + mag);
-                        } while (false);
-                    }/* overflow */
-                    return this;
-                }
-            }
-        }/* i */
-
-        // Drop through to here only if mantissa is all zeros
-        ind = iszero;
-        {/* select */
-            if (set.form != com.ibm.icu.math.MathContext.PLAIN)
-                exp = 0; // standard result; go to '0'
-            else if (exp > 0)
-                exp = 0; // +ve exponent also goes to '0'
-            else {
-                // a plain number with -ve exponent; preserve and check exponent
-                if (exp < MinExp)
-                    throw new java.lang.ArithmeticException("Exponent Overflow:" + " " + exp);
-            }
-        }
-        mant = ZERO.mant; // canonical mantissa
-        return this;
-    }
-}
+/* Generated from 'BigDecimal.nrx' 8 Sep 2000 11:10:50 [v2.00] */
+/* Options: Binary Comments Crossref Format Java Logo Strictargs Strictcase Trace2 Verbose3 */
+package com.ibm.icu.math;
+
+import java.math.BigInteger;
+
+/* ------------------------------------------------------------------ */
+/* BigDecimal -- Decimal arithmetic for Java                          */
+/* ------------------------------------------------------------------ */
+/* Copyright IBM Corporation, 1996-2011.  All Rights Reserved.       */
+/*                                                                    */
+/* The BigDecimal class provides immutable arbitrary-precision        */
+/* floating point (including integer) decimal numbers.                */
+/*                                                                    */
+/* As the numbers are decimal, there is an exact correspondence       */
+/* between an instance of a BigDecimal object and its String          */
+/* representation; the BigDecimal class provides direct conversions   */
+/* to and from String and character array objects, and well as        */
+/* conversions to and from the Java primitive types (which may not    */
+/* be exact).                                                         */
+/* ------------------------------------------------------------------ */
+/* Notes:                                                             */
+/*                                                                    */
+/* 1. A BigDecimal object is never changed in value once constructed; */
+/*    this avoids the need for locking.  Note in particular that the  */
+/*    mantissa array may be shared between many BigDecimal objects,   */
+/*    so that once exposed it must not be altered.                    */
+/*                                                                    */
+/* 2. This class looks at MathContext class fields directly (for      */
+/*    performance).  It must not and does not change them.            */
+/*                                                                    */
+/* 3. Exponent checking is delayed until finish(), as we know         */
+/*    intermediate calculations cannot cause 31-bit overflow.         */
+/*    [This assertion depends on MAX_DIGITS in MathContext.]          */
+/*                                                                    */
+/* 4. Comments for the public API now follow the javadoc conventions. */
+/*    The NetRexx -comments option is used to pass these comments     */
+/*    through to the generated Java code (with -format, if desired).  */
+/*                                                                    */
+/* 5. System.arraycopy is faster than explicit loop as follows        */
+/*      Mean length 4:  equal                                         */
+/*      Mean length 8:  x2                                            */
+/*      Mean length 16: x3                                            */
+/*      Mean length 24: x4                                            */
+/*    From prior experience, we expect mean length a little below 8,  */
+/*    but arraycopy is still the one to use, in general, until later  */
+/*    measurements suggest otherwise.                                 */
+/*                                                                    */
+/* 6. 'DMSRCN' referred to below is the original (1981) IBM S/370     */
+/*    assembler code implementation of the algorithms below; it is    */
+/*    now called IXXRCN and is available with the OS/390 and VM/ESA   */
+/*    operating systems.                                              */
+/* ------------------------------------------------------------------ */
+/* Change History:                                                    */
+/* 1997.09.02 Initial version (derived from netrexx.lang classes)     */
+/* 1997.09.12 Add lostDigits checking                                 */
+/* 1997.10.06 Change mantissa to a byte array                         */
+/* 1997.11.22 Rework power [did not prepare arguments, etc.]          */
+/* 1997.12.13 multiply did not prepare arguments                      */
+/* 1997.12.14 add did not prepare and align arguments correctly       */
+/* 1998.05.02 0.07 packaging changes suggested by Sun and Oracle      */
+/* 1998.05.21 adjust remainder operator finalization                  */
+/* 1998.06.04 rework to pass MathContext to finish() and round()      */
+/* 1998.06.06 change format to use round(); support rounding modes    */
+/* 1998.06.25 rename to BigDecimal and begin merge                    */
+/*            zero can now have trailing zeros (i.e., exp\=0)         */
+/* 1998.06.28 new methods: movePointXxxx, scale, toBigInteger         */
+/*                         unscaledValue, valueof                     */
+/* 1998.07.01 improve byteaddsub to allow array reuse, etc.           */
+/* 1998.07.01 make null testing explicit to avoid JIT bug [Win32]     */
+/* 1998.07.07 scaled division  [divide(BigDecimal, int, int)]         */
+/* 1998.07.08 setScale, faster equals                                 */
+/* 1998.07.11 allow 1E6 (no sign) <sigh>; new double/float conversion */
+/* 1998.10.12 change package to com.ibm.icu.math                          */
+/* 1998.12.14 power operator no longer rounds RHS [to match ANSI]     */
+/*            add toBigDecimal() and BigDecimal(java.math.BigDecimal) */
+/* 1998.12.29 improve byteaddsub by using table lookup                */
+/* 1999.02.04 lostdigits=0 behaviour rounds instead of digits+1 guard */
+/* 1999.02.05 cleaner code for BigDecimal(char[])                     */
+/* 1999.02.06 add javadoc comments                                    */
+/* 1999.02.11 format() changed from 7 to 2 method form                */
+/* 1999.03.05 null pointer checking is no longer explicit             */
+/* 1999.03.05 simplify; changes from discussion with J. Bloch:        */
+/*            null no longer permitted for MathContext; drop boolean, */
+/*            byte, char, float, short constructor, deprecate double  */
+/*            constructor, no blanks in string constructor, add       */
+/*            offset and length version of char[] constructor;        */
+/*            add valueOf(double); drop booleanValue, charValue;      */
+/*            add ...Exact versions of remaining convertors           */
+/* 1999.03.13 add toBigIntegerExact                                   */
+/* 1999.03.13 1.00 release to IBM Centre for Java Technology          */
+/* 1999.05.27 1.01 correct 0-0.2 bug under scaled arithmetic          */
+/* 1999.06.29 1.02 constructors should not allow exponent > 9 digits  */
+/* 1999.07.03 1.03 lost digits should not be checked if digits=0      */
+/* 1999.07.06      lost digits Exception message changed              */
+/* 1999.07.10 1.04 more work on 0-0.2 (scaled arithmetic)             */
+/* 1999.07.17      improve messages from pow method                   */
+/* 1999.08.08      performance tweaks                                 */
+/* 1999.08.15      fastpath in multiply                               */
+/* 1999.11.05 1.05 fix problem in intValueExact [e.g., 5555555555]    */
+/* 1999.12.22 1.06 remove multiply fastpath, and improve performance  */
+/* 2000.01.01      copyright update [Y2K has arrived]                 */
+/* 2000.06.18 1.08 no longer deprecate BigDecimal(double)             */
+/* ------------------------------------------------------------------ */
+
+/**
+ * The <code>BigDecimal</code> class implements immutable arbitrary-precision decimal numbers. The methods of the
+ * <code>BigDecimal</code> class provide operations for fixed and floating point arithmetic, comparison, format
+ * conversions, and hashing.
+ * <p>
+ * As the numbers are decimal, there is an exact correspondence between an instance of a <code>BigDecimal</code> object
+ * and its <code>String</code> representation; the <code>BigDecimal</code> class provides direct conversions to and from
+ * <code>String</code> and character array (<code>char[]</code>) objects, as well as conversions to and from the Java
+ * primitive types (which may not be exact) and <code>BigInteger</code>.
+ * <p>
+ * In the descriptions of constructors and methods in this documentation, the value of a <code>BigDecimal</code> number
+ * object is shown as the result of invoking the <code>toString()</code> method on the object. The internal
+ * representation of a decimal number is neither defined nor exposed, and is not permitted to affect the result of any
+ * operation.
+ * <p>
+ * The floating point arithmetic provided by this class is defined by the ANSI X3.274-1996 standard, and is also
+ * documented at <code>http://www2.hursley.ibm.com/decimal</code> <br>
+ * <i>[This URL will change.]</i>
+ * 
+ * <h3>Operator methods</h3>
+ * <p>
+ * Operations on <code>BigDecimal</code> numbers are controlled by a {@link MathContext} object, which provides the
+ * context (precision and other information) for the operation. Methods that can take a <code>MathContext</code>
+ * parameter implement the standard arithmetic operators for <code>BigDecimal</code> objects and are known as
+ * <i>operator methods</i>. The default settings provided by the constant {@link MathContext#DEFAULT} (<code>digits=9,
+ * form=SCIENTIFIC, lostDigits=false, roundingMode=ROUND_HALF_UP</code>) perform general-purpose floating point
+ * arithmetic to nine digits of precision. The <code>MathContext</code> parameter must not be <code>null</code>.
+ * <p>
+ * Each operator method also has a version provided which does not take a <code>MathContext</code> parameter. For this
+ * version of each method, the context settings used are <code>digits=0,
+ * form=PLAIN, lostDigits=false, roundingMode=ROUND_HALF_UP</code>; these settings perform fixed point arithmetic with
+ * unlimited precision, as defined for the original BigDecimal class in Java 1.1 and Java 1.2.
+ * <p>
+ * For monadic operators, only the optional <code>MathContext</code> parameter is present; the operation acts upon the
+ * current object.
+ * <p>
+ * For dyadic operators, a <code>BigDecimal</code> parameter is always present; it must not be <code>null</code>. The
+ * operation acts with the current object being the left-hand operand and the <code>BigDecimal</code> parameter being
+ * the right-hand operand.
+ * <p>
+ * For example, adding two <code>BigDecimal</code> objects referred to by the names <code>award</code> and
+ * <code>extra</code> could be written as any of:
+ * <p>
+ * <code>
+ *     award.add(extra)
+ * <br>award.add(extra, MathContext.DEFAULT)
+ * <br>award.add(extra, acontext)
+ * </code>
+ * <p>
+ * (where <code>acontext</code> is a <code>MathContext</code> object), which would return a <code>BigDecimal</code>
+ * object whose value is the result of adding <code>award</code> and <code>extra</code> under the appropriate context
+ * settings.
+ * <p>
+ * When a <code>BigDecimal</code> operator method is used, a set of rules define what the result will be (and, by
+ * implication, how the result would be represented as a character string). These rules are defined in the BigDecimal
+ * arithmetic documentation (see the URL above), but in summary:
+ * <ul>
+ * <li>Results are normally calculated with up to some maximum number of significant digits. For example, if the
+ * <code>MathContext</code> parameter for an operation were <code>MathContext.DEFAULT</code> then the result would be
+ * rounded to 9 digits; the division of 2 by 3 would then result in 0.666666667. <br>
+ * You can change the default of 9 significant digits by providing the method with a suitable <code>MathContext</code>
+ * object. This lets you calculate using as many digits as you need -- thousands, if necessary. Fixed point (scaled)
+ * arithmetic is indicated by using a <code>digits</code> setting of 0 (or omitting the <code>MathContext</code>
+ * parameter). <br>
+ * Similarly, you can change the algorithm used for rounding from the default "classic" algorithm.
+ * <li>
+ * In standard arithmetic (that is, when the <code>form</code> setting is not <code>PLAIN</code>), a zero result is
+ * always expressed as the single digit <code>'0'</code> (that is, with no sign, decimal point, or exponent part).
+ * <li>
+ * Except for the division and power operators in standard arithmetic, trailing zeros are preserved (this is in contrast
+ * to binary floating point operations and most electronic calculators, which lose the information about trailing zeros
+ * in the fractional part of results). <br>
+ * So, for example:
+ * <p>
+ * <code>
+ *     new BigDecimal("2.40").add(     new BigDecimal("2"))      =&gt; "4.40"
+ * <br>new BigDecimal("2.40").subtract(new BigDecimal("2"))      =&gt; "0.40"
+ * <br>new BigDecimal("2.40").multiply(new BigDecimal("2"))      =&gt; "4.80"
+ * <br>new BigDecimal("2.40").divide(  new BigDecimal("2"), def) =&gt; "1.2"
+ * </code>
+ * <p>
+ * where the value on the right of the <code>=&gt;</code> would be the result of the operation, expressed as a
+ * <code>String</code>, and <code>def</code> (in this and following examples) refers to <code>MathContext.DEFAULT</code>
+ * ). This preservation of trailing zeros is desirable for most calculations (including financial calculations). If
+ * necessary, trailing zeros may be easily removed using division by 1.
+ * <li>
+ * In standard arithmetic, exponential form is used for a result depending on its value and the current setting of
+ * <code>digits</code> (the default is 9 digits). If the number of places needed before the decimal point exceeds the
+ * <code>digits</code> setting, or the absolute value of the number is less than <code>0.000001</code>, then the number
+ * will be expressed in exponential notation; thus
+ * <p>
+ * <code>
+ *   new BigDecimal("1e+6").multiply(new BigDecimal("1e+6"), def)
+ * </code>
+ * <p>
+ * results in <code>1E+12</code> instead of <code>1000000000000</code>, and
+ * <p>
+ * <code>
+ *   new BigDecimal("1").divide(new BigDecimal("3E+10"), def)
+ * </code>
+ * <p>
+ * results in <code>3.33333333E-11</code> instead of <code>0.0000000000333333333</code>.
+ * <p>
+ * The form of the exponential notation (scientific or engineering) is determined by the <code>form</code> setting.
+ * <eul>
+ * <p>
+ * The names of methods in this class follow the conventions established by <code>java.lang.Number</code>,
+ * <code>java.math.BigInteger</code>, and <code>java.math.BigDecimal</code> in Java 1.1 and Java 1.2.
+ * 
+ * @see MathContext
+ * @author Mike Cowlishaw
+ * @stable ICU 2.0
+ */
+
+public class BigDecimal extends java.lang.Number implements java.io.Serializable, java.lang.Comparable<BigDecimal> {
+    // private static final java.lang.String $0="BigDecimal.nrx";
+
+    /* ----- Constants ----- */
+    /* properties constant public */// useful to others
+    /**
+     * The <code>BigDecimal</code> constant "0".
+     * 
+     * @see #ONE
+     * @see #TEN
+     * @stable ICU 2.0
+     */
+    public static final com.ibm.icu.math.BigDecimal ZERO = new com.ibm.icu.math.BigDecimal((long) 0); // use long as we
+                                                                                                      // want the int
+                                                                                                      // constructor
+    // .. to be able to use this, for speed
+
+    /**
+     * The <code>BigDecimal</code> constant "1".
+     * 
+     * @see #TEN
+     * @see #ZERO
+     * @stable ICU 2.0
+     */
+    public static final com.ibm.icu.math.BigDecimal ONE = new com.ibm.icu.math.BigDecimal((long) 1); // use long as we
+                                                                                                     // want the int
+                                                                                                     // constructor
+    // .. to be able to use this, for speed
+
+    /**
+     * The <code>BigDecimal</code> constant "10".
+     * 
+     * @see #ONE
+     * @see #ZERO
+     * @stable ICU 2.0
+     */
+    public static final com.ibm.icu.math.BigDecimal TEN = new com.ibm.icu.math.BigDecimal(10);
+
+    // the rounding modes (copied here for upwards compatibility)
+    /**
+     * Rounding mode to round to a more positive number.
+     * 
+     * @see MathContext#ROUND_CEILING
+     * @stable ICU 2.0
+     */
+    public static final int ROUND_CEILING = com.ibm.icu.math.MathContext.ROUND_CEILING;
+
+    /**
+     * Rounding mode to round towards zero.
+     * 
+     * @see MathContext#ROUND_DOWN
+     * @stable ICU 2.0
+     */
+    public static final int ROUND_DOWN = com.ibm.icu.math.MathContext.ROUND_DOWN;
+
+    /**
+     * Rounding mode to round to a more negative number.
+     * 
+     * @see MathContext#ROUND_FLOOR
+     * @stable ICU 2.0
+     */
+    public static final int ROUND_FLOOR = com.ibm.icu.math.MathContext.ROUND_FLOOR;
+
+    /**
+     * Rounding mode to round to nearest neighbor, where an equidistant value is rounded down.
+     * 
+     * @see MathContext#ROUND_HALF_DOWN
+     * @stable ICU 2.0
+     */
+    public static final int ROUND_HALF_DOWN = com.ibm.icu.math.MathContext.ROUND_HALF_DOWN;
+
+    /**
+     * Rounding mode to round to nearest neighbor, where an equidistant value is rounded to the nearest even neighbor.
+     * 
+     * @see MathContext#ROUND_HALF_EVEN
+     * @stable ICU 2.0
+     */
+    public static final int ROUND_HALF_EVEN = com.ibm.icu.math.MathContext.ROUND_HALF_EVEN;
+
+    /**
+     * Rounding mode to round to nearest neighbor, where an equidistant value is rounded up.
+     * 
+     * @see MathContext#ROUND_HALF_UP
+     * @stable ICU 2.0
+     */
+    public static final int ROUND_HALF_UP = com.ibm.icu.math.MathContext.ROUND_HALF_UP;
+
+    /**
+     * Rounding mode to assert that no rounding is necessary.
+     * 
+     * @see MathContext#ROUND_UNNECESSARY
+     * @stable ICU 2.0
+     */
+    public static final int ROUND_UNNECESSARY = com.ibm.icu.math.MathContext.ROUND_UNNECESSARY;
+
+    /**
+     * Rounding mode to round away from zero.
+     * 
+     * @see MathContext#ROUND_UP
+     * @stable ICU 2.0
+     */
+    public static final int ROUND_UP = com.ibm.icu.math.MathContext.ROUND_UP;
+
+    /* properties constant private */// locals
+    private static final byte ispos = 1; // ind: indicates positive (must be 1)
+    private static final byte iszero = 0; // ind: indicates zero (must be 0)
+    private static final byte isneg = -1; // ind: indicates negative (must be -1)
+    // [later could add NaN, +/- infinity, here]
+
+    private static final int MinExp = -999999999; // minimum exponent allowed
+    private static final int MaxExp = 999999999; // maximum exponent allowed
+    private static final int MinArg = -999999999; // minimum argument integer
+    private static final int MaxArg = 999999999; // maximum argument integer
+
+    private static final com.ibm.icu.math.MathContext plainMC = new com.ibm.icu.math.MathContext(0,
+            com.ibm.icu.math.MathContext.PLAIN); // context for plain unlimited math
+
+    /* properties constant private unused */// present but not referenced
+    // Serialization version
+    private static final long serialVersionUID = 8245355804974198832L;
+
+    // private static final java.lang.String
+    // copyright=" Copyright (c) IBM Corporation 1996, 2000.  All rights reserved. ";
+
+    /* properties static private */
+    // Precalculated constant arrays (used by byteaddsub)
+    private static byte bytecar[] = new byte[(90 + 99) + 1]; // carry/borrow array
+    private static byte bytedig[] = diginit(); // next digit array
+
+    /* ----- Instance properties [all private and immutable] ----- */
+    /* properties private */
+
+    /**
+     * The indicator. This may take the values:
+     * <ul>
+     * <li>ispos -- the number is positive <li>iszero -- the number is zero <li>isneg -- the number is negative
+     * </ul>
+     * 
+     * @serial
+     */
+    private byte ind; // assumed undefined
+    // Note: some code below assumes IND = Sign [-1, 0, 1], at present.
+    // We only need two bits for this, but use a byte [also permits
+    // smooth future extension].
+
+    /**
+     * The formatting style. This may take the values:
+     * <ul>
+     * <li>MathContext.PLAIN -- no exponent needed <li>MathContext.SCIENTIFIC -- scientific notation required <li>
+     * MathContext.ENGINEERING -- engineering notation required
+     * </ul>
+     * <p>
+     * This property is an optimization; it allows us to defer number layout until it is actually needed as a string,
+     * hence avoiding unnecessary formatting.
+     * 
+     * @serial
+     */
+    private byte form = (byte) com.ibm.icu.math.MathContext.PLAIN; // assumed PLAIN
+    // We only need two bits for this, at present, but use a byte
+    // [again, to allow for smooth future extension]
+
+    /**
+     * The value of the mantissa.
+     * <p>
+     * Once constructed, this may become shared between several BigDecimal objects, so must not be altered.
+     * <p>
+     * For efficiency (speed), this is a byte array, with each byte taking a value of 0 -> 9.
+     * <p>
+     * If the first byte is 0 then the value of the number is zero (and mant.length=1, except when constructed from a
+     * plain number, for example, 0.000).
+     * 
+     * @serial
+     */
+    private byte mant[]; // assumed null
+
+    /**
+     * The exponent.
+     * <p>
+     * For fixed point arithmetic, scale is <code>-exp</code>, and can apply to zero.
+     * 
+     * Note that this property can have a value less than MinExp when the mantissa has more than one digit.
+     * 
+     * @serial
+     */
+    private int exp;
+
+    // assumed 0
+
+    /* ---------------------------------------------------------------- */
+    /* Constructors */
+    /* ---------------------------------------------------------------- */
+
+    /**
+     * Constructs a <code>BigDecimal</code> object from a <code>java.math.BigDecimal</code>.
+     * <p>
+     * Constructs a <code>BigDecimal</code> as though the parameter had been represented as a <code>String</code> (using
+     * its <code>toString</code> method) and the {@link #BigDecimal(java.lang.String)} constructor had then been used.
+     * The parameter must not be <code>null</code>.
+     * <p>
+     * <i>(Note: this constructor is provided only in the <code>com.ibm.icu.math</code> version of the BigDecimal class.
+     * It would not be present in a <code>java.math</code> version.)</i>
+     * 
+     * @param bd The <code>BigDecimal</code> to be translated.
+     * @stable ICU 2.0
+     */
+
+    public BigDecimal(java.math.BigDecimal bd) {
+        this(bd.toString());
+        return;
+    }
+
+    /**
+     * Constructs a <code>BigDecimal</code> object from a <code>BigInteger</code>, with scale 0.
+     * <p>
+     * Constructs a <code>BigDecimal</code> which is the exact decimal representation of the <code>BigInteger</code>,
+     * with a scale of zero. The value of the <code>BigDecimal</code> is identical to the value of the <code>BigInteger
+     * </code>. The parameter must not be <code>null</code>.
+     * <p>
+     * The <code>BigDecimal</code> will contain only decimal digits, prefixed with a leading minus sign (hyphen) if the
+     * <code>BigInteger</code> is negative. A leading zero will be present only if the <code>BigInteger</code> is zero.
+     * 
+     * @param bi The <code>BigInteger</code> to be converted.
+     * @stable ICU 2.0
+     */
+
+    public BigDecimal(java.math.BigInteger bi) {
+        this(bi.toString(10));
+        return;
+    }
+
+    // exp remains 0
+
+    /**
+     * Constructs a <code>BigDecimal</code> object from a <code>BigInteger</code> and a scale.
+     * <p>
+     * Constructs a <code>BigDecimal</code> which is the exact decimal representation of the <code>BigInteger</code>,
+     * scaled by the second parameter, which may not be negative. The value of the <code>BigDecimal</code> is the <code>
+     * BigInteger</code> divided by ten to the power of the scale. The <code>BigInteger</code> parameter must not be
+     * <code>null</code>.
+     * <p>
+     * The <code>BigDecimal</code> will contain only decimal digits, (with an embedded decimal point followed by <code>
+     * scale</code> decimal digits if the scale is positive), prefixed with a leading minus sign (hyphen) if the <code>
+     * BigInteger</code> is negative. A leading zero will be present only if the <code>BigInteger</code> is zero.
+     * 
+     * @param bi The <code>BigInteger</code> to be converted.
+     * @param scale The <code>int</code> specifying the scale.
+     * @throws NumberFormatException If the scale is negative.
+     * @stable ICU 2.0
+     */
+
+    public BigDecimal(java.math.BigInteger bi, int scale) {
+        this(bi.toString(10));
+        if (scale < 0)
+            throw new java.lang.NumberFormatException("Negative scale:" + " " + scale);
+        exp = -scale; // exponent is -scale
+        return;
+    }
+
+    /**
+     * Constructs a <code>BigDecimal</code> object from an array of characters.
+     * <p>
+     * Constructs a <code>BigDecimal</code> as though a <code>String</code> had been constructed from the character
+     * array and the {@link #BigDecimal(java.lang.String)} constructor had then been used. The parameter must not be
+     * <code>null</code>.
+     * <p>
+     * Using this constructor is faster than using the <code>BigDecimal(String)</code> constructor if the string is
+     * already available in character array form.
+     * 
+     * @param inchars The <code>char[]</code> array containing the number to be converted.
+     * @throws NumberFormatException If the parameter is not a valid number.
+     * @stable ICU 2.0
+     */
+
+    public BigDecimal(char inchars[]) {
+        this(inchars, 0, inchars.length);
+        return;
+    }
+
+    /**
+     * Constructs a <code>BigDecimal</code> object from an array of characters.
+     * <p>
+     * Constructs a <code>BigDecimal</code> as though a <code>String</code> had been constructed from the character
+     * array (or a subarray of that array) and the {@link #BigDecimal(java.lang.String)} constructor had then been used.
+     * The first parameter must not be <code>null</code>, and the subarray must be wholly contained within it.
+     * <p>
+     * Using this constructor is faster than using the <code>BigDecimal(String)</code> constructor if the string is
+     * already available within a character array.
+     * 
+     * @param inchars The <code>char[]</code> array containing the number to be converted.
+     * @param offset The <code>int</code> offset into the array of the start of the number to be converted.
+     * @param length The <code>int</code> length of the number.
+     * @throws NumberFormatException If the parameter is not a valid number for any reason.
+     * @stable ICU 2.0
+     */
+
+    public BigDecimal(char inchars[], int offset, int length) {
+        super();
+        boolean exotic;
+        boolean hadexp;
+        int d;
+        int dotoff;
+        int last;
+        int i = 0;
+        char si = 0;
+        boolean eneg = false;
+        int k = 0;
+        int elen = 0;
+        int j = 0;
+        char sj = 0;
+        int dvalue = 0;
+        int mag = 0;
+        // This is the primary constructor; all incoming strings end up
+        // here; it uses explicit (inline) parsing for speed and to avoid
+        // generating intermediate (temporary) objects of any kind.
+        // 1998.06.25: exponent form built only if E/e in string
+        // 1998.06.25: trailing zeros not removed for zero
+        // 1999.03.06: no embedded blanks; allow offset and length
+        if (length <= 0)
+            bad(inchars); // bad conversion (empty string)
+        // [bad offset will raise array bounds exception]
+
+        /* Handle and step past sign */
+        ind = ispos; // assume positive
+        if (inchars[offset] == ('-')) {
+            length--;
+            if (length == 0)
+                bad(inchars); // nothing after sign
+            ind = isneg;
+            offset++;
+        } else if (inchars[offset] == ('+')) {
+            length--;
+            if (length == 0)
+                bad(inchars); // nothing after sign
+            offset++;
+        }
+
+        /* We're at the start of the number */
+        exotic = false; // have extra digits
+        hadexp = false; // had explicit exponent
+        d = 0; // count of digits found
+        dotoff = -1; // offset where dot was found
+        last = -1; // last character of mantissa
+        {
+            int $1 = length;
+            i = offset;
+            i: for (; $1 > 0; $1--, i++) {
+                si = inchars[i];
+                if (si >= '0') // test for Arabic digit
+                    if (si <= '9') {
+                        last = i;
+                        d++; // still in mantissa
+                        continue i;
+                    }
+                if (si == '.') { // record and ignore
+                    if (dotoff >= 0)
+                        bad(inchars); // two dots
+                    dotoff = i - offset; // offset into mantissa
+                    continue i;
+                }
+                if (si != 'e')
+                    if (si != 'E') { // expect an extra digit
+                        if ((!(Character.isDigit(si))))
+                            bad(inchars); // not a number
+                        // defer the base 10 check until later to avoid extra method call
+                        exotic = true; // will need conversion later
+                        last = i;
+                        d++; // still in mantissa
+                        continue i;
+                    }
+                /* Found 'e' or 'E' -- now process explicit exponent */
+                // 1998.07.11: sign no longer required
+                if ((i - offset) > (length - 2))
+                    bad(inchars); // no room for even one digit
+                eneg = false;
+                if ((inchars[i + 1]) == ('-')) {
+                    eneg = true;
+                    k = i + 2;
+                } else if ((inchars[i + 1]) == ('+'))
+                    k = i + 2;
+                else
+                    k = i + 1;
+                // k is offset of first expected digit
+                elen = length - ((k - offset)); // possible number of digits
+                if ((elen == 0) | (elen > 9))
+                    bad(inchars); // 0 or more than 9 digits
+                {
+                    int $2 = elen;
+                    j = k;
+                    for (; $2 > 0; $2--, j++) {
+                        sj = inchars[j];
+                        if (sj < '0')
+                            bad(inchars); // always bad
+                        if (sj > '9') { // maybe an exotic digit
+                            if ((!(Character.isDigit(sj))))
+                                bad(inchars); // not a number
+                            dvalue = Character.digit(sj, 10); // check base
+                            if (dvalue < 0)
+                                bad(inchars); // not base 10
+                        } else
+                            dvalue = ((int) (sj)) - ((int) ('0'));
+                        exp = (exp * 10) + dvalue;
+                    }
+                }/* j */
+                if (eneg)
+                    exp = -exp; // was negative
+                hadexp = true; // remember we had one
+                break i; // we are done
+            }
+        }/* i */
+
+        /* Here when all inspected */
+        if (d == 0)
+            bad(inchars); // no mantissa digits
+        if (dotoff >= 0)
+            exp = (exp + dotoff) - d; // adjust exponent if had dot
+
+        /* strip leading zeros/dot (leave final if all 0's) */
+        {
+            int $3 = last - 1;
+            i = offset;
+            i: for (; i <= $3; i++) {
+                si = inchars[i];
+                if (si == '0') {
+                    offset++;
+                    dotoff--;
+                    d--;
+                } else if (si == '.') {
+                    offset++; // step past dot
+                    dotoff--;
+                } else if (si <= '9')
+                    break i;/* non-0 */
+                else {/* exotic */
+                    if ((Character.digit(si, 10)) != 0)
+                        break i; // non-0 or bad
+                    // is 0 .. strip like '0'
+                    offset++;
+                    dotoff--;
+                    d--;
+                }
+            }
+        }/* i */
+
+        /* Create the mantissa array */
+        mant = new byte[d]; // we know the length
+        j = offset; // input offset
+        if (exotic) {
+            do { // slow: check for exotica
+                {
+                    int $4 = d;
+                    i = 0;
+                    for (; $4 > 0; $4--, i++) {
+                        if (i == dotoff)
+                            j++; // at dot
+                        sj = inchars[j];
+                        if (sj <= '9')
+                            mant[i] = (byte) (((int) (sj)) - ((int) ('0')));/* easy */
+                        else {
+                            dvalue = Character.digit(sj, 10);
+                            if (dvalue < 0)
+                                bad(inchars); // not a number after all
+                            mant[i] = (byte) dvalue;
+                        }
+                        j++;
+                    }
+                }/* i */
+            } while (false);
+        }/* exotica */
+        else {
+            do {
+                {
+                    int $5 = d;
+                    i = 0;
+                    for (; $5 > 0; $5--, i++) {
+                        if (i == dotoff)
+                            j++;
+                        mant[i] = (byte) (((int) (inchars[j])) - ((int) ('0')));
+                        j++;
+                    }
+                }/* i */
+            } while (false);
+        }/* simple */
+
+        /* Looks good. Set the sign indicator and form, as needed. */
+        // Trailing zeros are preserved
+        // The rule here for form is:
+        // If no E-notation, then request plain notation
+        // Otherwise act as though add(0,DEFAULT) and request scientific notation
+        // [form is already PLAIN]
+        if (mant[0] == 0) {
+            ind = iszero; // force to show zero
+            // negative exponent is significant (e.g., -3 for 0.000) if plain
+            if (exp > 0)
+                exp = 0; // positive exponent can be ignored
+            if (hadexp) { // zero becomes single digit from add
+                mant = ZERO.mant;
+                exp = 0;
+            }
+        } else { // non-zero
+            // [ind was set earlier]
+            // now determine form
+            if (hadexp) {
+                form = (byte) com.ibm.icu.math.MathContext.SCIENTIFIC;
+                // 1999.06.29 check for overflow
+                mag = (exp + mant.length) - 1; // true exponent in scientific notation
+                if ((mag < MinExp) | (mag > MaxExp))
+                    bad(inchars);
+            }
+        }
+        // say 'BD(c[]): mant[0] mantlen exp ind form:' mant[0] mant.length exp ind form
+        return;
+    }
+
+    /**
+     * Constructs a <code>BigDecimal</code> object directly from a <code>double</code>.
+     * <p>
+     * Constructs a <code>BigDecimal</code> which is the exact decimal representation of the 64-bit signed binary
+     * floating point parameter.
+     * <p>
+     * Note that this constructor it an exact conversion; it does not give the same result as converting <code>num
+     * </code> to a <code>String</code> using the <code>Double.toString()</code> method and then using the
+     * {@link #BigDecimal(java.lang.String)} constructor. To get that result, use the static {@link #valueOf(double)}
+     * method to construct a <code>BigDecimal</code> from a <code>double</code>.
+     * 
+     * @param num The <code>double</code> to be converted.
+     * @throws NumberFormatException If the parameter is infinite or not a number.
+     * @stable ICU 2.0
+     */
+
+    public BigDecimal(double num) {
+        // 1999.03.06: use exactly the old algorithm
+        // 2000.01.01: note that this constructor does give an exact result,
+        // so perhaps it should not be deprecated
+        // 2000.06.18: no longer deprecated
+        this((new java.math.BigDecimal(num)).toString());
+        return;
+    }
+
+    /**
+     * Constructs a <code>BigDecimal</code> object directly from a <code>int</code>.
+     * <p>
+     * Constructs a <code>BigDecimal</code> which is the exact decimal representation of the 32-bit signed binary
+     * integer parameter. The <code>BigDecimal</code> will contain only decimal digits, prefixed with a leading minus
+     * sign (hyphen) if the parameter is negative. A leading zero will be present only if the parameter is zero.
+     * 
+     * @param num The <code>int</code> to be converted.
+     * @stable ICU 2.0
+     */
+
+    public BigDecimal(int num) {
+        super();
+        int mun;
+        int i = 0;
+        // We fastpath commoners
+        if (num <= 9)
+            if (num >= (-9)) {
+                do {
+                    // very common single digit case
+                    {/* select */
+                        if (num == 0) {
+                            mant = ZERO.mant;
+                            ind = iszero;
+                        } else if (num == 1) {
+                            mant = ONE.mant;
+                            ind = ispos;
+                        } else if (num == (-1)) {
+                            mant = ONE.mant;
+                            ind = isneg;
+                        } else {
+                            {
+                                mant = new byte[1];
+                                if (num > 0) {
+                                    mant[0] = (byte) num;
+                                    ind = ispos;
+                                } else { // num<-1
+                                    mant[0] = (byte) -num;
+                                    ind = isneg;
+                                }
+                            }
+                        }
+                    }
+                    return;
+                } while (false);
+            }/* singledigit */
+
+        /* We work on negative numbers so we handle the most negative number */
+        if (num > 0) {
+            ind = ispos;
+            num = -num;
+        } else
+            ind = isneg;/* negative */// [0 case already handled]
+        // [it is quicker, here, to pre-calculate the length with
+        // one loop, then allocate exactly the right length of byte array,
+        // then re-fill it with another loop]
+        mun = num; // working copy
+        {
+            i = 9;
+            i: for (;; i--) {
+                mun = mun / 10;
+                if (mun == 0)
+                    break i;
+            }
+        }/* i */
+        // i is the position of the leftmost digit placed
+        mant = new byte[10 - i];
+        {
+            i = (10 - i) - 1;
+            i: for (;; i--) {
+                mant[i] = (byte) -(((byte) (num % 10)));
+                num = num / 10;
+                if (num == 0)
+                    break i;
+            }
+        }/* i */
+        return;
+    }
+
+    /**
+     * Constructs a <code>BigDecimal</code> object directly from a <code>long</code>.
+     * <p>
+     * Constructs a <code>BigDecimal</code> which is the exact decimal representation of the 64-bit signed binary
+     * integer parameter. The <code>BigDecimal</code> will contain only decimal digits, prefixed with a leading minus
+     * sign (hyphen) if the parameter is negative. A leading zero will be present only if the parameter is zero.
+     * 
+     * @param num The <code>long</code> to be converted.
+     * @stable ICU 2.0
+     */
+
+    public BigDecimal(long num) {
+        super();
+        long mun;
+        int i = 0;
+        // Not really worth fastpathing commoners in this constructor [also,
+        // we use this to construct the static constants].
+        // This is much faster than: this(String.valueOf(num).toCharArray())
+        /* We work on negative num so we handle the most negative number */
+        if (num > 0) {
+            ind = ispos;
+            num = -num;
+        } else if (num == 0)
+            ind = iszero;
+        else
+            ind = isneg;/* negative */
+        mun = num;
+        {
+            i = 18;
+            i: for (;; i--) {
+                mun = mun / 10;
+                if (mun == 0)
+                    break i;
+            }
+        }/* i */
+        // i is the position of the leftmost digit placed
+        mant = new byte[19 - i];
+        {
+            i = (19 - i) - 1;
+            i: for (;; i--) {
+                mant[i] = (byte) -(((byte) (num % 10)));
+                num = num / 10;
+                if (num == 0)
+                    break i;
+            }
+        }/* i */
+        return;
+    }
+
+    /**
+     * Constructs a <code>BigDecimal</code> object from a <code>String</code>.
+     * <p>
+     * Constructs a <code>BigDecimal</code> from the parameter, which must not be <code>null</code> and must represent a
+     * valid <i>number</i>, as described formally in the documentation referred to {@link BigDecimal above}.
+     * <p>
+     * In summary, numbers in <code>String</code> form must have at least one digit, may have a leading sign, may have a
+     * decimal point, and exponential notation may be used. They follow conventional syntax, and may not contain blanks.
+     * <p>
+     * Some valid strings from which a <code>BigDecimal</code> might be constructed are:
+     * 
+     * <pre>
+     * 
+     * "0" -- Zero "12" -- A whole number "-76" -- A signed whole number "12.70" -- Some decimal places "+0.003" -- Plus
+     * sign is allowed "17." -- The same as 17 ".5" -- The same as 0.5 "4E+9" -- Exponential notation "0.73e-7" --
+     * Exponential notation
+     * 
+     * </pre>
+     * <p>
+     * (Exponential notation means that the number includes an optional sign and a power of ten following an
+     * '</code>E</code>' that indicates how the decimal point will be shifted. Thus the <code>"4E+9"</code> above is
+     * just a short way of writing <code>4000000000</code>, and the <code>"0.73e-7"</code> is short for <code>
+     * 0.000000073</code>.)
+     * <p>
+     * The <code>BigDecimal</code> constructed from the String is in a standard form, with no blanks, as though the
+     * {@link #add(BigDecimal)} method had been used to add zero to the number with unlimited precision. If the string
+     * uses exponential notation (that is, includes an <code>e</code> or an <code>E</code>), then the <code>BigDecimal
+     * </code> number will be expressed in scientific notation (where the power of ten is adjusted so there is a single
+     * non-zero digit to the left of the decimal point); in this case if the number is zero then it will be expressed as
+     * the single digit 0, and if non-zero it will have an exponent unless that exponent would be 0. The exponent must
+     * fit in nine digits both before and after it is expressed in scientific notation.
+     * <p>
+     * Any digits in the parameter must be decimal; that is, <code>Character.digit(c, 10)</code> (where </code>c</code>
+     * is the character in question) would not return -1.
+     * 
+     * @param string The <code>String</code> to be converted.
+     * @throws NumberFormatException If the parameter is not a valid number.
+     * @stable ICU 2.0
+     */
+
+    public BigDecimal(java.lang.String string) {
+        this(string.toCharArray(), 0, string.length());
+        return;
+    }
+
+    /* <sgml> Make a default BigDecimal object for local use. </sgml> */
+
+    private BigDecimal() {
+        super();
+        return;
+    }
+
+    /* ---------------------------------------------------------------- */
+    /* Operator methods [methods which take a context parameter] */
+    /* ---------------------------------------------------------------- */
+
+    /**
+     * Returns a plain <code>BigDecimal</code> whose value is the absolute value of this <code>BigDecimal</code>.
+     * <p>
+     * The same as {@link #abs(MathContext)}, where the context is <code>new MathContext(0, MathContext.PLAIN)</code>.
+     * <p>
+     * The length of the decimal part (the scale) of the result will be <code>this.scale()</code>
+     * 
+     * @return A <code>BigDecimal</code> whose value is the absolute value of this <code>BigDecimal</code>.
+     * @stable ICU 2.0
+     */
+
+    public com.ibm.icu.math.BigDecimal abs() {
+        return this.abs(plainMC);
+    }
+
+    /**
+     * Returns a <code>BigDecimal</code> whose value is the absolute value of this <code>BigDecimal</code>.
+     * <p>
+     * If the current object is zero or positive, then the same result as invoking the {@link #plus(MathContext)} method
+     * with the same parameter is returned. Otherwise, the same result as invoking the {@link #negate(MathContext)}
+     * method with the same parameter is returned.
+     * 
+     * @param set The <code>MathContext</code> arithmetic settings.
+     * @return A <code>BigDecimal</code> whose value is the absolute value of this <code>BigDecimal</code>.
+     * @stable ICU 2.0
+     */
+
+    public com.ibm.icu.math.BigDecimal abs(com.ibm.icu.math.MathContext set) {
+        if (this.ind == isneg)
+            return this.negate(set);
+        return this.plus(set);
+    }
+
+    /**
+     * Returns a plain <code>BigDecimal</code> whose value is <code>this+rhs</code>, using fixed point arithmetic.
+     * <p>
+     * The same as {@link #add(BigDecimal, MathContext)}, where the <code>BigDecimal</code> is <code>rhs</code>, and the
+     * context is <code>new MathContext(0, MathContext.PLAIN)</code>.
+     * <p>
+     * The length of the decimal part (the scale) of the result will be the maximum of the scales of the two operands.
+     * 
+     * @param rhs The <code>BigDecimal</code> for the right hand side of the addition.
+     * @return A <code>BigDecimal</code> whose value is <code>this+rhs</code>, using fixed point arithmetic.
+     * @stable ICU 2.0
+     */
+
+    public com.ibm.icu.math.BigDecimal add(com.ibm.icu.math.BigDecimal rhs) {
+        return this.add(rhs, plainMC);
+    }
+
+    /**
+     * Returns a <code>BigDecimal</code> whose value is <code>this+rhs</code>.
+     * <p>
+     * Implements the addition (<b><code>+</code></b>) operator (as defined in the decimal documentation, see
+     * {@link BigDecimal class header}), and returns the result as a <code>BigDecimal</code> object.
+     * 
+     * @param rhs The <code>BigDecimal</code> for the right hand side of the addition.
+     * @param set The <code>MathContext</code> arithmetic settings.
+     * @return A <code>BigDecimal</code> whose value is <code>this+rhs</code>.
+     * @stable ICU 2.0
+     */
+
+    public com.ibm.icu.math.BigDecimal add(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) {
+        com.ibm.icu.math.BigDecimal lhs;
+        int reqdig;
+        com.ibm.icu.math.BigDecimal res;
+        byte usel[];
+        int usellen;
+        byte user[];
+        int userlen;
+        int newlen = 0;
+        int tlen = 0;
+        int mult = 0;
+        byte t[] = null;
+        int ia = 0;
+        int ib = 0;
+        int ea = 0;
+        int eb = 0;
+        byte ca = 0;
+        byte cb = 0;
+        /* determine requested digits and form */
+        if (set.lostDigits)
+            checkdigits(rhs, set.digits);
+        lhs = this; // name for clarity and proxy
+
+        /* Quick exit for add floating 0 */
+        // plus() will optimize to return same object if possible
+        if (lhs.ind == 0)
+            if (set.form != com.ibm.icu.math.MathContext.PLAIN)
+                return rhs.plus(set);
+        if (rhs.ind == 0)
+            if (set.form != com.ibm.icu.math.MathContext.PLAIN)
+                return lhs.plus(set);
+
+        /* Prepare numbers (round, unless unlimited precision) */
+        reqdig = set.digits; // local copy (heavily used)
+        if (reqdig > 0) {
+            if (lhs.mant.length > reqdig)
+                lhs = clone(lhs).round(set);
+            if (rhs.mant.length > reqdig)
+                rhs = clone(rhs).round(set);
+            // [we could reuse the new LHS for result in this case]
+        }
+
+        res = new com.ibm.icu.math.BigDecimal(); // build result here
+
+        /*
+         * Now see how much we have to pad or truncate lhs or rhs in order to align the numbers. If one number is much
+         * larger than the other, then the smaller cannot affect the answer [but we may still need to pad with up to
+         * DIGITS trailing zeros].
+         */
+        // Note sign may be 0 if digits (reqdig) is 0
+        // usel and user will be the byte arrays passed to the adder; we'll
+        // use them on all paths except quick exits
+        usel = lhs.mant;
+        usellen = lhs.mant.length;
+        user = rhs.mant;
+        userlen = rhs.mant.length;
+        {
+            do {/* select */
+                if (lhs.exp == rhs.exp) {/* no padding needed */
+                    // This is the most common, and fastest, path
+                    res.exp = lhs.exp;
+                } else if (lhs.exp > rhs.exp) { // need to pad lhs and/or truncate rhs
+                    newlen = (usellen + lhs.exp) - rhs.exp;
+                    /*
+                     * If, after pad, lhs would be longer than rhs by digits+1 or more (and digits>0) then rhs cannot
+                     * affect answer, so we only need to pad up to a length of DIGITS+1.
+                     */
+                    if (newlen >= ((userlen + reqdig) + 1))
+                        if (reqdig > 0) {
+                            // LHS is sufficient
+                            res.mant = usel;
+                            res.exp = lhs.exp;
+                            res.ind = lhs.ind;
+                            if (usellen < reqdig) { // need 0 padding
+                                res.mant = extend(lhs.mant, reqdig);
+                                res.exp = res.exp - ((reqdig - usellen));
+                            }
+                            return res.finish(set, false);
+                        }
+                    // RHS may affect result
+                    res.exp = rhs.exp; // expected final exponent
+                    if (newlen > (reqdig + 1))
+                        if (reqdig > 0) {
+                            // LHS will be max; RHS truncated
+                            tlen = (newlen - reqdig) - 1; // truncation length
+                            userlen = userlen - tlen;
+                            res.exp = res.exp + tlen;
+                            newlen = reqdig + 1;
+                        }
+                    if (newlen > usellen)
+                        usellen = newlen; // need to pad LHS
+                } else { // need to pad rhs and/or truncate lhs
+                    newlen = (userlen + rhs.exp) - lhs.exp;
+                    if (newlen >= ((usellen + reqdig) + 1))
+                        if (reqdig > 0) {
+                            // RHS is sufficient
+                            res.mant = user;
+                            res.exp = rhs.exp;
+                            res.ind = rhs.ind;
+                            if (userlen < reqdig) { // need 0 padding
+                                res.mant = extend(rhs.mant, reqdig);
+                                res.exp = res.exp - ((reqdig - userlen));
+                            }
+                            return res.finish(set, false);
+                        }
+                    // LHS may affect result
+                    res.exp = lhs.exp; // expected final exponent
+                    if (newlen > (reqdig + 1))
+                        if (reqdig > 0) {
+                            // RHS will be max; LHS truncated
+                            tlen = (newlen - reqdig) - 1; // truncation length
+                            usellen = usellen - tlen;
+                            res.exp = res.exp + tlen;
+                            newlen = reqdig + 1;
+                        }
+                    if (newlen > userlen)
+                        userlen = newlen; // need to pad RHS
+                }
+            } while (false);
+        }/* padder */
+
+        /* OK, we have aligned mantissas. Now add or subtract. */
+        // 1998.06.27 Sign may now be 0 [e.g., 0.000] .. treat as positive
+        // 1999.05.27 Allow for 00 on lhs [is not larger than 2 on rhs]
+        // 1999.07.10 Allow for 00 on rhs [is not larger than 2 on rhs]
+        if (lhs.ind == iszero)
+            res.ind = ispos;
+        else
+            res.ind = lhs.ind; // likely sign, all paths
+        if (((lhs.ind == isneg) ? 1 : 0) == ((rhs.ind == isneg) ? 1 : 0)) // same sign, 0 non-negative
+            mult = 1;
+        else {
+            do { // different signs, so subtraction is needed
+                mult = -1; // will cause subtract
+                /*
+                 * Before we can subtract we must determine which is the larger, as our add/subtract routine only
+                 * handles non-negative results so we may need to swap the operands.
+                 */
+                {
+                    do {/* select */
+                        if (rhs.ind == iszero) {
+                            // original A bigger
+                        } else if ((usellen < userlen) | (lhs.ind == iszero)) { // original B bigger
+                            t = usel;
+                            usel = user;
+                            user = t; // swap
+                            tlen = usellen;
+                            usellen = userlen;
+                            userlen = tlen; // ..
+                            res.ind = (byte) -res.ind; // and set sign
+                        } else if (usellen > userlen) {
+                            // original A bigger
+                        } else {
+                            {/* logical lengths the same */// need compare
+                                /* may still need to swap: compare the strings */
+                                ia = 0;
+                                ib = 0;
+                                ea = usel.length - 1;
+                                eb = user.length - 1;
+                                {
+                                    compare: for (;;) {
+                                        if (ia <= ea)
+                                            ca = usel[ia];
+                                        else {
+                                            if (ib > eb) {/* identical */
+                                                if (set.form != com.ibm.icu.math.MathContext.PLAIN)
+                                                    return ZERO;
+                                                // [if PLAIN we must do the subtract, in case of 0.000 results]
+                                                break compare;
+                                            }
+                                            ca = (byte) 0;
+                                        }
+                                        if (ib <= eb)
+                                            cb = user[ib];
+                                        else
+                                            cb = (byte) 0;
+                                        if (ca != cb) {
+                                            if (ca < cb) {/* swap needed */
+                                                t = usel;
+                                                usel = user;
+                                                user = t; // swap
+                                                tlen = usellen;
+                                                usellen = userlen;
+                                                userlen = tlen; // ..
+                                                res.ind = (byte) -res.ind;
+                                            }
+                                            break compare;
+                                        }
+                                        /* mantissas the same, so far */
+                                        ia++;
+                                        ib++;
+                                    }
+                                }/* compare */
+                            } // lengths the same
+                        }
+                    } while (false);
+                }/* swaptest */
+            } while (false);
+        }/* signdiff */
+
+        /* here, A is > B if subtracting */
+        // add [A+B*1] or subtract [A+(B*-1)]
+        res.mant = byteaddsub(usel, usellen, user, userlen, mult, false);
+        // [reuse possible only after chop; accounting makes not worthwhile]
+
+        // Finish() rounds before stripping leading 0's, then sets form, etc.
+        return res.finish(set, false);
+    }
+
+    /**
+     * Compares this <code>BigDecimal</code> to another, using unlimited precision.
+     * <p>
+     * The same as {@link #compareTo(BigDecimal, MathContext)}, where the <code>BigDecimal</code> is <code>rhs</code>,
+     * and the context is <code>new MathContext(0, MathContext.PLAIN)</code>.
+     * 
+     * @param rhs The <code>BigDecimal</code> for the right hand side of the comparison.
+     * @return An <code>int</code> whose value is -1, 0, or 1 as <code>this</code> is numerically less than, equal to,
+     *         or greater than <code>rhs</code>.
+     * @stable ICU 2.0
+     */
+
+    public int compareTo(com.ibm.icu.math.BigDecimal rhs) {
+        return this.compareTo(rhs, plainMC);
+    }
+
+    /**
+     * Compares this <code>BigDecimal</code> to another.
+     * <p>
+     * Implements numeric comparison, (as defined in the decimal documentation, see {@link BigDecimal class header}),
+     * and returns a result of type <code>int</code>.
+     * <p>
+     * The result will be:
+     * <table cellpadding=2>
+     * <tr>
+     * <td align=right><b>-1</b></td> <td>if the current object is less than the first parameter</td>
+     * </tr>
+     * <tr>
+     * <td align=right><b>0</b></td> <td>if the current object is equal to the first parameter</td>
+     * </tr>
+     * <tr>
+     * <td align=right><b>1</b></td> <td>if the current object is greater than the first parameter.</td>
+     * </tr>
+     * </table>
+     * <p>
+     * A {@link #compareTo(BigDecimal)} method is also provided.
+     * 
+     * @param rhs The <code>BigDecimal</code> for the right hand side of the comparison.
+     * @param set The <code>MathContext</code> arithmetic settings.
+     * @return An <code>int</code> whose value is -1, 0, or 1 as <code>this</code> is numerically less than, equal to,
+     *         or greater than <code>rhs</code>.
+     * @stable ICU 2.0
+     */
+
+    public int compareTo(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) {
+        int thislength = 0;
+        int i = 0;
+        com.ibm.icu.math.BigDecimal newrhs;
+        // rhs=null will raise NullPointerException, as per Comparable interface
+        if (set.lostDigits)
+            checkdigits(rhs, set.digits);
+        // [add will recheck in slowpath cases .. but would report -rhs]
+        if ((this.ind == rhs.ind) & (this.exp == rhs.exp)) {
+            /* sign & exponent the same [very common] */
+            thislength = this.mant.length;
+            if (thislength < rhs.mant.length)
+                return (byte) -this.ind;
+            if (thislength > rhs.mant.length)
+                return this.ind;
+            /*
+             * lengths are the same; we can do a straight mantissa compare unless maybe rounding [rounding is very
+             * unusual]
+             */
+            if ((thislength <= set.digits) | (set.digits == 0)) {
+                {
+                    int $6 = thislength;
+                    i = 0;
+                    for (; $6 > 0; $6--, i++) {
+                        if (this.mant[i] < rhs.mant[i])
+                            return (byte) -this.ind;
+                        if (this.mant[i] > rhs.mant[i])
+                            return this.ind;
+                    }
+                }/* i */
+                return 0; // identical
+            }
+            /* drop through for full comparison */
+        } else {
+            /* More fastpaths possible */
+            if (this.ind < rhs.ind)
+                return -1;
+            if (this.ind > rhs.ind)
+                return 1;
+        }
+        /* carry out a subtract to make the comparison */
+        newrhs = clone(rhs); // safe copy
+        newrhs.ind = (byte) -newrhs.ind; // prepare to subtract
+        return this.add(newrhs, set).ind; // add, and return sign of result
+    }
+
+    /**
+     * Returns a plain <code>BigDecimal</code> whose value is <code>this/rhs</code>, using fixed point arithmetic.
+     * <p>
+     * The same as {@link #divide(BigDecimal, int)}, where the <code>BigDecimal</code> is <code>rhs</code>, and the
+     * rounding mode is {@link MathContext#ROUND_HALF_UP}.
+     * 
+     * The length of the decimal part (the scale) of the result will be the same as the scale of the current object, if
+     * the latter were formatted without exponential notation.
+     * 
+     * @param rhs The <code>BigDecimal</code> for the right hand side of the division.
+     * @return A plain <code>BigDecimal</code> whose value is <code>this/rhs</code>, using fixed point arithmetic.
+     * @throws ArithmeticException If <code>rhs</code> is zero.
+     * @stable ICU 2.0
+     */
+
+    public com.ibm.icu.math.BigDecimal divide(com.ibm.icu.math.BigDecimal rhs) {
+        return this.dodivide('D', rhs, plainMC, -1);
+    }
+
+    /**
+     * Returns a plain <code>BigDecimal</code> whose value is <code>this/rhs</code>, using fixed point arithmetic and a
+     * rounding mode.
+     * <p>
+     * The same as {@link #divide(BigDecimal, int, int)}, where the <code>BigDecimal</code> is <code>rhs</code>, and the
+     * second parameter is <code>this.scale()</code>, and the third is <code>round</code>.
+     * <p>
+     * The length of the decimal part (the scale) of the result will therefore be the same as the scale of the current
+     * object, if the latter were formatted without exponential notation.
+     * <p>
+     * 
+     * @param rhs The <code>BigDecimal</code> for the right hand side of the division.
+     * @param round The <code>int</code> rounding mode to be used for the division (see the {@link MathContext} class).
+     * @return A plain <code>BigDecimal</code> whose value is <code>this/rhs</code>, using fixed point arithmetic and
+     *         the specified rounding mode.
+     * @throws IllegalArgumentException if <code>round</code> is not a valid rounding mode.
+     * @throws ArithmeticException if <code>rhs</code> is zero.
+     * @throws ArithmeticException if <code>round</code> is {@link MathContext#ROUND_UNNECESSARY} and <code>this.scale()</code> is insufficient to represent the result exactly.
+     * @stable ICU 2.0
+     */
+
+    public com.ibm.icu.math.BigDecimal divide(com.ibm.icu.math.BigDecimal rhs, int round) {
+        com.ibm.icu.math.MathContext set;
+        set = new com.ibm.icu.math.MathContext(0, com.ibm.icu.math.MathContext.PLAIN, false, round); // [checks round,
+                                                                                                     // too]
+        return this.dodivide('D', rhs, set, -1); // take scale from LHS
+    }
+
+    /**
+     * Returns a plain <code>BigDecimal</code> whose value is <code>this/rhs</code>, using fixed point arithmetic and a
+     * given scale and rounding mode.
+     * <p>
+     * The same as {@link #divide(BigDecimal, MathContext)}, where the <code>BigDecimal</code> is <code>rhs</code>,
+     * <code>new MathContext(0, MathContext.PLAIN, false, round)</code>, except that the length of the decimal part (the
+     * scale) to be used for the result is explicit rather than being taken from <code>this</code>.
+     * <p>
+     * The length of the decimal part (the scale) of the result will be the same as the scale of the current object, if
+     * the latter were formatted without exponential notation.
+     * <p>
+     * 
+     * @param rhs The <code>BigDecimal</code> for the right hand side of the division.
+     * @param scale The <code>int</code> scale to be used for the result.
+     * @param round The <code>int</code> rounding mode to be used for the division (see the {@link MathContext} class).
+     * @return A plain <code>BigDecimal</code> whose value is <code>this/rhs</code>, using fixed point arithmetic and
+     *         the specified rounding mode.
+     * @throws IllegalArgumentException if <code>round</code> is not a valid rounding mode.
+     * @throws ArithmeticException if <code>rhs</code> is zero.
+     * @throws ArithmeticException if <code>scale</code> is negative.
+     * @throws ArithmeticException if <code>round</code> is {@link MathContext#ROUND_UNNECESSARY} and <code>scale</code> is insufficient
+     *             to represent the result exactly.
+     * @stable ICU 2.0
+     */
+
+    public com.ibm.icu.math.BigDecimal divide(com.ibm.icu.math.BigDecimal rhs, int scale, int round) {
+        com.ibm.icu.math.MathContext set;
+        if (scale < 0)
+            throw new java.lang.ArithmeticException("Negative scale:" + " " + scale);
+        set = new com.ibm.icu.math.MathContext(0, com.ibm.icu.math.MathContext.PLAIN, false, round); // [checks round]
+        return this.dodivide('D', rhs, set, scale);
+    }
+
+    /**
+     * Returns a <code>BigDecimal</code> whose value is <code>this/rhs</code>.
+     * <p>
+     * Implements the division (<b><code>/</code></b>) operator (as defined in the decimal documentation, see
+     * {@link BigDecimal class header}), and returns the result as a <code>BigDecimal</code> object.
+     * 
+     * @param rhs The <code>BigDecimal</code> for the right hand side of the division.
+     * @param set The <code>MathContext</code> arithmetic settings.
+     * @return A <code>BigDecimal</code> whose value is <code>this/rhs</code>.
+     * @throws ArithmeticException if <code>rhs</code> is zero.
+     * @stable ICU 2.0
+     */
+
+    public com.ibm.icu.math.BigDecimal divide(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) {
+        return this.dodivide('D', rhs, set, -1);
+    }
+
+    /**
+     * Returns a plain <code>BigDecimal</code> whose value is the integer part of <code>this/rhs</code>.
+     * <p>
+     * The same as {@link #divideInteger(BigDecimal, MathContext)}, where the <code>BigDecimal</code> is <code>rhs
+     * </code>, and the context is <code>new MathContext(0, MathContext.PLAIN)</code>.
+     * 
+     * @param rhs The <code>BigDecimal</code> for the right hand side of the integer division.
+     * @return A <code>BigDecimal</code> whose value is the integer part of <code>this/rhs</code>.
+     * @throws ArithmeticException if <code>rhs</code> is zero.
+     * @stable ICU 2.0
+     */
+
+    public com.ibm.icu.math.BigDecimal divideInteger(com.ibm.icu.math.BigDecimal rhs) {
+        // scale 0 to drop .000 when plain
+        return this.dodivide('I', rhs, plainMC, 0);
+    }
+
+    /**
+     * Returns a <code>BigDecimal</code> whose value is the integer part of <code>this/rhs</code>.
+     * <p>
+     * Implements the integer division operator (as defined in the decimal documentation, see {@link BigDecimal class
+     * header}), and returns the result as a <code>BigDecimal</code> object.
+     * 
+     * @param rhs The <code>BigDecimal</code> for the right hand side of the integer division.
+     * @param set The <code>MathContext</code> arithmetic settings.
+     * @return A <code>BigDecimal</code> whose value is the integer part of <code>this/rhs</code>.
+     * @throws ArithmeticException if <code>rhs</code> is zero.
+     * @throws ArithmeticException if the result will not fit in the number of digits specified for the context.
+     * @stable ICU 2.0
+     */
+
+    public com.ibm.icu.math.BigDecimal divideInteger(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) {
+        // scale 0 to drop .000 when plain
+        return this.dodivide('I', rhs, set, 0);
+    }
+
+    /**
+     * Returns a plain <code>BigDecimal</code> whose value is the maximum of <code>this</code> and <code>rhs</code>.
+     * <p>
+     * The same as {@link #max(BigDecimal, MathContext)}, where the <code>BigDecimal</code> is <code>rhs</code>, and the
+     * context is <code>new MathContext(0, MathContext.PLAIN)</code>.
+     * 
+     * @param rhs The <code>BigDecimal</code> for the right hand side of the comparison.
+     * @return A <code>BigDecimal</code> whose value is the maximum of <code>this</code> and <code>rhs</code>.
+     * @stable ICU 2.0
+     */
+
+    public com.ibm.icu.math.BigDecimal max(com.ibm.icu.math.BigDecimal rhs) {
+        return this.max(rhs, plainMC);
+    }
+
+    /**
+     * Returns a <code>BigDecimal</code> whose value is the maximum of <code>this</code> and <code>rhs</code>.
+     * <p>
+     * Returns the larger of the current object and the first parameter.
+     * <p>
+     * If calling the {@link #compareTo(BigDecimal, MathContext)} method with the same parameters would return <code>1
+     * </code> or <code>0</code>, then the result of calling the {@link #plus(MathContext)} method on the current object
+     * (using the same <code>MathContext</code> parameter) is returned. Otherwise, the result of calling the
+     * {@link #plus(MathContext)} method on the first parameter object (using the same <code>MathContext</code>
+     * parameter) is returned.
+     * 
+     * @param rhs The <code>BigDecimal</code> for the right hand side of the comparison.
+     * @param set The <code>MathContext</code> arithmetic settings.
+     * @return A <code>BigDecimal</code> whose value is the maximum of <code>this</code> and <code>rhs</code>.
+     * @stable ICU 2.0
+     */
+
+    public com.ibm.icu.math.BigDecimal max(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) {
+        if ((this.compareTo(rhs, set)) >= 0)
+            return this.plus(set);
+        else
+            return rhs.plus(set);
+    }
+
+    /**
+     * Returns a plain <code>BigDecimal</code> whose value is the minimum of <code>this</code> and <code>rhs</code>.
+     * <p>
+     * The same as {@link #min(BigDecimal, MathContext)}, where the <code>BigDecimal</code> is <code>rhs</code>, and the
+     * context is <code>new MathContext(0, MathContext.PLAIN)</code>.
+     * 
+     * @param rhs The <code>BigDecimal</code> for the right hand side of the comparison.
+     * @return A <code>BigDecimal</code> whose value is the minimum of <code>this</code> and <code>rhs</code>.
+     * @stable ICU 2.0
+     */
+
+    public com.ibm.icu.math.BigDecimal min(com.ibm.icu.math.BigDecimal rhs) {
+        return this.min(rhs, plainMC);
+    }
+
+    /**
+     * Returns a <code>BigDecimal</code> whose value is the minimum of <code>this</code> and <code>rhs</code>.
+     * <p>
+     * Returns the smaller of the current object and the first parameter.
+     * <p>
+     * If calling the {@link #compareTo(BigDecimal, MathContext)} method with the same parameters would return <code>-1
+     * </code> or <code>0</code>, then the result of calling the {@link #plus(MathContext)} method on the current object
+     * (using the same <code>MathContext</code> parameter) is returned. Otherwise, the result of calling the
+     * {@link #plus(MathContext)} method on the first parameter object (using the same <code>MathContext</code>
+     * parameter) is returned.
+     * 
+     * @param rhs The <code>BigDecimal</code> for the right hand side of the comparison.
+     * @param set The <code>MathContext</code> arithmetic settings.
+     * @return A <code>BigDecimal</code> whose value is the minimum of <code>this</code> and <code>rhs</code>.
+     * @stable ICU 2.0
+     */
+
+    public com.ibm.icu.math.BigDecimal min(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) {
+        if ((this.compareTo(rhs, set)) <= 0)
+            return this.plus(set);
+        else
+            return rhs.plus(set);
+    }
+
+    /**
+     * Returns a plain <code>BigDecimal</code> whose value is <code>this*rhs</code>, using fixed point arithmetic.
+     * <p>
+     * The same as {@link #add(BigDecimal, MathContext)}, where the <code>BigDecimal</code> is <code>rhs</code>, and the
+     * context is <code>new MathContext(0, MathContext.PLAIN)</code>.
+     * <p>
+     * The length of the decimal part (the scale) of the result will be the sum of the scales of the operands, if they
+     * were formatted without exponential notation.
+     * 
+     * @param rhs The <code>BigDecimal</code> for the right hand side of the multiplication.
+     * @return A <code>BigDecimal</code> whose value is <code>this*rhs</code>, using fixed point arithmetic.
+     * @stable ICU 2.0
+     */
+
+    public com.ibm.icu.math.BigDecimal multiply(com.ibm.icu.math.BigDecimal rhs) {
+        return this.multiply(rhs, plainMC);
+    }
+
+    /**
+     * Returns a <code>BigDecimal</code> whose value is <code>this*rhs</code>.
+     * <p>
+     * Implements the multiplication (<b><code> </code></b>) operator (as defined in the decimal documentation, see
+     * {@link BigDecimal class header}), and returns the result as a <code>BigDecimal</code> object.
+     * 
+     * @param rhs The <code>BigDecimal</code> for the right hand side of the multiplication.
+     * @param set The <code>MathContext</code> arithmetic settings.
+     * @return A <code>BigDecimal</code> whose value is <code>this*rhs</code>.
+     * @stable ICU 2.0
+     */
+
+    public com.ibm.icu.math.BigDecimal multiply(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) {
+        com.ibm.icu.math.BigDecimal lhs;
+        int padding;
+        int reqdig;
+        byte multer[] = null;
+        byte multand[] = null;
+        int multandlen;
+        int acclen = 0;
+        com.ibm.icu.math.BigDecimal res;
+        byte acc[];
+        int n = 0;
+        byte mult = 0;
+        if (set.lostDigits)
+            checkdigits(rhs, set.digits);
+        lhs = this; // name for clarity and proxy
+
+        /* Prepare numbers (truncate, unless unlimited precision) */
+        padding = 0; // trailing 0's to add
+        reqdig = set.digits; // local copy
+        if (reqdig > 0) {
+            if (lhs.mant.length > reqdig)
+                lhs = clone(lhs).round(set);
+            if (rhs.mant.length > reqdig)
+                rhs = clone(rhs).round(set);
+            // [we could reuse the new LHS for result in this case]
+        } else {/* unlimited */
+            // fixed point arithmetic will want every trailing 0; we add these
+            // after the calculation rather than before, for speed.
+            if (lhs.exp > 0)
+                padding = padding + lhs.exp;
+            if (rhs.exp > 0)
+                padding = padding + rhs.exp;
+        }
+
+        // For best speed, as in DMSRCN, we use the shorter number as the
+        // multiplier and the longer as the multiplicand.
+        // 1999.12.22: We used to special case when the result would fit in
+        // a long, but with Java 1.3 this gave no advantage.
+        if (lhs.mant.length < rhs.mant.length) {
+            multer = lhs.mant;
+            multand = rhs.mant;
+        } else {
+            multer = rhs.mant;
+            multand = lhs.mant;
+        }
+
+        /* Calculate how long result byte array will be */
+        multandlen = (multer.length + multand.length) - 1; // effective length
+        // optimize for 75% of the cases where a carry is expected...
+        if ((multer[0] * multand[0]) > 9)
+            acclen = multandlen + 1;
+        else
+            acclen = multandlen;
+
+        /* Now the main long multiplication loop */
+        res = new com.ibm.icu.math.BigDecimal(); // where we'll build result
+        acc = new byte[acclen]; // accumulator, all zeros
+        // 1998.07.01: calculate from left to right so that accumulator goes
+        // to likely final length on first addition; this avoids a one-digit
+        // extension (and object allocation) each time around the loop.
+        // Initial number therefore has virtual zeros added to right.
+        {
+            int $7 = multer.length;
+            n = 0;
+            for (; $7 > 0; $7--, n++) {
+                mult = multer[n];
+                if (mult != 0) { // [optimization]
+                    // accumulate [accumulator is reusable array]
+                    acc = byteaddsub(acc, acc.length, multand, multandlen, mult, true);
+                }
+                // divide multiplicand by 10 for next digit to right
+                multandlen--; // 'virtual length'
+            }
+        }/* n */
+
+        res.ind = (byte) (lhs.ind * rhs.ind); // final sign
+        res.exp = (lhs.exp + rhs.exp) - padding; // final exponent
+        // [overflow is checked by finish]
+
+        /* add trailing zeros to the result, if necessary */
+        if (padding == 0)
+            res.mant = acc;
+        else
+            res.mant = extend(acc, acc.length + padding); // add trailing 0s
+        return res.finish(set, false);
+    }
+
+    /**
+     * Returns a plain <code>BigDecimal</code> whose value is <code>-this</code>.
+     * <p>
+     * The same as {@link #negate(MathContext)}, where the context is <code>new MathContext(0, MathContext.PLAIN)</code>
+     * .
+     * <p>
+     * The length of the decimal part (the scale) of the result will be be <code>this.scale()</code>
+     * 
+     * 
+     * @return A <code>BigDecimal</code> whose value is <code>-this</code>.
+     * @stable ICU 2.0
+     */
+
+    public com.ibm.icu.math.BigDecimal negate() {
+        return this.negate(plainMC);
+    }
+
+    /**
+     * Returns a <code>BigDecimal</code> whose value is <code>-this</code>.
+     * <p>
+     * Implements the negation (Prefix <b><code>-</code></b>) operator (as defined in the decimal documentation, see
+     * {@link BigDecimal class header}), and returns the result as a <code>BigDecimal</code> object.
+     * 
+     * @param set The <code>MathContext</code> arithmetic settings.
+     * @return A <code>BigDecimal</code> whose value is <code>-this</code>.
+     * @stable ICU 2.0
+     */
+
+    public com.ibm.icu.math.BigDecimal negate(com.ibm.icu.math.MathContext set) {
+        com.ibm.icu.math.BigDecimal res;
+        // Originally called minus(), changed to matched Java precedents
+        // This simply clones, flips the sign, and possibly rounds
+        if (set.lostDigits)
+            checkdigits((com.ibm.icu.math.BigDecimal) null, set.digits);
+        res = clone(this); // safe copy
+        res.ind = (byte) -res.ind;
+        return res.finish(set, false);
+    }
+
+    /**
+     * Returns a plain <code>BigDecimal</code> whose value is <code>+this</code>. Note that <code>this</code> is not
+     * necessarily a plain <code>BigDecimal</code>, but the result will always be.
+     * <p>
+     * The same as {@link #plus(MathContext)}, where the context is <code>new MathContext(0, MathContext.PLAIN)</code>.
+     * <p>
+     * The length of the decimal part (the scale) of the result will be be <code>this.scale()</code>
+     * 
+     * @return A <code>BigDecimal</code> whose value is <code>+this</code>.
+     * @stable ICU 2.0
+     */
+
+    public com.ibm.icu.math.BigDecimal plus() {
+        return this.plus(plainMC);
+    }
+
+    /**
+     * Returns a <code>BigDecimal</code> whose value is <code>+this</code>.
+     * <p>
+     * Implements the plus (Prefix <b><code>+</code></b>) operator (as defined in the decimal documentation, see
+     * {@link BigDecimal class header}), and returns the result as a <code>BigDecimal</code> object.
+     * <p>
+     * This method is useful for rounding or otherwise applying a context to a decimal value.
+     * 
+     * @param set The <code>MathContext</code> arithmetic settings.
+     * @return A <code>BigDecimal</code> whose value is <code>+this</code>.
+     * @stable ICU 2.0
+     */
+
+    public com.ibm.icu.math.BigDecimal plus(com.ibm.icu.math.MathContext set) {
+        // This clones and forces the result to the new settings
+        // May return same object
+        if (set.lostDigits)
+            checkdigits((com.ibm.icu.math.BigDecimal) null, set.digits);
+        // Optimization: returns same object for some common cases
+        if (set.form == com.ibm.icu.math.MathContext.PLAIN)
+            if (this.form == com.ibm.icu.math.MathContext.PLAIN) {
+                if (this.mant.length <= set.digits)
+                    return this;
+                if (set.digits == 0)
+                    return this;
+            }
+        return clone(this).finish(set, false);
+    }
+
+    /**
+     * Returns a plain <code>BigDecimal</code> whose value is <code>this**rhs</code>, using fixed point arithmetic.
+     * <p>
+     * The same as {@link #pow(BigDecimal, MathContext)}, where the <code>BigDecimal</code> is <code>rhs</code>, and the
+     * context is <code>new MathContext(0, MathContext.PLAIN)</code>.
+     * <p>
+     * The parameter is the power to which the <code>this</code> will be raised; it must be in the range 0 through
+     * 999999999, and must have a decimal part of zero. Note that these restrictions may be removed in the future, so
+     * they should not be used as a test for a whole number.
+     * <p>
+     * In addition, the power must not be negative, as no <code>MathContext</code> is used and so the result would then
+     * always be 0.
+     * 
+     * @param rhs The <code>BigDecimal</code> for the right hand side of the operation (the power).
+     * @return A <code>BigDecimal</code> whose value is <code>this**rhs</code>, using fixed point arithmetic.
+     * @throws ArithmeticException if <code>rhs</code> is out of range or is not a whole number.
+     * @stable ICU 2.0
+     */
+
+    public com.ibm.icu.math.BigDecimal pow(com.ibm.icu.math.BigDecimal rhs) {
+        return this.pow(rhs, plainMC);
+    }
+
+    // The name for this method is inherited from the precedent set by the
+    // BigInteger and Math classes.
+
+    /**
+     * Returns a <code>BigDecimal</code> whose value is <code>this**rhs</code>.
+     * <p>
+     * Implements the power (<b><code> </code></b>) operator (as defined in the decimal documentation, see
+     * {@link BigDecimal class header}), and returns the result as a <code>BigDecimal</code> object.
+     * <p>
+     * The first parameter is the power to which the <code>this</code> will be raised; it must be in the range
+     * -999999999 through 999999999, and must have a decimal part of zero. Note that these restrictions may be removed
+     * in the future, so they should not be used as a test for a whole number.
+     * <p>
+     * If the <code>digits</code> setting of the <code>MathContext</code> parameter is 0, the power must be zero or
+     * positive.
+     * 
+     * @param rhs The <code>BigDecimal</code> for the right hand side of the operation (the power).
+     * @param set The <code>MathContext</code> arithmetic settings.
+     * @return A <code>BigDecimal</code> whose value is <code>this**rhs</code>.
+     * @throws ArithmeticException if <code>rhs</code> is out of range or is not a whole number.
+     * @stable ICU 2.0
+     */
+
+    public com.ibm.icu.math.BigDecimal pow(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) {
+        int n;
+        com.ibm.icu.math.BigDecimal lhs;
+        int reqdig;
+        int workdigits = 0;
+        int L = 0;
+        com.ibm.icu.math.MathContext workset;
+        com.ibm.icu.math.BigDecimal res;
+        boolean seenbit;
+        int i = 0;
+        if (set.lostDigits)
+            checkdigits(rhs, set.digits);
+        n = rhs.intcheck(MinArg, MaxArg); // check RHS by the rules
+        lhs = this; // clarified name
+
+        reqdig = set.digits; // local copy (heavily used)
+        if (reqdig == 0) {
+            if (rhs.ind == isneg)
+                throw new java.lang.ArithmeticException("Negative power:" + " " + rhs.toString());
+            workdigits = 0;
+        } else {/* non-0 digits */
+            if ((rhs.mant.length + rhs.exp) > reqdig)
+                throw new java.lang.ArithmeticException("Too many digits:" + " " + rhs.toString());
+
+            /* Round the lhs to DIGITS if need be */
+            if (lhs.mant.length > reqdig)
+                lhs = clone(lhs).round(set);
+
+            /* L for precision calculation [see ANSI X3.274-1996] */
+            L = rhs.mant.length + rhs.exp; // length without decimal zeros/exp
+            workdigits = (reqdig + L) + 1; // calculate the working DIGITS
+        }
+
+        /* Create a copy of set for working settings */
+        // Note: no need to check for lostDigits again.
+        // 1999.07.17 Note: this construction must follow RHS check
+        workset = new com.ibm.icu.math.MathContext(workdigits, set.form, false, set.roundingMode);
+
+        res = ONE; // accumulator
+        if (n == 0)
+            return res; // x**0 == 1
+        if (n < 0)
+            n = -n; // [rhs.ind records the sign]
+        seenbit = false; // set once we've seen a 1-bit
+        {
+            i = 1;
+            i: for (;; i++) { // for each bit [top bit ignored]
+                n = n + n; // shift left 1 bit
+                if (n < 0) { // top bit is set
+                    seenbit = true; // OK, we're off
+                    res = res.multiply(lhs, workset); // acc=acc*x
+                }
+                if (i == 31)
+                    break i; // that was the last bit
+                if ((!seenbit))
+                    continue i; // we don't have to square 1
+                res = res.multiply(res, workset); // acc=acc*acc [square]
+            }
+        }/* i */// 32 bits
+        if (rhs.ind < 0) // was a **-n [hence digits>0]
+            res = ONE.divide(res, workset); // .. so acc=1/acc
+        return res.finish(set, true); // round and strip [original digits]
+    }
+
+    /**
+     * Returns a plain <code>BigDecimal</code> whose value is the remainder of <code>this/rhs</code>, using fixed point
+     * arithmetic.
+     * <p>
+     * The same as {@link #remainder(BigDecimal, MathContext)}, where the <code>BigDecimal</code> is <code>rhs</code>,
+     * and the context is <code>new MathContext(0, MathContext.PLAIN)</code>.
+     * <p>
+     * This is not the modulo operator -- the result may be negative.
+     * 
+     * @param rhs The <code>BigDecimal</code> for the right hand side of the remainder operation.
+     * @return A <code>BigDecimal</code> whose value is the remainder of <code>this/rhs</code>, using fixed point
+     *         arithmetic.
+     * @throws ArithmeticException if <code>rhs</code> is zero.
+     * @stable ICU 2.0
+     */
+
+    public com.ibm.icu.math.BigDecimal remainder(com.ibm.icu.math.BigDecimal rhs) {
+        return this.dodivide('R', rhs, plainMC, -1);
+    }
+
+    /**
+     * Returns a <code>BigDecimal</code> whose value is the remainder of <code>this/rhs</code>.
+     * <p>
+     * Implements the remainder operator (as defined in the decimal documentation, see {@link BigDecimal class header}),
+     * and returns the result as a <code>BigDecimal</code> object.
+     * <p>
+     * This is not the modulo operator -- the result may be negative.
+     * 
+     * @param rhs The <code>BigDecimal</code> for the right hand side of the remainder operation.
+     * @param set The <code>MathContext</code> arithmetic settings.
+     * @return A <code>BigDecimal</code> whose value is the remainder of <code>this+rhs</code>.
+     * @throws ArithmeticException if <code>rhs</code> is zero.
+     * @throws ArithmeticException  if the integer part of the result will not fit in the number of digits specified for the context.
+     * @stable ICU 2.0
+     */
+
+    public com.ibm.icu.math.BigDecimal remainder(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) {
+        return this.dodivide('R', rhs, set, -1);
+    }
+
+    /**
+     * Returns a plain <code>BigDecimal</code> whose value is <code>this-rhs</code>, using fixed point arithmetic.
+     * <p>
+     * The same as {@link #subtract(BigDecimal, MathContext)}, where the <code>BigDecimal</code> is <code>rhs</code>,
+     * and the context is <code>new MathContext(0, MathContext.PLAIN)</code>.
+     * <p>
+     * The length of the decimal part (the scale) of the result will be the maximum of the scales of the two operands.
+     * 
+     * @param rhs The <code>BigDecimal</code> for the right hand side of the subtraction.
+     * @return A <code>BigDecimal</code> whose value is <code>this-rhs</code>, using fixed point arithmetic.
+     * @stable ICU 2.0
+     */
+
+    public com.ibm.icu.math.BigDecimal subtract(com.ibm.icu.math.BigDecimal rhs) {
+        return this.subtract(rhs, plainMC);
+    }
+
+    /**
+     * Returns a <code>BigDecimal</code> whose value is <code>this-rhs</code>.
+     * <p>
+     * Implements the subtraction (<b><code>-</code></b>) operator (as defined in the decimal documentation, see
+     * {@link BigDecimal class header}), and returns the result as a <code>BigDecimal</code> object.
+     * 
+     * @param rhs The <code>BigDecimal</code> for the right hand side of the subtraction.
+     * @param set The <code>MathContext</code> arithmetic settings.
+     * @return A <code>BigDecimal</code> whose value is <code>this-rhs</code>.
+     * @stable ICU 2.0
+     */
+
+    public com.ibm.icu.math.BigDecimal subtract(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) {
+        com.ibm.icu.math.BigDecimal newrhs;
+        if (set.lostDigits)
+            checkdigits(rhs, set.digits);
+        // [add will recheck .. but would report -rhs]
+        /* carry out the subtraction */
+        // we could fastpath -0, but it is too rare.
+        newrhs = clone(rhs); // safe copy
+        newrhs.ind = (byte) -newrhs.ind; // prepare to subtract
+        return this.add(newrhs, set); // arithmetic
+    }
+
+    /* ---------------------------------------------------------------- */
+    /* Other methods */
+    /* ---------------------------------------------------------------- */
+
+    /**
+     * Converts this <code>BigDecimal</code> to a <code>byte</code>. If the <code>BigDecimal</code> has a non-zero
+     * decimal part or is out of the possible range for a <code>byte</code> (8-bit signed integer) result then an <code>
+     * ArithmeticException</code> is thrown.
+     * 
+     * @return A <code>byte</code> equal in value to <code>this</code>.
+     * @throws ArithmeticException if <code>this</code> has a non-zero decimal part, or will not fit in a <code>byte</code>.
+     * @stable ICU 2.0
+     */
+
+    public byte byteValueExact() {
+        int num;
+        num = this.intValueExact(); // will check decimal part too
+        if ((num > 127) | (num < (-128)))
+            throw new java.lang.ArithmeticException("Conversion overflow:" + " " + this.toString());
+        return (byte) num;
+    }
+
+    /**
+     * Converts this <code>BigDecimal</code> to a <code>double</code>. If the <code>BigDecimal</code> is out of the
+     * possible range for a <code>double</code> (64-bit signed floating point) result then an <code>ArithmeticException
+     * </code> is thrown.
+     * <p>
+     * The double produced is identical to result of expressing the <code>BigDecimal</code> as a <code>String</code> and
+     * then converting it using the <code>Double(String)</code> constructor; this can result in values of <code>
+     * Double.NEGATIVE_INFINITY</code> or <code>Double.POSITIVE_INFINITY</code>.
+     * 
+     * @return A <code>double</code> corresponding to <code>this</code>.
+     * @stable ICU 2.0
+     */
+
+    public double doubleValue() {
+        // We go via a String [as does BigDecimal in JDK 1.2]
+        // Next line could possibly raise NumberFormatException
+        return java.lang.Double.valueOf(this.toString()).doubleValue();
+    }
+
+    /**
+     * Compares this <code>BigDecimal</code> with <code>rhs</code> for equality.
+     * <p>
+     * If the parameter is <code>null</code>, or is not an instance of the BigDecimal type, or is not exactly equal to
+     * the current <code>BigDecimal</code> object, then <i>false</i> is returned. Otherwise, <i>true</i> is returned.
+     * <p>
+     * "Exactly equal", here, means that the <code>String</code> representations of the <code>BigDecimal</code> numbers
+     * are identical (they have the same characters in the same sequence).
+     * <p>
+     * The {@link #compareTo(BigDecimal, MathContext)} method should be used for more general comparisons.
+     * 
+     * @param obj The <code>Object</code> for the right hand side of the comparison.
+     * @return A <code>boolean</code> whose value <i>true</i> if and only if the operands have identical string
+     *         representations.
+     * @throws ClassCastException if <code>rhs</code> cannot be cast to a <code>BigDecimal</code> object.
+     * @stable ICU 2.0
+     * @see #compareTo(BigDecimal)
+     * @see #compareTo(BigDecimal, MathContext)
+     */
+
+    public boolean equals(java.lang.Object obj) {
+        com.ibm.icu.math.BigDecimal rhs;
+        int i = 0;
+        char lca[] = null;
+        char rca[] = null;
+        // We are equal iff toString of both are exactly the same
+        if (obj == null)
+            return false; // not equal
+        if ((!(((obj instanceof com.ibm.icu.math.BigDecimal)))))
+            return false; // not a decimal
+        rhs = (com.ibm.icu.math.BigDecimal) obj; // cast; we know it will work
+        if (this.ind != rhs.ind)
+            return false; // different signs never match
+        if (((this.mant.length == rhs.mant.length) & (this.exp == rhs.exp)) & (this.form == rhs.form))
+
+        { // mantissas say all
+            // here with equal-length byte arrays to compare
+            {
+                int $8 = this.mant.length;
+                i = 0;
+                for (; $8 > 0; $8--, i++) {
+                    if (this.mant[i] != rhs.mant[i])
+                        return false;
+                }
+            }/* i */
+        } else { // need proper layout
+            lca = this.layout(); // layout to character array
+            rca = rhs.layout();
+            if (lca.length != rca.length)
+                return false; // mismatch
+            // here with equal-length character arrays to compare
+            {
+                int $9 = lca.length;
+                i = 0;
+                for (; $9 > 0; $9--, i++) {
+                    if (lca[i] != rca[i])
+                        return false;
+                }
+            }/* i */
+        }
+        return true; // arrays have identical content
+    }
+
+    /**
+     * Converts this <code>BigDecimal</code> to a <code>float</code>. If the <code>BigDecimal</code> is out of the
+     * possible range for a <code>float</code> (32-bit signed floating point) result then an <code>ArithmeticException
+     * </code> is thrown.
+     * <p>
+     * The float produced is identical to result of expressing the <code>BigDecimal</code> as a <code>String</code> and
+     * then converting it using the <code>Float(String)</code> constructor; this can result in values of <code>
+     * Float.NEGATIVE_INFINITY</code> or <code>Float.POSITIVE_INFINITY</code>.
+     * 
+     * @return A <code>float</code> corresponding to <code>this</code>.
+     * @stable ICU 2.0
+     */
+
+    public float floatValue() {
+        return java.lang.Float.valueOf(this.toString()).floatValue();
+    }
+
+    /**
+     * Returns the <code>String</code> representation of this <code>BigDecimal</code>, modified by layout parameters.
+     * <p>
+     * <i>This method is provided as a primitive for use by more sophisticated classes, such as <code>DecimalFormat
+     * </code>, that can apply locale-sensitive editing of the result. The level of formatting that it provides is a
+     * necessary part of the BigDecimal class as it is sensitive to and must follow the calculation and rounding rules
+     * for BigDecimal arithmetic. However, if the function is provided elsewhere, it may be removed from this class.
+     * </i>
+     * <p>
+     * The parameters, for both forms of the <code>format</code> method are all of type <code>int</code>. A value of -1
+     * for any parameter indicates that the default action or value for that parameter should be used.
+     * <p>
+     * The parameters, <code>before</code> and <code>after</code>, specify the number of characters to be used for the
+     * integer part and decimal part of the result respectively. Exponential notation is not used. If either parameter
+     * is -1 (which indicates the default action), the number of characters used will be exactly as many as are needed
+     * for that part.
+     * <p>
+     * <code>before</code> must be a positive number; if it is larger than is needed to contain the integer part, that
+     * part is padded on the left with blanks to the requested length. If <code>before</code> is not large enough to
+     * contain the integer part of the number (including the sign, for negative numbers) an exception is thrown.
+     * <p>
+     * <code>after</code> must be a non-negative number; if it is not the same size as the decimal part of the number,
+     * the number will be rounded (or extended with zeros) to fit. Specifying 0 for <code>after</code> will cause the
+     * number to be rounded to an integer (that is, it will have no decimal part or decimal point). The rounding method
+     * will be the default, <code>MathContext.ROUND_HALF_UP</code>.
+     * <p>
+     * Other rounding methods, and the use of exponential notation, can be selected by using
+     * {@link #format(int,int,int,int,int,int)}. Using the two-parameter form of the method has exactly the same effect
+     * as using the six-parameter form with the final four parameters all being -1.
+     * 
+     * @param before The <code>int</code> specifying the number of places before the decimal point. Use -1 for 'as many as are needed'.
+     * @param after The <code>int</code> specifying the number of places after the decimal point. Use -1 for 'as many as are needed'.
+     * @return A <code>String</code> representing this <code>BigDecimal</code>, laid out according to the specified parameters
+     * @throws ArithmeticException if the number cannot be laid out as requested.
+     * @throws IllegalArgumentException if a parameter is out of range.
+     * @stable ICU 2.0
+     * @see #toString
+     * @see #toCharArray
+     */
+
+    public java.lang.String format(int before, int after) {
+        return format(before, after, -1, -1, com.ibm.icu.math.MathContext.SCIENTIFIC, ROUND_HALF_UP);
+    }
+
+    /**
+     * Returns the <code>String</code> representation of this <code>BigDecimal</code>, modified by layout parameters and
+     * allowing exponential notation.
+     * <p>
+     * <i>This method is provided as a primitive for use by more sophisticated classes, such as <code>DecimalFormat
+     * </code>, that can apply locale-sensitive editing of the result. The level of formatting that it provides is a
+     * necessary part of the BigDecimal class as it is sensitive to and must follow the calculation and rounding rules
+     * for BigDecimal arithmetic. However, if the function is provided elsewhere, it may be removed from this class.
+     * </i>
+     * <p>
+     * The parameters are all of type <code>int</code>. A value of -1 for any parameter indicates that the default
+     * action or value for that parameter should be used.
+     * <p>
+     * The first two parameters (<code>before</code> and <code>after</code>) specify the number of characters to be used
+     * for the integer part and decimal part of the result respectively, as defined for {@link #format(int,int)}. If
+     * either of these is -1 (which indicates the default action), the number of characters used will be exactly as many
+     * as are needed for that part.
+     * <p>
+     * The remaining parameters control the use of exponential notation and rounding. Three (<code>explaces</code>,
+     * <code>exdigits</code>, and <code>exform</code>) control the exponent part of the result. As before, the default
+     * action for any of these parameters may be selected by using the value -1.
+     * <p>
+     * <code>explaces</code> must be a positive number; it sets the number of places (digits after the sign of the
+     * exponent) to be used for any exponent part, the default (when <code>explaces</code> is -1) being to use as many
+     * as are needed. If <code>explaces</code> is not -1, space is always reserved for an exponent; if one is not needed
+     * (for example, if the exponent will be 0) then <code>explaces</code>+2 blanks are appended to the result. <!--
+     * (This preserves vertical alignment of similarly formatted numbers in a monospace font.) --> If <code>explaces
+     * </code> is not -1 and is not large enough to contain the exponent, an exception is thrown.
+     * <p>
+     * <code>exdigits</code> sets the trigger point for use of exponential notation. If, before any rounding, the number
+     * of places needed before the decimal point exceeds <code>exdigits</code>, or if the absolute value of the result
+     * is less than <code>0.000001</code>, then exponential form will be used, provided that <code>exdigits</code> was
+     * specified. When <code>exdigits</code> is -1, exponential notation will never be used. If 0 is specified for
+     * <code>exdigits</code>, exponential notation is always used unless the exponent would be 0.
+     * <p>
+     * <code>exform</code> sets the form for exponential notation (if needed). It may be either
+     * {@link MathContext#SCIENTIFIC} or {@link MathContext#ENGINEERING}. If the latter, engineering, form is requested,
+     * up to three digits (plus sign, if negative) may be needed for the integer part of the result (<code>before</code>
+     * ). Otherwise, only one digit (plus sign, if negative) is needed.
+     * <p>
+     * Finally, the sixth argument, <code>exround</code>, selects the rounding algorithm to be used, and must be one of
+     * the values indicated by a public constant in the {@link MathContext} class whose name starts with <code>ROUND_
+     * </code>. The default (<code>ROUND_HALF_UP</code>) may also be selected by using the value -1, as before.
+     * <p>
+     * The special value <code>MathContext.ROUND_UNNECESSARY</code> may be used to detect whether non-zero digits are
+     * discarded -- if <code>exround</code> has this value than if non-zero digits would be discarded (rounded) during
+     * formatting then an <code>ArithmeticException</code> is thrown.
+     * 
+     * @param before The <code>int</code> specifying the number of places before the decimal point. Use -1 for 'as many as
+     *            are needed'.
+     * @param after The <code>int</code> specifying the number of places after the decimal point. Use -1 for 'as many as
+     *            are needed'.
+     * @param explaces The <code>int</code> specifying the number of places to be used for any exponent. Use -1 for 'as many
+     *            as are needed'.
+     * @param exdigits The <code>int</code> specifying the trigger (digits before the decimal point) which if exceeded causes
+     *            exponential notation to be used. Use 0 to force exponential notation. Use -1 to force plain notation
+     *            (no exponential notation).
+     * @param exformint The <code>int</code> specifying the form of exponential notation to be used (
+     *            {@link MathContext#SCIENTIFIC} or {@link MathContext#ENGINEERING}).
+     * @param exround The <code>int</code> specifying the rounding mode to use. Use -1 for the default,
+     *            {@link MathContext#ROUND_HALF_UP}.
+     * @return A <code>String</code> representing this <code>BigDecimal</code>, laid out according to the specified
+     *         parameters
+     * @throws ArithmeticException if the number cannot be laid out as requested.
+     * @throws IllegalArgumentException if a parameter is out of range.
+     * @see #toString
+     * @see #toCharArray
+     * @stable ICU 2.0
+     */
+
+    public java.lang.String format(int before, int after, int explaces, int exdigits, int exformint, int exround) {
+        com.ibm.icu.math.BigDecimal num;
+        int mag = 0;
+        int thisafter = 0;
+        int lead = 0;
+        byte newmant[] = null;
+        int chop = 0;
+        int need = 0;
+        int oldexp = 0;
+        char a[];
+        int p = 0;
+        char newa[] = null;
+        int i = 0;
+        int places = 0;
+
+        /* Check arguments */
+        if ((before < (-1)) | (before == 0))
+            badarg("format", 1, java.lang.String.valueOf(before));
+        if (after < (-1))
+            badarg("format", 2, java.lang.String.valueOf(after));
+        if ((explaces < (-1)) | (explaces == 0))
+            badarg("format", 3, java.lang.String.valueOf(explaces));
+        if (exdigits < (-1))
+            badarg("format", 4, java.lang.String.valueOf(explaces));
+        {/* select */
+            if (exformint == com.ibm.icu.math.MathContext.SCIENTIFIC) {
+            } else if (exformint == com.ibm.icu.math.MathContext.ENGINEERING) {
+            } else if (exformint == (-1))
+                exformint = com.ibm.icu.math.MathContext.SCIENTIFIC;
+            // note PLAIN isn't allowed
+            else {
+                badarg("format", 5, java.lang.String.valueOf(exformint));
+            }
+        }
+        // checking the rounding mode is done by trying to construct a
+        // MathContext object with that mode; it will fail if bad
+        if (exround != ROUND_HALF_UP) {
+            try { // if non-default...
+                if (exround == (-1))
+                    exround = ROUND_HALF_UP;
+                else
+                    new com.ibm.icu.math.MathContext(9, com.ibm.icu.math.MathContext.SCIENTIFIC, false, exround);
+            } catch (java.lang.IllegalArgumentException $10) {
+                badarg("format", 6, java.lang.String.valueOf(exround));
+            }
+        }
+
+        num = clone(this); // make private copy
+
+        /*
+         * Here: num is BigDecimal to format before is places before point [>0] after is places after point [>=0]
+         * explaces is exponent places [>0] exdigits is exponent digits [>=0] exformint is exponent form [one of two]
+         * exround is rounding mode [one of eight] 'before' through 'exdigits' are -1 if not specified
+         */
+
+        /* determine form */
+        {
+            do {/* select */
+                if (exdigits == (-1))
+                    num.form = (byte) com.ibm.icu.math.MathContext.PLAIN;
+                else if (num.ind == iszero)
+                    num.form = (byte) com.ibm.icu.math.MathContext.PLAIN;
+                else {
+                    // determine whether triggers
+                    mag = num.exp + num.mant.length;
+                    if (mag > exdigits)
+                        num.form = (byte) exformint;
+                    else if (mag < (-5))
+                        num.form = (byte) exformint;
+                    else
+                        num.form = (byte) com.ibm.icu.math.MathContext.PLAIN;
+                }
+            } while (false);
+        }/* setform */
+
+        /*
+         * If 'after' was specified then we may need to adjust the mantissa. This is a little tricky, as we must conform
+         * to the rules of exponential layout if necessary (e.g., we cannot end up with 10.0 if scientific).
+         */
+        if (after >= 0) {
+            setafter: for (;;) {
+                // calculate the current after-length
+                {/* select */
+                    if (num.form == com.ibm.icu.math.MathContext.PLAIN)
+                        thisafter = -num.exp; // has decimal part
+                    else if (num.form == com.ibm.icu.math.MathContext.SCIENTIFIC)
+                        thisafter = num.mant.length - 1;
+                    else { // engineering
+                        lead = (((num.exp + num.mant.length) - 1)) % 3; // exponent to use
+                        if (lead < 0)
+                            lead = 3 + lead; // negative exponent case
+                        lead++; // number of leading digits
+                        if (lead >= num.mant.length)
+                            thisafter = 0;
+                        else
+                            thisafter = num.mant.length - lead;
+                    }
+                }
+                if (thisafter == after)
+                    break setafter; // we're in luck
+                if (thisafter < after) { // need added trailing zeros
+                    // [thisafter can be negative]
+                    newmant = extend(num.mant, (num.mant.length + after) - thisafter);
+                    num.mant = newmant;
+                    num.exp = num.exp - ((after - thisafter)); // adjust exponent
+                    if (num.exp < MinExp)
+                        throw new java.lang.ArithmeticException("Exponent Overflow:" + " " + num.exp);
+                    break setafter;
+                }
+                // We have too many digits after the decimal point; this could
+                // cause a carry, which could change the mantissa...
+                // Watch out for implied leading zeros in PLAIN case
+                chop = thisafter - after; // digits to lop [is >0]
+                if (chop > num.mant.length) { // all digits go, no chance of carry
+                    // carry on with zero
+                    num.mant = ZERO.mant;
+                    num.ind = iszero;
+                    num.exp = 0;
+                    continue setafter; // recheck: we may need trailing zeros
+                }
+                // we have a digit to inspect from existing mantissa
+                // round the number as required
+                need = num.mant.length - chop; // digits to end up with [may be 0]
+                oldexp = num.exp; // save old exponent
+                num.round(need, exround);
+                // if the exponent grew by more than the digits we chopped, then
+                // we must have had a carry, so will need to recheck the layout
+                if ((num.exp - oldexp) == chop)
+                    break setafter; // number did not have carry
+                // mantissa got extended .. so go around and check again
+            }
+        }/* setafter */
+
+        a = num.layout(); // lay out, with exponent if required, etc.
+
+        /* Here we have laid-out number in 'a' */
+        // now apply 'before' and 'explaces' as needed
+        if (before > 0) {
+            // look for '.' or 'E'
+            {
+                int $11 = a.length;
+                p = 0;
+                p: for (; $11 > 0; $11--, p++) {
+                    if (a[p] == '.')
+                        break p;
+                    if (a[p] == 'E')
+                        break p;
+                }
+            }/* p */
+            // p is now offset of '.', 'E', or character after end of array
+            // that is, the current length of before part
+            if (p > before)
+                badarg("format", 1, java.lang.String.valueOf(before)); // won't fit
+            if (p < before) { // need leading blanks
+                newa = new char[(a.length + before) - p];
+                {
+                    int $12 = before - p;
+                    i = 0;
+                    for (; $12 > 0; $12--, i++) {
+                        newa[i] = ' ';
+                    }
+                }/* i */
+                java.lang.System.arraycopy((java.lang.Object) a, 0, (java.lang.Object) newa, i, a.length);
+                a = newa;
+            }
+            // [if p=before then it's just the right length]
+        }
+
+        if (explaces > 0) {
+            // look for 'E' [cannot be at offset 0]
+            {
+                int $13 = a.length - 1;
+                p = a.length - 1;
+                p: for (; $13 > 0; $13--, p--) {
+                    if (a[p] == 'E')
+                        break p;
+                }
+            }/* p */
+            // p is now offset of 'E', or 0
+            if (p == 0) { // no E part; add trailing blanks
+                newa = new char[(a.length + explaces) + 2];
+                java.lang.System.arraycopy((java.lang.Object) a, 0, (java.lang.Object) newa, 0, a.length);
+                {
+                    int $14 = explaces + 2;
+                    i = a.length;
+                    for (; $14 > 0; $14--, i++) {
+                        newa[i] = ' ';
+                    }
+                }/* i */
+                a = newa;
+            } else {/* found E */// may need to insert zeros
+                places = (a.length - p) - 2; // number so far
+                if (places > explaces)
+                    badarg("format", 3, java.lang.String.valueOf(explaces));
+                if (places < explaces) { // need to insert zeros
+                    newa = new char[(a.length + explaces) - places];
+                    java.lang.System.arraycopy((java.lang.Object) a, 0, (java.lang.Object) newa, 0, p + 2); // through E
+                                                                                                            // and sign
+                    {
+                        int $15 = explaces - places;
+                        i = p + 2;
+                        for (; $15 > 0; $15--, i++) {
+                            newa[i] = '0';
+                        }
+                    }/* i */
+                    java.lang.System.arraycopy((java.lang.Object) a, p + 2, (java.lang.Object) newa, i, places); // remainder
+                                                                                                                 // of
+                                                                                                                 // exponent
+                    a = newa;
+                }
+                // [if places=explaces then it's just the right length]
+            }
+        }
+        return new java.lang.String(a);
+    }
+
+    /**
+     * Returns the hashcode for this <code>BigDecimal</code>. This hashcode is suitable for use by the <code>
+     * java.util.Hashtable</code> class.
+     * <p>
+     * Note that two <code>BigDecimal</code> objects are only guaranteed to produce the same hashcode if they are
+     * exactly equal (that is, the <code>String</code> representations of the <code>BigDecimal</code> numbers are
+     * identical -- they have the same characters in the same sequence).
+     * 
+     * @return An <code>int</code> that is the hashcode for <code>this</code>.
+     * @stable ICU 2.0
+     */
+
+    public int hashCode() {
+        // Maybe calculate ourselves, later. If so, note that there can be
+        // more than one internal representation for a given toString() result.
+        return this.toString().hashCode();
+    }
+
+    /**
+     * Converts this <code>BigDecimal</code> to an <code>int</code>. If the <code>BigDecimal</code> has a non-zero
+     * decimal part it is discarded. If the <code>BigDecimal</code> is out of the possible range for an <code>int</code>
+     * (32-bit signed integer) result then only the low-order 32 bits are used. (That is, the number may be
+     * <i>decapitated</i>.) To avoid unexpected errors when these conditions occur, use the {@link #intValueExact}
+     * method.
+     * 
+     * @return An <code>int</code> converted from <code>this</code>, truncated and decapitated if necessary.
+     * @stable ICU 2.0
+     */
+
+    public int intValue() {
+        return toBigInteger().intValue();
+    }
+
+    /**
+     * Converts this <code>BigDecimal</code> to an <code>int</code>. If the <code>BigDecimal</code> has a non-zero
+     * decimal part or is out of the possible range for an <code>int</code> (32-bit signed integer) result then an
+     * <code>ArithmeticException</code> is thrown.
+     * 
+     * @return An <code>int</code> equal in value to <code>this</code>.
+     * @throws ArithmeticException if <code>this</code> has a non-zero decimal part, or will not fit in an <code>int</code>.
+     * @stable ICU 2.0
+     */
+
+    public int intValueExact() {
+        int lodigit;
+        int useexp = 0;
+        int result;
+        int i = 0;
+        int topdig = 0;
+        // This does not use longValueExact() as the latter can be much
+        // slower.
+        // intcheck (from pow) relies on this to check decimal part
+        if (ind == iszero)
+            return 0; // easy, and quite common
+        /* test and drop any trailing decimal part */
+        lodigit = mant.length - 1;
+        if (exp < 0) {
+            lodigit = lodigit + exp; // reduces by -(-exp)
+            /* all decimal places must be 0 */
+            if ((!(allzero(mant, lodigit + 1))))
+                throw new java.lang.ArithmeticException("Decimal part non-zero:" + " " + this.toString());
+            if (lodigit < 0)
+                return 0; // -1<this<1
+            useexp = 0;
+        } else {/* >=0 */
+            if ((exp + lodigit) > 9) // early exit
+                throw new java.lang.ArithmeticException("Conversion overflow:" + " " + this.toString());
+            useexp = exp;
+        }
+        /* convert the mantissa to binary, inline for speed */
+        result = 0;
+        {
+            int $16 = lodigit + useexp;
+            i = 0;
+            for (; i <= $16; i++) {
+                result = result * 10;
+                if (i <= lodigit)
+                    result = result + mant[i];
+            }
+        }/* i */
+
+        /* Now, if the risky length, check for overflow */
+        if ((lodigit + useexp) == 9) {
+            // note we cannot just test for -ve result, as overflow can move a
+            // zero into the top bit [consider 5555555555]
+            topdig = result / 1000000000; // get top digit, preserving sign
+            if (topdig != mant[0]) { // digit must match and be positive
+                // except in the special case ...
+                if (result == java.lang.Integer.MIN_VALUE) // looks like the special
+                    if (ind == isneg) // really was negative
+                        if (mant[0] == 2)
+                            return result; // really had top digit 2
+                throw new java.lang.ArithmeticException("Conversion overflow:" + " " + this.toString());
+            }
+        }
+
+        /* Looks good */
+        if (ind == ispos)
+            return result;
+        return -result;
+    }
+
+    /**
+     * Converts this <code>BigDecimal</code> to a <code>long</code>. If the <code>BigDecimal</code> has a non-zero
+     * decimal part it is discarded. If the <code>BigDecimal</code> is out of the possible range for a <code>long</code>
+     * (64-bit signed integer) result then only the low-order 64 bits are used. (That is, the number may be
+     * <i>decapitated</i>.) To avoid unexpected errors when these conditions occur, use the {@link #longValueExact}
+     * method.
+     * 
+     * @return A <code>long</code> converted from <code>this</code>, truncated and decapitated if necessary.
+     * @stable ICU 2.0
+     */
+
+    public long longValue() {
+        return toBigInteger().longValue();
+    }
+
+    /**
+     * Converts this <code>BigDecimal</code> to a <code>long</code>. If the <code>BigDecimal</code> has a non-zero
+     * decimal part or is out of the possible range for a <code>long</code> (64-bit signed integer) result then an
+     * <code>ArithmeticException</code> is thrown.
+     * 
+     * @return A <code>long</code> equal in value to <code>this</code>.
+     * @throws ArithmeticException if <code>this</code> has a non-zero decimal part, or will not fit in a <code>long</code>.
+     * @stable ICU 2.0
+     */
+
+    public long longValueExact() {
+        int lodigit;
+        int cstart = 0;
+        int useexp = 0;
+        long result;
+        int i = 0;
+        long topdig = 0;
+        // Identical to intValueExact except for result=long, and exp>=20 test
+        if (ind == 0)
+            return 0; // easy, and quite common
+        lodigit = mant.length - 1; // last included digit
+        if (exp < 0) {
+            lodigit = lodigit + exp; // -(-exp)
+            /* all decimal places must be 0 */
+            if (lodigit < 0)
+                cstart = 0;
+            else
+                cstart = lodigit + 1;
+            if ((!(allzero(mant, cstart))))
+                throw new java.lang.ArithmeticException("Decimal part non-zero:" + " " + this.toString());
+            if (lodigit < 0)
+                return 0; // -1<this<1
+            useexp = 0;
+        } else {/* >=0 */
+            if ((exp + mant.length) > 18) // early exit
+                throw new java.lang.ArithmeticException("Conversion overflow:" + " " + this.toString());
+            useexp = exp;
+        }
+
+        /* convert the mantissa to binary, inline for speed */
+        // note that we could safely use the 'test for wrap to negative'
+        // algorithm here, but instead we parallel the intValueExact
+        // algorithm for ease of checking and maintenance.
+        result = (long) 0;
+        {
+            int $17 = lodigit + useexp;
+            i = 0;
+            for (; i <= $17; i++) {
+                result = result * 10;
+                if (i <= lodigit)
+                    result = result + mant[i];
+            }
+        }/* i */
+
+        /* Now, if the risky length, check for overflow */
+        if ((lodigit + useexp) == 18) {
+            topdig = result / 1000000000000000000L; // get top digit, preserving sign
+            if (topdig != mant[0]) { // digit must match and be positive
+                // except in the special case ...
+                if (result == java.lang.Long.MIN_VALUE) // looks like the special
+                    if (ind == isneg) // really was negative
+                        if (mant[0] == 9)
+                            return result; // really had top digit 9
+                throw new java.lang.ArithmeticException("Conversion overflow:" + " " + this.toString());
+            }
+        }
+
+        /* Looks good */
+        if (ind == ispos)
+            return result;
+        return -result;
+    }
+
+    /**
+     * Returns a plain <code>BigDecimal</code> whose decimal point has been moved to the left by a specified number of
+     * positions. The parameter, <code>n</code>, specifies the number of positions to move the decimal point. That is,
+     * if <code>n</code> is 0 or positive, the number returned is given by:
+     * <p>
+     * <code> this.multiply(TEN.pow(new BigDecimal(-n))) </code>
+     * <p>
+     * <code>n</code> may be negative, in which case the method returns the same result as <code>movePointRight(-n)
+     * </code>.
+     * 
+     * @param n The <code>int</code> specifying the number of places to move the decimal point leftwards.
+     * @return A <code>BigDecimal</code> derived from <code>this</code>, with the decimal point moved <code>n</code>
+     *         places to the left.
+     * @stable ICU 2.0
+     */
+
+    public com.ibm.icu.math.BigDecimal movePointLeft(int n) {
+        com.ibm.icu.math.BigDecimal res;
+        // very little point in optimizing for shift of 0
+        res = clone(this);
+        res.exp = res.exp - n;
+        return res.finish(plainMC, false); // finish sets form and checks exponent
+    }
+
+    /**
+     * Returns a plain <code>BigDecimal</code> whose decimal point has been moved to the right by a specified number of
+     * positions. The parameter, <code>n</code>, specifies the number of positions to move the decimal point. That is,
+     * if <code>n</code> is 0 or positive, the number returned is given by:
+     * <p>
+     * <code> this.multiply(TEN.pow(new BigDecimal(n))) </code>
+     * <p>
+     * <code>n</code> may be negative, in which case the method returns the same result as <code>movePointLeft(-n)
+     * </code>.
+     * 
+     * @param n The <code>int</code> specifying the number of places to move the decimal point rightwards.
+     * @return A <code>BigDecimal</code> derived from <code>this</code>, with the decimal point moved <code>n</code>
+     *         places to the right.
+     * @stable ICU 2.0
+     */
+
+    public com.ibm.icu.math.BigDecimal movePointRight(int n) {
+        com.ibm.icu.math.BigDecimal res;
+        res = clone(this);
+        res.exp = res.exp + n;
+        return res.finish(plainMC, false);
+    }
+
+    /**
+     * Returns the scale of this <code>BigDecimal</code>. Returns a non-negative <code>int</code> which is the scale of
+     * the number. The scale is the number of digits in the decimal part of the number if the number were formatted
+     * without exponential notation.
+     * 
+     * @return An <code>int</code> whose value is the scale of this <code>BigDecimal</code>.
+     * @stable ICU 2.0
+     */
+
+    public int scale() {
+        if (exp >= 0)
+            return 0; // scale can never be negative
+        return -exp;
+    }
+
+    /**
+     * Returns a plain <code>BigDecimal</code> with a given scale.
+     * <p>
+     * If the given scale (which must be zero or positive) is the same as or greater than the length of the decimal part
+     * (the scale) of this <code>BigDecimal</code> then trailing zeros will be added to the decimal part as necessary.
+     * <p>
+     * If the given scale is less than the length of the decimal part (the scale) of this <code>BigDecimal</code> then
+     * trailing digits will be removed, and in this case an <code>ArithmeticException</code> is thrown if any discarded
+     * digits are non-zero.
+     * <p>
+     * The same as {@link #setScale(int, int)}, where the first parameter is the scale, and the second is <code>
+     * MathContext.ROUND_UNNECESSARY</code>.
+     * 
+     * @param scale The <code>int</code> specifying the scale of the resulting <code>BigDecimal</code>.
+     * @return A plain <code>BigDecimal</code> with the given scale.
+     * @throws ArithmeticException if <code>scale</code> is negative.
+     * @throws ArithmeticException if reducing scale would discard non-zero digits.
+     * @stable ICU 2.0
+     */
+
+    public com.ibm.icu.math.BigDecimal setScale(int scale) {
+        return setScale(scale, ROUND_UNNECESSARY);
+    }
+
+    /**
+     * Returns a plain <code>BigDecimal</code> with a given scale.
+     * <p>
+     * If the given scale (which must be zero or positive) is the same as or greater than the length of the decimal part
+     * (the scale) of this <code>BigDecimal</code> then trailing zeros will be added to the decimal part as necessary.
+     * <p>
+     * If the given scale is less than the length of the decimal part (the scale) of this <code>BigDecimal</code> then
+     * trailing digits will be removed, and the rounding mode given by the second parameter is used to determine if the
+     * remaining digits are affected by a carry. In this case, an <code>IllegalArgumentException</code> is thrown if
+     * <code>round</code> is not a valid rounding mode.
+     * <p>
+     * If <code>round</code> is <code>MathContext.ROUND_UNNECESSARY</code>, an <code>ArithmeticException</code> is
+     * thrown if any discarded digits are non-zero.
+     * 
+     * @param scale The <code>int</code> specifying the scale of the resulting <code>BigDecimal</code>.
+     * @param round The <code>int</code> rounding mode to be used for the division (see the {@link MathContext} class).
+     * @return A plain <code>BigDecimal</code> with the given scale.
+     * @throws IllegalArgumentException if <code>round</code> is not a valid rounding mode.
+     * @throws ArithmeticException if <code>scale</code> is negative.
+     * @throws ArithmeticException if <code>round</code> is <code>MathContext.ROUND_UNNECESSARY</code>, and reducing scale would discard
+     *             non-zero digits.
+     * @stable ICU 2.0
+     */
+
+    public com.ibm.icu.math.BigDecimal setScale(int scale, int round) {
+        int ourscale;
+        com.ibm.icu.math.BigDecimal res;
+        int padding = 0;
+        int newlen = 0;
+        // at present this naughtily only checks the round value if it is
+        // needed (used), for speed
+        ourscale = this.scale();
+        if (ourscale == scale) // already correct scale
+            if (this.form == com.ibm.icu.math.MathContext.PLAIN) // .. and form
+                return this;
+        res = clone(this); // need copy
+        if (ourscale <= scale) { // simply zero-padding/changing form
+            // if ourscale is 0 we may have lots of 0s to add
+            if (ourscale == 0)
+                padding = res.exp + scale;
+            else
+                padding = scale - ourscale;
+            res.mant = extend(res.mant, res.mant.length + padding);
+            res.exp = -scale; // as requested
+        } else {/* ourscale>scale: shortening, probably */
+            if (scale < 0)
+                throw new java.lang.ArithmeticException("Negative scale:" + " " + scale);
+            // [round() will raise exception if invalid round]
+            newlen = res.mant.length - ((ourscale - scale)); // [<=0 is OK]
+            res = res.round(newlen, round); // round to required length
+            // This could have shifted left if round (say) 0.9->1[.0]
+            // Repair if so by adding a zero and reducing exponent
+            if (res.exp != -scale) {
+                res.mant = extend(res.mant, res.mant.length + 1);
+                res.exp = res.exp - 1;
+            }
+        }
+        res.form = (byte) com.ibm.icu.math.MathContext.PLAIN; // by definition
+        return res;
+    }
+
+    /**
+     * Converts this <code>BigDecimal</code> to a <code>short</code>. If the <code>BigDecimal</code> has a non-zero
+     * decimal part or is out of the possible range for a <code>short</code> (16-bit signed integer) result then an
+     * <code>ArithmeticException</code> is thrown.
+     * 
+     * @return A <code>short</code> equal in value to <code>this</code>.
+     * @throws ArithmeticException if <code>this</code> has a non-zero decimal part, or will not fit in a <code>short</code>.
+     * @stable ICU 2.0
+     */
+
+    public short shortValueExact() {
+        int num;
+        num = this.intValueExact(); // will check decimal part too
+        if ((num > 32767) | (num < (-32768)))
+            throw new java.lang.ArithmeticException("Conversion overflow:" + " " + this.toString());
+        return (short) num;
+    }
+
+    /**
+     * Returns the sign of this <code>BigDecimal</code>, as an <code>int</code>. This returns the <i>signum</i> function
+     * value that represents the sign of this <code>BigDecimal</code>. That is, -1 if the <code>BigDecimal</code> is
+     * negative, 0 if it is numerically equal to zero, or 1 if it is positive.
+     * 
+     * @return An <code>int</code> which is -1 if the <code>BigDecimal</code> is negative, 0 if it is numerically equal
+     *         to zero, or 1 if it is positive.
+     * @stable ICU 2.0
+     */
+
+    public int signum() {
+        return (int) this.ind; // [note this assumes values for ind.]
+    }
+
+    /**
+     * Converts this <code>BigDecimal</code> to a <code>java.math.BigDecimal</code>.
+     * <p>
+     * This is an exact conversion; the result is the same as if the <code>BigDecimal</code> were formatted as a plain
+     * number without any rounding or exponent and then the <code>java.math.BigDecimal(java.lang.String)</code>
+     * constructor were used to construct the result.
+     * <p>
+     * <i>(Note: this method is provided only in the <code>com.ibm.icu.math</code> version of the BigDecimal class. It
+     * would not be present in a <code>java.math</code> version.)</i>
+     * 
+     * @return The <code>java.math.BigDecimal</code> equal in value to this <code>BigDecimal</code>.
+     * @stable ICU 2.0
+     */
+
+    public java.math.BigDecimal toBigDecimal() {
+        return new java.math.BigDecimal(this.unscaledValue(), this.scale());
+    }
+
+    /**
+     * Converts this <code>BigDecimal</code> to a <code>java.math.BigInteger</code>.
+     * <p>
+     * Any decimal part is truncated (discarded). If an exception is desired should the decimal part be non-zero, use
+     * {@link #toBigIntegerExact()}.
+     * 
+     * @return The <code>java.math.BigInteger</code> equal in value to the integer part of this <code>BigDecimal</code>.
+     * @stable ICU 2.0
+     */
+
+    public java.math.BigInteger toBigInteger() {
+        com.ibm.icu.math.BigDecimal res = null;
+        int newlen = 0;
+        byte newmant[] = null;
+        {/* select */
+            if ((exp >= 0) & (form == com.ibm.icu.math.MathContext.PLAIN))
+                res = this; // can layout simply
+            else if (exp >= 0) {
+                res = clone(this); // safe copy
+                res.form = (byte) com.ibm.icu.math.MathContext.PLAIN; // .. and request PLAIN
+            } else {
+                { // exp<0; scale to be truncated
+                    // we could use divideInteger, but we may as well be quicker
+                    if (-this.exp >= this.mant.length)
+                        res = ZERO; // all blows away
+                    else {
+                        res = clone(this); // safe copy
+                        newlen = res.mant.length + res.exp;
+                        newmant = new byte[newlen]; // [shorter]
+                        java.lang.System.arraycopy((java.lang.Object) res.mant, 0, (java.lang.Object) newmant, 0,
+                                newlen);
+                        res.mant = newmant;
+                        res.form = (byte) com.ibm.icu.math.MathContext.PLAIN;
+                        res.exp = 0;
+                    }
+                }
+            }
+        }
+        return new BigInteger(new java.lang.String(res.layout()));
+    }
+
+    /**
+     * Converts this <code>BigDecimal</code> to a <code>java.math.BigInteger</code>.
+     * <p>
+     * An exception is thrown if the decimal part (if any) is non-zero.
+     * 
+     * @return The <code>java.math.BigInteger</code> equal in value to the integer part of this <code>BigDecimal</code>.
+     * @throws ArithmeticException if <code>this</code> has a non-zero decimal part.
+     * @stable ICU 2.0
+     */
+
+    public java.math.BigInteger toBigIntegerExact() {
+        /* test any trailing decimal part */
+        if (exp < 0) { // possible decimal part
+            /* all decimal places must be 0; note exp<0 */
+            if ((!(allzero(mant, mant.length + exp))))
+                throw new java.lang.ArithmeticException("Decimal part non-zero:" + " " + this.toString());
+        }
+        return toBigInteger();
+    }
+
+    /**
+     * Returns the <code>BigDecimal</code> as a character array. The result of this method is the same as using the
+     * sequence <code>toString().toCharArray()</code>, but avoids creating the intermediate <code>String</code> and
+     * <code>char[]</code> objects.
+     * 
+     * @return The <code>char[]</code> array corresponding to this <code>BigDecimal</code>.
+     * @stable ICU 2.0
+     */
+
+    public char[] toCharArray() {
+        return layout();
+    }
+
+    /**
+     * Returns the <code>BigDecimal</code> as a <code>String</code>. This returns a <code>String</code> that exactly
+     * represents this <code>BigDecimal</code>, as defined in the decimal documentation (see {@link BigDecimal class
+     * header}).
+     * <p>
+     * By definition, using the {@link #BigDecimal(String)} constructor on the result <code>String</code> will create a
+     * <code>BigDecimal</code> that is exactly equal to the original <code>BigDecimal</code>.
+     * 
+     * @return The <code>String</code> exactly corresponding to this <code>BigDecimal</code>.
+     * @see #format(int, int)
+     * @see #format(int, int, int, int, int, int)
+     * @see #toCharArray()
+     * @stable ICU 2.0
+     */
+
+    public java.lang.String toString() {
+        return new java.lang.String(layout());
+    }
+
+    /**
+     * Returns the number as a <code>BigInteger</code> after removing the scale. That is, the number is expressed as a
+     * plain number, any decimal point is then removed (retaining the digits of any decimal part), and the result is
+     * then converted to a <code>BigInteger</code>.
+     * 
+     * @return The <code>java.math.BigInteger</code> equal in value to this <code>BigDecimal</code> multiplied by ten to
+     *         the power of <code>this.scale()</code>.
+     * @stable ICU 2.0
+     */
+
+    public java.math.BigInteger unscaledValue() {
+        com.ibm.icu.math.BigDecimal res = null;
+        if (exp >= 0)
+            res = this;
+        else {
+            res = clone(this); // safe copy
+            res.exp = 0; // drop scale
+        }
+        return res.toBigInteger();
+    }
+
+    /**
+     * Translates a <code>double</code> to a <code>BigDecimal</code>.
+     * <p>
+     * Returns a <code>BigDecimal</code> which is the decimal representation of the 64-bit signed binary floating point
+     * parameter. If the parameter is infinite, or is not a number (NaN), a <code>NumberFormatException</code> is
+     * thrown.
+     * <p>
+     * The number is constructed as though <code>num</code> had been converted to a <code>String</code> using the <code>
+     * Double.toString()</code> method and the {@link #BigDecimal(java.lang.String)} constructor had then been used.
+     * This is typically not an exact conversion.
+     * 
+     * @param dub The <code>double</code> to be translated.
+     * @return The <code>BigDecimal</code> equal in value to <code>dub</code>.
+     * @throws NumberFormatException if the parameter is infinite or not a number.
+     * @stable ICU 2.0
+     */
+
+    public static com.ibm.icu.math.BigDecimal valueOf(double dub) {
+        // Reminder: a zero double returns '0.0', so we cannot fastpath to
+        // use the constant ZERO. This might be important enough to justify
+        // a factory approach, a cache, or a few private constants, later.
+        return new com.ibm.icu.math.BigDecimal((new java.lang.Double(dub)).toString());
+    }
+
+    /**
+     * Translates a <code>long</code> to a <code>BigDecimal</code>. That is, returns a plain <code>BigDecimal</code>
+     * whose value is equal to the given <code>long</code>.
+     * 
+     * @param lint The <code>long</code> to be translated.
+     * @return The <code>BigDecimal</code> equal in value to <code>lint</code>.
+     * @stable ICU 2.0
+     */
+
+    public static com.ibm.icu.math.BigDecimal valueOf(long lint) {
+        return valueOf(lint, 0);
+    }
+
+    /**
+     * Translates a <code>long</code> to a <code>BigDecimal</code> with a given scale. That is, returns a plain <code>
+     * BigDecimal</code> whose unscaled value is equal to the given <code>long</code>, adjusted by the second parameter,
+     * <code>scale</code>.
+     * <p>
+     * The result is given by:
+     * <p>
+     * <code> (new BigDecimal(lint)).divide(TEN.pow(new BigDecimal(scale))) </code>
+     * <p>
+     * A <code>NumberFormatException</code> is thrown if <code>scale</code> is negative.
+     * 
+     * @param lint The <code>long</code> to be translated.
+     * @param scale The <code>int</code> scale to be applied.
+     * @return The <code>BigDecimal</code> equal in value to <code>lint</code>.
+     * @throws NumberFormatException if the scale is negative.
+     * @stable ICU 2.0
+     */
+
+    public static com.ibm.icu.math.BigDecimal valueOf(long lint, int scale) {
+        com.ibm.icu.math.BigDecimal res = null;
+        {/* select */
+            if (lint == 0)
+                res = ZERO;
+            else if (lint == 1)
+                res = ONE;
+            else if (lint == 10)
+                res = TEN;
+            else {
+                res = new com.ibm.icu.math.BigDecimal(lint);
+            }
+        }
+        if (scale == 0)
+            return res;
+        if (scale < 0)
+            throw new java.lang.NumberFormatException("Negative scale:" + " " + scale);
+        res = clone(res); // safe copy [do not mutate]
+        res.exp = -scale; // exponent is -scale
+        return res;
+    }
+
+    /* ---------------------------------------------------------------- */
+    /* Private methods */
+    /* ---------------------------------------------------------------- */
+
+    /*
+     * <sgml> Return char array value of a BigDecimal (conversion from BigDecimal to laid-out canonical char array).
+     * <p>The mantissa will either already have been rounded (following an operation) or will be of length appropriate
+     * (in the case of construction from an int, for example). <p>We must not alter the mantissa, here. <p>'form'
+     * describes whether we are to use exponential notation (and if so, which), or if we are to lay out as a plain/pure
+     * numeric. </sgml>
+     */
+
+    private char[] layout() {
+        char cmant[];
+        int i = 0;
+        StringBuilder sb = null;
+        int euse = 0;
+        int sig = 0;
+        char csign = 0;
+        char rec[] = null;
+        int needsign;
+        int mag;
+        int len = 0;
+        cmant = new char[mant.length]; // copy byte[] to a char[]
+        {
+            int $18 = mant.length;
+            i = 0;
+            for (; $18 > 0; $18--, i++) {
+                cmant[i] = (char) (mant[i] + ((int) ('0')));
+            }
+        }/* i */
+
+        if (form != com.ibm.icu.math.MathContext.PLAIN) {/* exponential notation needed */
+            sb = new StringBuilder(cmant.length + 15); // -x.xxxE+999999999
+            if (ind == isneg)
+                sb.append('-');
+            euse = (exp + cmant.length) - 1; // exponent to use
+            /* setup sig=significant digits and copy to result */
+            if (form == com.ibm.icu.math.MathContext.SCIENTIFIC) { // [default]
+                sb.append(cmant[0]); // significant character
+                if (cmant.length > 1) // have decimal part
+                    sb.append('.').append(cmant, 1, cmant.length - 1);
+            } else {
+                do {
+                    sig = euse % 3; // common
+                    if (sig < 0)
+                        sig = 3 + sig; // negative exponent
+                    euse = euse - sig;
+                    sig++;
+                    if (sig >= cmant.length) { // zero padding may be needed
+                        sb.append(cmant, 0, cmant.length);
+                        {
+                            int $19 = sig - cmant.length;
+                            for (; $19 > 0; $19--) {
+                                sb.append('0');
+                            }
+                        }
+                    } else { // decimal point needed
+                        sb.append(cmant, 0, sig).append('.').append(cmant, sig, cmant.length - sig);
+                    }
+                } while (false);
+            }/* engineering */
+            if (euse != 0) {
+                if (euse < 0) {
+                    csign = '-';
+                    euse = -euse;
+                } else
+                    csign = '+';
+                sb.append('E').append(csign).append(euse);
+            }
+            rec = new char[sb.length()];
+            int srcEnd = sb.length();
+            if (0 != srcEnd) {
+                sb.getChars(0, srcEnd, rec, 0);
+            }
+            return rec;
+        }
+
+        /* Here for non-exponential (plain) notation */
+        if (exp == 0) {/* easy */
+            if (ind >= 0)
+                return cmant; // non-negative integer
+            rec = new char[cmant.length + 1];
+            rec[0] = '-';
+            java.lang.System.arraycopy((java.lang.Object) cmant, 0, (java.lang.Object) rec, 1, cmant.length);
+            return rec;
+        }
+
+        /* Need a '.' and/or some zeros */
+        needsign = (ind == isneg) ? 1 : 0; // space for sign? 0 or 1
+
+        /*
+         * MAG is the position of the point in the mantissa (index of the character it follows)
+         */
+        mag = exp + cmant.length;
+
+        if (mag < 1) {/* 0.00xxxx form */
+            len = (needsign + 2) - exp; // needsign+2+(-mag)+cmant.length
+            rec = new char[len];
+            if (needsign != 0)
+                rec[0] = '-';
+            rec[needsign] = '0';
+            rec[needsign + 1] = '.';
+            {
+                int $20 = -mag;
+                i = needsign + 2;
+                for (; $20 > 0; $20--, i++) { // maybe none
+                    rec[i] = '0';
+                }
+            }/* i */
+            java.lang.System.arraycopy((java.lang.Object) cmant, 0, (java.lang.Object) rec, (needsign + 2) - mag,
+                    cmant.length);
+            return rec;
+        }
+
+        if (mag > cmant.length) {/* xxxx0000 form */
+            len = needsign + mag;
+            rec = new char[len];
+            if (needsign != 0)
+                rec[0] = '-';
+            java.lang.System.arraycopy((java.lang.Object) cmant, 0, (java.lang.Object) rec, needsign, cmant.length);
+            {
+                int $21 = mag - cmant.length;
+                i = needsign + cmant.length;
+                for (; $21 > 0; $21--, i++) { // never 0
+                    rec[i] = '0';
+                }
+            }/* i */
+            return rec;
+        }
+
+        /* decimal point is in the middle of the mantissa */
+        len = (needsign + 1) + cmant.length;
+        rec = new char[len];
+        if (needsign != 0)
+            rec[0] = '-';
+        java.lang.System.arraycopy((java.lang.Object) cmant, 0, (java.lang.Object) rec, needsign, mag);
+        rec[needsign + mag] = '.';
+        java.lang.System.arraycopy((java.lang.Object) cmant, mag, (java.lang.Object) rec, (needsign + mag) + 1,
+                cmant.length - mag);
+        return rec;
+    }
+
+    /*
+     * <sgml> Checks a BigDecimal argument to ensure it's a true integer in a given range. <p>If OK, returns it as an
+     * int. </sgml>
+     */
+    // [currently only used by pow]
+    private int intcheck(int min, int max) {
+        int i;
+        i = this.intValueExact(); // [checks for non-0 decimal part]
+        // Use same message as though intValueExact failed due to size
+        if ((i < min) | (i > max))
+            throw new java.lang.ArithmeticException("Conversion overflow:" + " " + i);
+        return i;
+    }
+
+    /* <sgml> Carry out division operations. </sgml> */
+    /*
+     * Arg1 is operation code: D=divide, I=integer divide, R=remainder Arg2 is the rhs. Arg3 is the context. Arg4 is
+     * explicit scale iff code='D' or 'I' (-1 if none).
+     * 
+     * Underlying algorithm (complications for Remainder function and scaled division are omitted for clarity):
+     * 
+     * Test for x/0 and then 0/x Exp =Exp1 - Exp2 Exp =Exp +len(var1) -len(var2) Sign=Sign1 Sign2 Pad accumulator (Var1)
+     * to double-length with 0's (pad1) Pad Var2 to same length as Var1 B2B=1st two digits of var2, +1 to allow for
+     * roundup have=0 Do until (have=digits+1 OR residue=0) if exp<0 then if integer divide/residue then leave
+     * this_digit=0 Do forever compare numbers if <0 then leave inner_loop if =0 then (- quick exit without subtract -)
+     * do this_digit=this_digit+1; output this_digit leave outer_loop; end Compare lengths of numbers (mantissae): If
+     * same then CA=first_digit_of_Var1 else CA=first_two_digits_of_Var1 mult=ca10/b2b -- Good and safe guess at divisor
+     * if mult=0 then mult=1 this_digit=this_digit+mult subtract end inner_loop if have\=0 | this_digit\=0 then do
+     * output this_digit have=have+1; end var2=var2/10 exp=exp-1 end outer_loop exp=exp+1 -- set the proper exponent if
+     * have=0 then generate answer=0 Return to FINISHED Result defined by MATHV1
+     * 
+     * For extended commentary, see DMSRCN.
+     */
+
+    private com.ibm.icu.math.BigDecimal dodivide(char code, com.ibm.icu.math.BigDecimal rhs,
+            com.ibm.icu.math.MathContext set, int scale) {
+        com.ibm.icu.math.BigDecimal lhs;
+        int reqdig;
+        int newexp;
+        com.ibm.icu.math.BigDecimal res;
+        int newlen;
+        byte var1[];
+        int var1len;
+        byte var2[];
+        int var2len;
+        int b2b;
+        int have;
+        int thisdigit = 0;
+        int i = 0;
+        byte v2 = 0;
+        int ba = 0;
+        int mult = 0;
+        int start = 0;
+        int padding = 0;
+        int d = 0;
+        byte newvar1[] = null;
+        byte lasthave = 0;
+        int actdig = 0;
+        byte newmant[] = null;
+
+        if (set.lostDigits)
+            checkdigits(rhs, set.digits);
+        lhs = this; // name for clarity
+
+        // [note we must have checked lostDigits before the following checks]
+        if (rhs.ind == 0)
+            throw new java.lang.ArithmeticException("Divide by 0"); // includes 0/0
+        if (lhs.ind == 0) { // 0/x => 0 [possibly with .0s]
+            if (set.form != com.ibm.icu.math.MathContext.PLAIN)
+                return ZERO;
+            if (scale == (-1))
+                return lhs;
+            return lhs.setScale(scale);
+        }
+
+        /* Prepare numbers according to BigDecimal rules */
+        reqdig = set.digits; // local copy (heavily used)
+        if (reqdig > 0) {
+            if (lhs.mant.length > reqdig)
+                lhs = clone(lhs).round(set);
+            if (rhs.mant.length > reqdig)
+                rhs = clone(rhs).round(set);
+        } else {/* scaled divide */
+            if (scale == (-1))
+                scale = lhs.scale();
+            // set reqdig to be at least large enough for the computation
+            reqdig = lhs.mant.length; // base length
+            // next line handles both positive lhs.exp and also scale mismatch
+            if (scale != -lhs.exp)
+                reqdig = (reqdig + scale) + lhs.exp;
+            reqdig = (reqdig - ((rhs.mant.length - 1))) - rhs.exp; // reduce by RHS effect
+            if (reqdig < lhs.mant.length)
+                reqdig = lhs.mant.length; // clamp
+            if (reqdig < rhs.mant.length)
+                reqdig = rhs.mant.length; // ..
+        }
+
+        /* precalculate exponent */
+        newexp = ((lhs.exp - rhs.exp) + lhs.mant.length) - rhs.mant.length;
+        /* If new exponent -ve, then some quick exits are possible */
+        if (newexp < 0)
+            if (code != 'D') {
+                if (code == 'I')
+                    return ZERO; // easy - no integer part
+                /* Must be 'R'; remainder is [finished clone of] input value */
+                return clone(lhs).finish(set, false);
+            }
+
+        /* We need slow division */
+        res = new com.ibm.icu.math.BigDecimal(); // where we'll build result
+        res.ind = (byte) (lhs.ind * rhs.ind); // final sign (for D/I)
+        res.exp = newexp; // initial exponent (for D/I)
+        res.mant = new byte[reqdig + 1]; // where build the result
+
+        /* Now [virtually pad the mantissae with trailing zeros */
+        // Also copy the LHS, which will be our working array
+        newlen = (reqdig + reqdig) + 1;
+        var1 = extend(lhs.mant, newlen); // always makes longer, so new safe array
+        var1len = newlen; // [remaining digits are 0]
+
+        var2 = rhs.mant;
+        var2len = newlen;
+
+        /* Calculate first two digits of rhs (var2), +1 for later estimations */
+        b2b = (var2[0] * 10) + 1;
+        if (var2.length > 1)
+            b2b = b2b + var2[1];
+
+        /* start the long-division loops */
+        have = 0;
+        {
+            outer: for (;;) {
+                thisdigit = 0;
+                /* find the next digit */
+                {
+                    inner: for (;;) {
+                        if (var1len < var2len)
+                            break inner; // V1 too low
+                        if (var1len == var2len) { // compare needed
+                            {
+                                compare: do { // comparison
+                                    {
+                                        int $22 = var1len;
+                                        i = 0;
+                                        for (; $22 > 0; $22--, i++) {
+                                            // var1len is always <= var1.length
+                                            if (i < var2.length)
+                                                v2 = var2[i];
+                                            else
+                                                v2 = (byte) 0;
+                                            if (var1[i] < v2)
+                                                break inner; // V1 too low
+                                            if (var1[i] > v2)
+                                                break compare; // OK to subtract
+                                        }
+                                    }/* i */
+                                    /*
+                                     * reach here if lhs and rhs are identical; subtraction will increase digit by one,
+                                     * and the residue will be 0 so we are done; leave the loop with residue set to 0
+                                     * (in case code is 'R' or ROUND_UNNECESSARY or a ROUND_HALF_xxxx is being checked)
+                                     */
+                                    thisdigit++;
+                                    res.mant[have] = (byte) thisdigit;
+                                    have++;
+                                    var1[0] = (byte) 0; // residue to 0 [this is all we'll test]
+                                    // var1len=1 -- [optimized out]
+                                    break outer;
+                                } while (false);
+                            }/* compare */
+                            /* prepare for subtraction. Estimate BA (lengths the same) */
+                            ba = (int) var1[0]; // use only first digit
+                        } // lengths the same
+                        else {/* lhs longer than rhs */
+                            /* use first two digits for estimate */
+                            ba = var1[0] * 10;
+                            if (var1len > 1)
+                                ba = ba + var1[1];
+                        }
+                        /* subtraction needed; V1>=V2 */
+                        mult = (ba * 10) / b2b;
+                        if (mult == 0)
+                            mult = 1;
+                        thisdigit = thisdigit + mult;
+                        // subtract; var1 reusable
+                        var1 = byteaddsub(var1, var1len, var2, var2len, -mult, true);
+                        if (var1[0] != 0)
+                            continue inner; // maybe another subtract needed
+                        /*
+                         * V1 now probably has leading zeros, remove leading 0's and try again. (It could be longer than
+                         * V2)
+                         */
+                        {
+                            int $23 = var1len - 2;
+                            start = 0;
+                            start: for (; start <= $23; start++) {
+                                if (var1[start] != 0)
+                                    break start;
+                                var1len--;
+                            }
+                        }/* start */
+                        if (start == 0)
+                            continue inner;
+                        // shift left
+                        java.lang.System.arraycopy((java.lang.Object) var1, start, (java.lang.Object) var1, 0, var1len);
+                    }
+                }/* inner */
+
+                /* We have the next digit */
+                if ((have != 0) | (thisdigit != 0)) { // put the digit we got
+                    res.mant[have] = (byte) thisdigit;
+                    have++;
+                    if (have == (reqdig + 1))
+                        break outer; // we have all we need
+                    if (var1[0] == 0)
+                        break outer; // residue now 0
+                }
+                /* can leave now if a scaled divide and exponent is small enough */
+                if (scale >= 0)
+                    if (-res.exp > scale)
+                        break outer;
+                /* can leave now if not Divide and no integer part left */
+                if (code != 'D')
+                    if (res.exp <= 0)
+                        break outer;
+                res.exp = res.exp - 1; // reduce the exponent
+                /*
+                 * to get here, V1 is less than V2, so divide V2 by 10 and go for the next digit
+                 */
+                var2len--;
+            }
+        }/* outer */
+
+        /* here when we have finished dividing, for some reason */
+        // have is the number of digits we collected in res.mant
+        if (have == 0)
+            have = 1; // res.mant[0] is 0; we always want a digit
+
+        if ((code == 'I') | (code == 'R')) {/* check for integer overflow needed */
+            if ((have + res.exp) > reqdig)
+                throw new java.lang.ArithmeticException("Integer overflow");
+
+            if (code == 'R') {
+                do {
+                    /* We were doing Remainder -- return the residue */
+                    if (res.mant[0] == 0) // no integer part was found
+                        return clone(lhs).finish(set, false); // .. so return lhs, canonical
+                    if (var1[0] == 0)
+                        return ZERO; // simple 0 residue
+                    res.ind = lhs.ind; // sign is always as LHS
+                    /*
+                     * Calculate the exponent by subtracting the number of padding zeros we added and adding the
+                     * original exponent
+                     */
+                    padding = ((reqdig + reqdig) + 1) - lhs.mant.length;
+                    res.exp = (res.exp - padding) + lhs.exp;
+
+                    /*
+                     * strip insignificant padding zeros from residue, and create/copy the resulting mantissa if need be
+                     */
+                    d = var1len;
+                    {
+                        i = d - 1;
+                        i: for (; i >= 1; i--) {
+                            if (!((res.exp < lhs.exp) & (res.exp < rhs.exp)))
+                                break;
+                            if (var1[i] != 0)
+                                break i;
+                            d--;
+                            res.exp = res.exp + 1;
+                        }
+                    }/* i */
+                    if (d < var1.length) {/* need to reduce */
+                        newvar1 = new byte[d];
+                        java.lang.System.arraycopy((java.lang.Object) var1, 0, (java.lang.Object) newvar1, 0, d); // shorten
+                        var1 = newvar1;
+                    }
+                    res.mant = var1;
+                    return res.finish(set, false);
+                } while (false);
+            }/* remainder */
+        }
+
+        else {/* 'D' -- no overflow check needed */
+            // If there was a residue then bump the final digit (iff 0 or 5)
+            // so that the residue is visible for ROUND_UP, ROUND_HALF_xxx and
+            // ROUND_UNNECESSARY checks (etc.) later.
+            // [if we finished early, the residue will be 0]
+            if (var1[0] != 0) { // residue not 0
+                lasthave = res.mant[have - 1];
+                if (((lasthave % 5)) == 0)
+                    res.mant[have - 1] = (byte) (lasthave + 1);
+            }
+        }
+
+        /* Here for Divide or Integer Divide */
+        // handle scaled results first ['I' always scale 0, optional for 'D']
+        if (scale >= 0) {
+            do {
+                // say 'scale have res.exp len' scale have res.exp res.mant.length
+                if (have != res.mant.length)
+                    // already padded with 0's, so just adjust exponent
+                    res.exp = res.exp - ((res.mant.length - have));
+                // calculate number of digits we really want [may be 0]
+                actdig = res.mant.length - (-res.exp - scale);
+                res.round(actdig, set.roundingMode); // round to desired length
+                // This could have shifted left if round (say) 0.9->1[.0]
+                // Repair if so by adding a zero and reducing exponent
+                if (res.exp != -scale) {
+                    res.mant = extend(res.mant, res.mant.length + 1);
+                    res.exp = res.exp - 1;
+                }
+                return res.finish(set, true); // [strip if not PLAIN]
+            } while (false);
+        }/* scaled */
+
+        // reach here only if a non-scaled
+        if (have == res.mant.length) { // got digits+1 digits
+            res.round(set);
+            have = reqdig;
+        } else {/* have<=reqdig */
+            if (res.mant[0] == 0)
+                return ZERO; // fastpath
+            // make the mantissa truly just 'have' long
+            // [we could let finish do this, during strip, if we adjusted
+            // the exponent; however, truncation avoids the strip loop]
+            newmant = new byte[have]; // shorten
+            java.lang.System.arraycopy((java.lang.Object) res.mant, 0, (java.lang.Object) newmant, 0, have);
+            res.mant = newmant;
+        }
+        return res.finish(set, true);
+    }
+
+    /* <sgml> Report a conversion exception. </sgml> */
+
+    private void bad(char s[]) {
+        throw new java.lang.NumberFormatException("Not a number:" + " " + java.lang.String.valueOf(s));
+    }
+
+    /*
+     * <sgml> Report a bad argument to a method. </sgml> Arg1 is method name Arg2 is argument position Arg3 is what was
+     * found
+     */
+
+    private void badarg(java.lang.String name, int pos, java.lang.String value) {
+        throw new java.lang.IllegalArgumentException("Bad argument" + " " + pos + " " + "to" + " " + name + ":" + " "
+                + value);
+    }
+
+    /*
+     * <sgml> Extend byte array to given length, padding with 0s. If no extension is required then return the same
+     * array. </sgml>
+     * 
+     * Arg1 is the source byte array Arg2 is the new length (longer)
+     */
+
+    private static final byte[] extend(byte inarr[], int newlen) {
+        byte newarr[];
+        if (inarr.length == newlen)
+            return inarr;
+        newarr = new byte[newlen];
+        java.lang.System.arraycopy((java.lang.Object) inarr, 0, (java.lang.Object) newarr, 0, inarr.length);
+        // 0 padding is carried out by the JVM on allocation initialization
+        return newarr;
+    }
+
+    /*
+     * <sgml> Add or subtract two >=0 integers in byte arrays <p>This routine performs the calculation: <pre> C=A+(BM)
+     * </pre> Where M is in the range -9 through +9 <p> If M<0 then A>=B must be true, so the result is always
+     * non-negative.
+     * 
+     * Leading zeros are not removed after a subtraction. The result is either the same length as the longer of A and B,
+     * or 1 longer than that (if a carry occurred).
+     * 
+     * A is not altered unless Arg6 is 1. B is never altered.
+     * 
+     * Arg1 is A Arg2 is A length to use (if longer than A, pad with 0's) Arg3 is B Arg4 is B length to use (if longer
+     * than B, pad with 0's) Arg5 is M, the multiplier Arg6 is 1 if A can be used to build the result (if it fits)
+     * 
+     * This routine is severely performance-critical;any change here must be measured (timed) to assure no performance
+     * degradation.
+     */
+    // 1996.02.20 -- enhanced version of DMSRCN algorithm (1981)
+    // 1997.10.05 -- changed to byte arrays (from char arrays)
+    // 1998.07.01 -- changed to allow destructive reuse of LHS
+    // 1998.07.01 -- changed to allow virtual lengths for the arrays
+    // 1998.12.29 -- use lookaside for digit/carry calculation
+    // 1999.08.07 -- avoid multiply when mult=1, and make db an int
+    // 1999.12.22 -- special case m=-1, also drop 0 special case
+    private static final byte[] byteaddsub(byte a[], int avlen, byte b[], int bvlen, int m, boolean reuse) {
+        int alength;
+        int blength;
+        int ap;
+        int bp;
+        int maxarr;
+        byte reb[];
+        boolean quickm;
+        int digit;
+        int op = 0;
+        int dp90 = 0;
+        byte newarr[];
+        int i = 0;
+
+        // We'll usually be right if we assume no carry
+        alength = a.length; // physical lengths
+        blength = b.length; // ..
+        ap = avlen - 1; // -> final (rightmost) digit
+        bp = bvlen - 1; // ..
+        maxarr = bp;
+        if (maxarr < ap)
+            maxarr = ap;
+        reb = (byte[]) null; // result byte array
+        if (reuse)
+            if ((maxarr + 1) == alength)
+                reb = a; // OK to reuse A
+        if (reb == null)
+            reb = new byte[maxarr + 1]; // need new array
+
+        quickm = false; // 1 if no multiply needed
+        if (m == 1)
+            quickm = true; // most common
+        else if (m == (-1))
+            quickm = true; // also common
+
+        digit = 0; // digit, with carry or borrow
+        {
+            op = maxarr;
+            op: for (; op >= 0; op--) {
+                if (ap >= 0) {
+                    if (ap < alength)
+                        digit = digit + a[ap]; // within A
+                    ap--;
+                }
+                if (bp >= 0) {
+                    if (bp < blength) { // within B
+                        if (quickm) {
+                            if (m > 0)
+                                digit = digit + b[bp]; // most common
+                            else
+                                digit = digit - b[bp]; // also common
+                        } else
+                            digit = digit + (b[bp] * m);
+                    }
+                    bp--;
+                }
+                /* result so far (digit) could be -90 through 99 */
+                if (digit < 10)
+                    if (digit >= 0) {
+                        do { // 0-9
+                            reb[op] = (byte) digit;
+                            digit = 0; // no carry
+                            continue op;
+                        } while (false);
+                    }/* quick */
+                dp90 = digit + 90;
+                reb[op] = bytedig[dp90]; // this digit
+                digit = bytecar[dp90]; // carry or borrow
+            }
+        }/* op */
+
+        if (digit == 0)
+            return reb; // no carry
+        // following line will become an Assert, later
+        // if digit<0 then signal ArithmeticException("internal.error ["digit"]")
+
+        /* We have carry -- need to make space for the extra digit */
+        newarr = (byte[]) null;
+        if (reuse)
+            if ((maxarr + 2) == a.length)
+                newarr = a; // OK to reuse A
+        if (newarr == null)
+            newarr = new byte[maxarr + 2];
+        newarr[0] = (byte) digit; // the carried digit ..
+        // .. and all the rest [use local loop for short numbers]
+        if (maxarr < 10) {
+            int $24 = maxarr + 1;
+            i = 0;
+            for (; $24 > 0; $24--, i++) {
+                newarr[i + 1] = reb[i];
+            }
+        }/* i */
+        else
+            java.lang.System.arraycopy((java.lang.Object) reb, 0, (java.lang.Object) newarr, 1, maxarr + 1);
+        return newarr;
+    }
+
+    /*
+     * <sgml> Initializer for digit array properties (lookaside). </sgml> Returns the digit array, and initializes the
+     * carry array.
+     */
+
+    private static final byte[] diginit() {
+        byte work[];
+        int op = 0;
+        int digit = 0;
+        work = new byte[(90 + 99) + 1];
+        {
+            op = 0;
+            op: for (; op <= (90 + 99); op++) {
+                digit = op - 90;
+                if (digit >= 0) {
+                    work[op] = (byte) (digit % 10);
+                    bytecar[op] = (byte) (digit / 10); // calculate carry
+                    continue op;
+                }
+                // borrowing...
+                digit = digit + 100; // yes, this is right [consider -50]
+                work[op] = (byte) (digit % 10);
+                bytecar[op] = (byte) ((digit / 10) - 10); // calculate borrow [NB: - after %]
+            }
+        }/* op */
+        return work;
+    }
+
+    /*
+     * <sgml> Create a copy of BigDecimal object for local use. <p>This does NOT make a copy of the mantissa array.
+     * </sgml> Arg1 is the BigDecimal to clone (non-null)
+     */
+
+    private static final com.ibm.icu.math.BigDecimal clone(com.ibm.icu.math.BigDecimal dec) {
+        com.ibm.icu.math.BigDecimal copy;
+        copy = new com.ibm.icu.math.BigDecimal();
+        copy.ind = dec.ind;
+        copy.exp = dec.exp;
+        copy.form = dec.form;
+        copy.mant = dec.mant;
+        return copy;
+    }
+
+    /*
+     * <sgml> Check one or two numbers for lost digits. </sgml> Arg1 is RHS (or null, if none) Arg2 is current DIGITS
+     * setting returns quietly or throws an exception
+     */
+
+    private void checkdigits(com.ibm.icu.math.BigDecimal rhs, int dig) {
+        if (dig == 0)
+            return; // don't check if digits=0
+        // first check lhs...
+        if (this.mant.length > dig)
+            if ((!(allzero(this.mant, dig))))
+                throw new java.lang.ArithmeticException("Too many digits:" + " " + this.toString());
+        if (rhs == null)
+            return; // monadic
+        if (rhs.mant.length > dig)
+            if ((!(allzero(rhs.mant, dig))))
+                throw new java.lang.ArithmeticException("Too many digits:" + " " + rhs.toString());
+    }
+
+    /*
+     * <sgml> Round to specified digits, if necessary. </sgml> Arg1 is requested MathContext [with length and rounding
+     * mode] returns this, for convenience
+     */
+
+    private com.ibm.icu.math.BigDecimal round(com.ibm.icu.math.MathContext set) {
+        return round(set.digits, set.roundingMode);
+    }
+
+    /*
+     * <sgml> Round to specified digits, if necessary. Arg1 is requested length (digits to round to) [may be <=0 when
+     * called from format, dodivide, etc.] Arg2 is rounding mode returns this, for convenience
+     * 
+     * ind and exp are adjusted, but not cleared for a mantissa of zero
+     * 
+     * The length of the mantissa returned will be Arg1, except when Arg1 is 0, in which case the returned mantissa
+     * length will be 1. </sgml>
+     */
+
+    private com.ibm.icu.math.BigDecimal round(int len, int mode) {
+        int adjust;
+        int sign;
+        byte oldmant[];
+        boolean reuse = false;
+        byte first = 0;
+        int increment;
+        byte newmant[] = null;
+        adjust = mant.length - len;
+        if (adjust <= 0)
+            return this; // nowt to do
+
+        exp = exp + adjust; // exponent of result
+        sign = (int) ind; // save [assumes -1, 0, 1]
+        oldmant = mant; // save
+        if (len > 0) {
+            // remove the unwanted digits
+            mant = new byte[len];
+            java.lang.System.arraycopy((java.lang.Object) oldmant, 0, (java.lang.Object) mant, 0, len);
+            reuse = true; // can reuse mantissa
+            first = oldmant[len]; // first of discarded digits
+        } else {/* len<=0 */
+            mant = ZERO.mant;
+            ind = iszero;
+            reuse = false; // cannot reuse mantissa
+            if (len == 0)
+                first = oldmant[0];
+            else
+                first = (byte) 0; // [virtual digit]
+        }
+
+        // decide rounding adjustment depending on mode, sign, and discarded digits
+        increment = 0; // bumper
+        {
+            do {/* select */
+                if (mode == ROUND_HALF_UP) { // default first [most common]
+                    if (first >= 5)
+                        increment = sign;
+                } else if (mode == ROUND_UNNECESSARY) { // default for setScale()
+                    // discarding any non-zero digits is an error
+                    if ((!(allzero(oldmant, len))))
+                        throw new java.lang.ArithmeticException("Rounding necessary");
+                } else if (mode == ROUND_HALF_DOWN) { // 0.5000 goes down
+                    if (first > 5)
+                        increment = sign;
+                    else if (first == 5)
+                        if ((!(allzero(oldmant, len + 1))))
+                            increment = sign;
+                } else if (mode == ROUND_HALF_EVEN) { // 0.5000 goes down if left digit even
+                    if (first > 5)
+                        increment = sign;
+                    else if (first == 5) {
+                        if ((!(allzero(oldmant, len + 1))))
+                            increment = sign;
+                        else /* 0.5000 */
+                        if ((((mant[mant.length - 1]) % 2)) == 1)
+                            increment = sign;
+                    }
+                } else if (mode == ROUND_DOWN) {
+                    // never increment
+                } else if (mode == ROUND_UP) { // increment if discarded non-zero
+                    if ((!(allzero(oldmant, len))))
+                        increment = sign;
+                } else if (mode == ROUND_CEILING) { // more positive
+                    if (sign > 0)
+                        if ((!(allzero(oldmant, len))))
+                            increment = sign;
+                } else if (mode == ROUND_FLOOR) { // more negative
+                    if (sign < 0)
+                        if ((!(allzero(oldmant, len))))
+                            increment = sign;
+                } else {
+                    throw new java.lang.IllegalArgumentException("Bad round value:" + " " + mode);
+                }
+            } while (false);
+        }/* modes */
+
+        if (increment != 0) {
+            do {
+                if (ind == iszero) {
+                    // we must not subtract from 0, but result is trivial anyway
+                    mant = ONE.mant;
+                    ind = (byte) increment;
+                } else {
+                    // mantissa is non-0; we can safely add or subtract 1
+                    if (ind == isneg)
+                        increment = -increment;
+                    newmant = byteaddsub(mant, mant.length, ONE.mant, 1, increment, reuse);
+                    if (newmant.length > mant.length) { // had a carry
+                        // drop rightmost digit and raise exponent
+                        exp++;
+                        // mant is already the correct length
+                        java.lang.System.arraycopy((java.lang.Object) newmant, 0, (java.lang.Object) mant, 0,
+                                mant.length);
+                    } else
+                        mant = newmant;
+                }
+            } while (false);
+        }/* bump */
+        // rounding can increase exponent significantly
+        if (exp > MaxExp)
+            throw new java.lang.ArithmeticException("Exponent Overflow:" + " " + exp);
+        return this;
+    }
+
+    /*
+     * <sgml> Test if rightmost digits are all 0. Arg1 is a mantissa array to test Arg2 is the offset of first digit to
+     * check [may be negative; if so, digits to left are 0's] returns 1 if all the digits starting at Arg2 are 0
+     * 
+     * Arg2 may be beyond array bounds, in which case 1 is returned </sgml>
+     */
+
+    private static final boolean allzero(byte array[], int start) {
+        int i = 0;
+        if (start < 0)
+            start = 0;
+        {
+            int $25 = array.length - 1;
+            i = start;
+            for (; i <= $25; i++) {
+                if (array[i] != 0)
+                    return false;
+            }
+        }/* i */
+        return true;
+    }
+
+    /*
+     * <sgml> Carry out final checks and canonicalization <p> This finishes off the current number by: 1. Rounding if
+     * necessary (NB: length includes leading zeros) 2. Stripping trailing zeros (if requested and \PLAIN) 3. Stripping
+     * leading zeros (always) 4. Selecting exponential notation (if required) 5. Converting a zero result to just '0'
+     * (if \PLAIN) In practice, these operations overlap and share code. It always sets form. </sgml> Arg1 is requested
+     * MathContext (length to round to, trigger, and FORM) Arg2 is 1 if trailing insignificant zeros should be removed
+     * after round (for division, etc.), provided that set.form isn't PLAIN. returns this, for convenience
+     */
+
+    private com.ibm.icu.math.BigDecimal finish(com.ibm.icu.math.MathContext set, boolean strip) {
+        int d = 0;
+        int i = 0;
+        byte newmant[] = null;
+        int mag = 0;
+        int sig = 0;
+        /* Round if mantissa too long and digits requested */
+        if (set.digits != 0)
+            if (this.mant.length > set.digits)
+                this.round(set);
+
+        /*
+         * If strip requested (and standard formatting), remove insignificant trailing zeros.
+         */
+        if (strip)
+            if (set.form != com.ibm.icu.math.MathContext.PLAIN) {
+                d = this.mant.length;
+                /* see if we need to drop any trailing zeros */
+                {
+                    i = d - 1;
+                    i: for (; i >= 1; i--) {
+                        if (this.mant[i] != 0)
+                            break i;
+                        d--;
+                        exp++;
+                    }
+                }/* i */
+                if (d < this.mant.length) {/* need to reduce */
+                    newmant = new byte[d];
+                    java.lang.System.arraycopy((java.lang.Object) this.mant, 0, (java.lang.Object) newmant, 0, d);
+                    this.mant = newmant;
+                }
+            }
+
+        form = (byte) com.ibm.icu.math.MathContext.PLAIN; // preset
+
+        /* Now check for leading- and all- zeros in mantissa */
+        {
+            int $26 = this.mant.length;
+            i = 0;
+            for (; $26 > 0; $26--, i++) {
+                if (this.mant[i] != 0) {
+                    // non-0 result; ind will be correct
+                    // remove leading zeros [e.g., after subtract]
+                    if (i > 0) {
+                        do {
+                            newmant = new byte[this.mant.length - i];
+                            java.lang.System.arraycopy((java.lang.Object) this.mant, i, (java.lang.Object) newmant, 0,
+                                    this.mant.length - i);
+                            this.mant = newmant;
+                        } while (false);
+                    }/* delead */
+                    // now determine form if not PLAIN
+                    mag = exp + mant.length;
+                    if (mag > 0) { // most common path
+                        if (mag > set.digits)
+                            if (set.digits != 0)
+                                form = (byte) set.form;
+                        if ((mag - 1) <= MaxExp)
+                            return this; // no overflow; quick return
+                    } else if (mag < (-5))
+                        form = (byte) set.form;
+                    /* check for overflow */
+                    mag--;
+                    if ((mag < MinExp) | (mag > MaxExp)) {
+                        overflow: do {
+                            // possible reprieve if form is engineering
+                            if (form == com.ibm.icu.math.MathContext.ENGINEERING) {
+                                sig = mag % 3; // leftover
+                                if (sig < 0)
+                                    sig = 3 + sig; // negative exponent
+                                mag = mag - sig; // exponent to use
+                                // 1999.06.29: second test here must be MaxExp
+                                if (mag >= MinExp)
+                                    if (mag <= MaxExp)
+                                        break overflow;
+                            }
+                            throw new java.lang.ArithmeticException("Exponent Overflow:" + " " + mag);
+                        } while (false);
+                    }/* overflow */
+                    return this;
+                }
+            }
+        }/* i */
+
+        // Drop through to here only if mantissa is all zeros
+        ind = iszero;
+        {/* select */
+            if (set.form != com.ibm.icu.math.MathContext.PLAIN)
+                exp = 0; // standard result; go to '0'
+            else if (exp > 0)
+                exp = 0; // +ve exponent also goes to '0'
+            else {
+                // a plain number with -ve exponent; preserve and check exponent
+                if (exp < MinExp)
+                    throw new java.lang.ArithmeticException("Exponent Overflow:" + " " + exp);
+            }
+        }
+        mant = ZERO.mant; // canonical mantissa
+        return this;
+    }
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/math/MathContext.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/math/MathContext.java
index f7d2032..010c083 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/math/MathContext.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/math/MathContext.java
@@ -1,601 +1,601 @@
-/* Generated from 'MathContext.nrx' 8 Sep 2000 11:07:48 [v2.00] */
-/* Options: Binary Comments Crossref Format Java Logo Strictargs Strictcase Trace2 Verbose3 */
-package com.ibm.icu.math;
-
-/* ------------------------------------------------------------------ */
-/* MathContext -- Math context settings                               */
-/* ------------------------------------------------------------------ */
-/* Copyright IBM Corporation, 1997-2011.  All Rights Reserved.        */
-/*                                                                    */
-/*   The MathContext object encapsulates the settings used by the     */
-/*   BigDecimal class; it could also be used by other arithmetics.    */
-/* ------------------------------------------------------------------ */
-/* Notes:                                                             */
-/*                                                                    */
-/* 1. The properties are checked for validity on construction, so     */
-/*    the BigDecimal class may assume that they are correct.          */
-/* ------------------------------------------------------------------ */
-/* Author:    Mike Cowlishaw                                          */
-/* 1997.09.03 Initial version (edited from netrexx.lang.RexxSet)      */
-/* 1997.09.12 Add lostDigits property                                 */
-/* 1998.05.02 Make the class immutable and final; drop set methods    */
-/* 1998.06.05 Add Round (rounding modes) property                     */
-/* 1998.06.25 Rename from DecimalContext; allow digits=0              */
-/* 1998.10.12 change to com.ibm.icu.math package                          */
-/* 1999.02.06 add javadoc comments                                    */
-/* 1999.03.05 simplify; changes from discussion with J. Bloch         */
-/* 1999.03.13 1.00 release to IBM Centre for Java Technology          */
-/* 1999.07.10 1.04 flag serialization unused                          */
-/* 2000.01.01 1.06 copyright update                                   */
-/* ------------------------------------------------------------------ */
-
-
-
-
-/**
- * The <code>MathContext</code> immutable class encapsulates the
- * settings understood by the operator methods of the {@link BigDecimal}
- * class (and potentially other classes).  Operator methods are those
- * that effect an operation on a number or a pair of numbers.
- * <p>
- * The settings, which are not base-dependent, comprise:
- * <ol>
- * <li><code>digits</code>:
- * the number of digits (precision) to be used for an operation
- * <li><code>form</code>:
- * the form of any exponent that results from the operation
- * <li><code>lostDigits</code>:
- * whether checking for lost digits is enabled
- * <li><code>roundingMode</code>:
- * the algorithm to be used for rounding.
- * </ol>
- * <p>
- * When provided, a <code>MathContext</code> object supplies the
- * settings for an operation directly.
- * <p>
- * When <code>MathContext.DEFAULT</code> is provided for a
- * <code>MathContext</code> parameter then the default settings are used
- * (<code>9, SCIENTIFIC, false, ROUND_HALF_UP</code>).
- * <p>
- * In the <code>BigDecimal</code> class, all methods which accept a
- * <code>MathContext</code> object defaults) also have a version of the
- * method which does not accept a MathContext parameter.  These versions
- * carry out unlimited precision fixed point arithmetic (as though the
- * settings were (<code>0, PLAIN, false, ROUND_HALF_UP</code>).
- * <p>
- * The instance variables are shared with default access (so they are
- * directly accessible to the <code>BigDecimal</code> class), but must
- * never be changed.
- * <p>
- * The rounding mode constants have the same names and values as the
- * constants of the same name in <code>java.math.BigDecimal</code>, to
- * maintain compatibility with earlier versions of
- * <code>BigDecimal</code>.
- *
- * @see     BigDecimal
- * @author  Mike Cowlishaw
- * @stable ICU 2.0
- */
-
-public final class MathContext implements java.io.Serializable{
- //private static final java.lang.String $0="MathContext.nrx";
- 
- /* ----- Properties ----- */
- /* properties public constant */
- /**
-  * Plain (fixed point) notation, without any exponent.
-  * Used as a setting to control the form of the result of a
-  * <code>BigDecimal</code> operation.
-  * A zero result in plain form may have a decimal part of one or
-  * more zeros.
-  *
-  * @see #ENGINEERING
-  * @see #SCIENTIFIC
-  * @stable ICU 2.0
-  */
- public static final int PLAIN=0; // [no exponent]
- 
- /**
-  * Standard floating point notation (with scientific exponential
-  * format, where there is one digit before any decimal point).
-  * Used as a setting to control the form of the result of a
-  * <code>BigDecimal</code> operation.
-  * A zero result in plain form may have a decimal part of one or
-  * more zeros.
-  *
-  * @see #ENGINEERING
-  * @see #PLAIN
-  * @stable ICU 2.0
-  */
- public static final int SCIENTIFIC=1; // 1 digit before .
- 
- /**
-  * Standard floating point notation (with engineering exponential
-  * format, where the power of ten is a multiple of 3).
-  * Used as a setting to control the form of the result of a
-  * <code>BigDecimal</code> operation.
-  * A zero result in plain form may have a decimal part of one or
-  * more zeros.
-  *
-  * @see #PLAIN
-  * @see #SCIENTIFIC
-  * @stable ICU 2.0
-  */
- public static final int ENGINEERING=2; // 1-3 digits before .
- 
- // The rounding modes match the original BigDecimal class values
- /**
-  * Rounding mode to round to a more positive number.
-  * Used as a setting to control the rounding mode used during a
-  * <code>BigDecimal</code> operation.
-  * <p>
-  * If any of the discarded digits are non-zero then the result
-  * should be rounded towards the next more positive digit.
-  * @stable ICU 2.0
-  */
- public static final int ROUND_CEILING=2;
- 
- /**
-  * Rounding mode to round towards zero.
-  * Used as a setting to control the rounding mode used during a
-  * <code>BigDecimal</code> operation.
-  * <p>
-  * All discarded digits are ignored (truncated).  The result is
-  * neither incremented nor decremented.
-  * @stable ICU 2.0
-  */
- public static final int ROUND_DOWN=1;
- 
- /**
-  * Rounding mode to round to a more negative number.
-  * Used as a setting to control the rounding mode used during a
-  * <code>BigDecimal</code> operation.
-  * <p>
-  * If any of the discarded digits are non-zero then the result
-  * should be rounded towards the next more negative digit.
-  * @stable ICU 2.0
-  */
- public static final int ROUND_FLOOR=3;
- 
- /**
-  * Rounding mode to round to nearest neighbor, where an equidistant
-  * value is rounded down.
-  * Used as a setting to control the rounding mode used during a
-  * <code>BigDecimal</code> operation.
-  * <p>
-  * If the discarded digits represent greater than half (0.5 times)
-  * the value of a one in the next position then the result should be
-  * rounded up (away from zero).  Otherwise the discarded digits are
-  * ignored.
-  * @stable ICU 2.0
-  */
- public static final int ROUND_HALF_DOWN=5;
- 
- /**
-  * Rounding mode to round to nearest neighbor, where an equidistant
-  * value is rounded to the nearest even neighbor.
-  * Used as a setting to control the rounding mode used during a
-  * <code>BigDecimal</code> operation.
-  * <p>
-  * If the discarded digits represent greater than half (0.5 times)
-  * the value of a one in the next position then the result should be
-  * rounded up (away from zero).  If they represent less than half,
-  * then the result should be rounded down.
-  * <p>
-  * Otherwise (they represent exactly half) the result is rounded
-  * down if its rightmost digit is even, or rounded up if its
-  * rightmost digit is odd (to make an even digit).
-  * @stable ICU 2.0
-  */
- public static final int ROUND_HALF_EVEN=6;
- 
- /**
-  * Rounding mode to round to nearest neighbor, where an equidistant
-  * value is rounded up.
-  * Used as a setting to control the rounding mode used during a
-  * <code>BigDecimal</code> operation.
-  * <p>
-  * If the discarded digits represent greater than or equal to half
-  * (0.5 times) the value of a one in the next position then the result
-  * should be rounded up (away from zero).  Otherwise the discarded
-  * digits are ignored.
-  * @stable ICU 2.0
-  */
- public static final int ROUND_HALF_UP=4;
- 
- /**
-  * Rounding mode to assert that no rounding is necessary.
-  * Used as a setting to control the rounding mode used during a
-  * <code>BigDecimal</code> operation.
-  * <p>
-  * Rounding (potential loss of information) is not permitted.
-  * If any of the discarded digits are non-zero then an
-  * <code>ArithmeticException</code> should be thrown.
-  * @stable ICU 2.0
-  */
- public static final int ROUND_UNNECESSARY=7;
- 
- /**
-  * Rounding mode to round away from zero.
-  * Used as a setting to control the rounding mode used during a
-  * <code>BigDecimal</code> operation.
-  * <p>
-  * If any of the discarded digits are non-zero then the result will
-  * be rounded up (away from zero).
-  * @stable ICU 2.0
-  */
- public static final int ROUND_UP=0;
- 
- 
- /* properties shared */
- /**
-  * The number of digits (precision) to be used for an operation.
-  * A value of 0 indicates that unlimited precision (as many digits
-  * as are required) will be used.
-  * <p>
-  * The {@link BigDecimal} operator methods use this value to
-  * determine the precision of results.
-  * Note that leading zeros (in the integer part of a number) are
-  * never significant.
-  * <p>
-  * <code>digits</code> will always be non-negative.
-  *
-  * @serial
-  */
- int digits;
- 
- /**
-  * The form of results from an operation.
-  * <p>
-  * The {@link BigDecimal} operator methods use this value to
-  * determine the form of results, in particular whether and how
-  * exponential notation should be used.
-  *
-  * @see #ENGINEERING
-  * @see #PLAIN
-  * @see #SCIENTIFIC
-  * @serial
-  */
- int form; // values for this must fit in a byte
- 
- /**
-  * Controls whether lost digits checking is enabled for an
-  * operation.
-  * Set to <code>true</code> to enable checking, or
-  * to <code>false</code> to disable checking.
-  * <p>
-  * When enabled, the {@link BigDecimal} operator methods check
-  * the precision of their operand or operands, and throw an
-  * <code>ArithmeticException</code> if an operand is more precise
-  * than the digits setting (that is, digits would be lost).
-  * When disabled, operands are rounded to the specified digits.
-  *
-  * @serial
-  */
- boolean lostDigits;
- 
- /**
-  * The rounding algorithm to be used for an operation.
-  * <p>
-  * The {@link BigDecimal} operator methods use this value to
-  * determine the algorithm to be used when non-zero digits have to
-  * be discarded in order to reduce the precision of a result.
-  * The value must be one of the public constants whose name starts
-  * with <code>ROUND_</code>.
-  *
-  * @see #ROUND_CEILING
-  * @see #ROUND_DOWN
-  * @see #ROUND_FLOOR
-  * @see #ROUND_HALF_DOWN
-  * @see #ROUND_HALF_EVEN
-  * @see #ROUND_HALF_UP
-  * @see #ROUND_UNNECESSARY
-  * @see #ROUND_UP
-  * @serial
-  */
- int roundingMode;
- 
- /* properties private constant */
- // default settings
- private static final int DEFAULT_FORM=SCIENTIFIC;
- private static final int DEFAULT_DIGITS=9;
- private static final boolean DEFAULT_LOSTDIGITS=false;
- private static final int DEFAULT_ROUNDINGMODE=ROUND_HALF_UP;
- 
- /* properties private constant */
- 
- private static final int MIN_DIGITS=0; // smallest value for DIGITS.
- private static final int MAX_DIGITS=999999999; // largest value for DIGITS.  If increased,
- // the BigDecimal class may need update.
- // list of valid rounding mode values, most common two first
- private static final int ROUNDS[]=new int[]{ROUND_HALF_UP,ROUND_UNNECESSARY,ROUND_CEILING,ROUND_DOWN,ROUND_FLOOR,ROUND_HALF_DOWN,ROUND_HALF_EVEN,ROUND_UP};
- 
- 
- private static final java.lang.String ROUNDWORDS[]=new java.lang.String[]{"ROUND_HALF_UP","ROUND_UNNECESSARY","ROUND_CEILING","ROUND_DOWN","ROUND_FLOOR","ROUND_HALF_DOWN","ROUND_HALF_EVEN","ROUND_UP"}; // matching names of the ROUNDS values
- 
- 
- 
- 
- /* properties private constant unused */
- 
- // Serialization version
- private static final long serialVersionUID=7163376998892515376L;
- 
- /* properties public constant */
- /**
-  * A <code>MathContext</code> object initialized to the default
-  * settings for general-purpose arithmetic.  That is,
-  * <code>digits=9 form=SCIENTIFIC lostDigits=false
-  * roundingMode=ROUND_HALF_UP</code>.
-  *
-  * @see #SCIENTIFIC
-  * @see #ROUND_HALF_UP
-  * @stable ICU 2.0
-  */
- public static final com.ibm.icu.math.MathContext DEFAULT=new com.ibm.icu.math.MathContext(DEFAULT_DIGITS,DEFAULT_FORM,DEFAULT_LOSTDIGITS,DEFAULT_ROUNDINGMODE);
-
- 
- 
- 
- /* ----- Constructors ----- */
- 
- /**
-  * Constructs a new <code>MathContext</code> with a specified
-  * precision.
-  * The other settings are set to the default values
-  * (see {@link #DEFAULT}).
-  *
-  * An <code>IllegalArgumentException</code> is thrown if the
-  * <code>setdigits</code> parameter is out of range
-  * (&lt;0 or &gt;999999999).
-  *
-  * @param setdigits     The <code>int</code> digits setting
-  *                      for this <code>MathContext</code>.
-  * @throws IllegalArgumentException parameter out of range.
-  * @stable ICU 2.0
-  */
- 
- public MathContext(int setdigits){
-  this(setdigits,DEFAULT_FORM,DEFAULT_LOSTDIGITS,DEFAULT_ROUNDINGMODE);
-  return;}
-
- 
- /**
-  * Constructs a new <code>MathContext</code> with a specified
-  * precision and form.
-  * The other settings are set to the default values
-  * (see {@link #DEFAULT}).
-  *
-  * An <code>IllegalArgumentException</code> is thrown if the
-  * <code>setdigits</code> parameter is out of range
-  * (&lt;0 or &gt;999999999), or if the value given for the
-  * <code>setform</code> parameter is not one of the appropriate
-  * constants.
-  *
-  * @param setdigits     The <code>int</code> digits setting
-  *                      for this <code>MathContext</code>.
-  * @param setform       The <code>int</code> form setting
-  *                      for this <code>MathContext</code>.
-  * @throws IllegalArgumentException parameter out of range.
-  * @stable ICU 2.0
-  */
- 
- public MathContext(int setdigits,int setform){
-  this(setdigits,setform,DEFAULT_LOSTDIGITS,DEFAULT_ROUNDINGMODE);
-  return;}
-
- /**
-  * Constructs a new <code>MathContext</code> with a specified
-  * precision, form, and lostDigits setting.
-  * The roundingMode setting is set to its default value
-  * (see {@link #DEFAULT}).
-  *
-  * An <code>IllegalArgumentException</code> is thrown if the
-  * <code>setdigits</code> parameter is out of range
-  * (&lt;0 or &gt;999999999), or if the value given for the
-  * <code>setform</code> parameter is not one of the appropriate
-  * constants.
-  *
-  * @param setdigits     The <code>int</code> digits setting
-  *                      for this <code>MathContext</code>.
-  * @param setform       The <code>int</code> form setting
-  *                      for this <code>MathContext</code>.
-  * @param setlostdigits The <code>boolean</code> lostDigits
-  *                      setting for this <code>MathContext</code>.
-  * @throws IllegalArgumentException parameter out of range.
-  * @stable ICU 2.0
-  */
- 
- public MathContext(int setdigits,int setform,boolean setlostdigits){
-  this(setdigits,setform,setlostdigits,DEFAULT_ROUNDINGMODE);
-  return;}
-
- /**
-  * Constructs a new <code>MathContext</code> with a specified
-  * precision, form, lostDigits, and roundingMode setting.
-  *
-  * An <code>IllegalArgumentException</code> is thrown if the
-  * <code>setdigits</code> parameter is out of range
-  * (&lt;0 or &gt;999999999), or if the value given for the
-  * <code>setform</code> or <code>setroundingmode</code> parameters is
-  * not one of the appropriate constants.
-  *
-  * @param setdigits       The <code>int</code> digits setting
-  *                        for this <code>MathContext</code>.
-  * @param setform         The <code>int</code> form setting
-  *                        for this <code>MathContext</code>.
-  * @param setlostdigits   The <code>boolean</code> lostDigits
-  *                        setting for this <code>MathContext</code>.
-  * @param setroundingmode The <code>int</code> roundingMode setting
-  *                        for this <code>MathContext</code>.
-  * @throws IllegalArgumentException parameter out of range.
-  * @stable ICU 2.0
-  */
- 
- public MathContext(int setdigits,int setform,boolean setlostdigits,int setroundingmode){super();
-  
-  
-  // set values, after checking
-  if (setdigits!=DEFAULT_DIGITS) 
-   {
-    if (setdigits<MIN_DIGITS) 
-     throw new java.lang.IllegalArgumentException("Digits too small:"+" "+setdigits);
-    if (setdigits>MAX_DIGITS) 
-     throw new java.lang.IllegalArgumentException("Digits too large:"+" "+setdigits);
-   }
-  {/*select*/
-  if (setform==SCIENTIFIC){
-   // [most common]
-  }else if (setform==ENGINEERING){
-  }else if (setform==PLAIN){
-  }else{
-   throw new java.lang.IllegalArgumentException("Bad form value:"+" "+setform);
-  }
-  }
-  if ((!(isValidRound(setroundingmode)))) 
-   throw new java.lang.IllegalArgumentException("Bad roundingMode value:"+" "+setroundingmode);
-  digits=setdigits;
-  form=setform;
-  lostDigits=setlostdigits; // [no bad value possible]
-  roundingMode=setroundingmode;
-  return;}
-
- /**
-  * Returns the digits setting.
-  * This value is always non-negative.
-  *
-  * @return an <code>int</code> which is the value of the digits
-  *         setting
-  * @stable ICU 2.0
-  */
- 
- public int getDigits(){
-  return digits;
-  }
-
- /**
-  * Returns the form setting.
-  * This will be one of
-  * {@link #ENGINEERING},
-  * {@link #PLAIN}, or
-  * {@link #SCIENTIFIC}.
-  *
-  * @return an <code>int</code> which is the value of the form setting
-  * @stable ICU 2.0
-  */
- 
- public int getForm(){
-  return form;
-  }
-
- /**
-  * Returns the lostDigits setting.
-  * This will be either <code>true</code> (enabled) or
-  * <code>false</code> (disabled).
-  *
-  * @return a <code>boolean</code> which is the value of the lostDigits
-  *           setting
-  * @stable ICU 2.0
-  */
- 
- public boolean getLostDigits(){
-  return lostDigits;
-  }
-
- /**
-  * Returns the roundingMode setting.
-  * This will be one of
-  * {@link  #ROUND_CEILING},
-  * {@link  #ROUND_DOWN},
-  * {@link  #ROUND_FLOOR},
-  * {@link  #ROUND_HALF_DOWN},
-  * {@link  #ROUND_HALF_EVEN},
-  * {@link  #ROUND_HALF_UP},
-  * {@link  #ROUND_UNNECESSARY}, or
-  * {@link  #ROUND_UP}.
-  *
-  * @return an <code>int</code> which is the value of the roundingMode
-  *         setting
-  * @stable ICU 2.0
-  */
- 
- public int getRoundingMode(){
-  return roundingMode;
-  }
-
- /** Returns the <code>MathContext</code> as a readable string.
-  * The <code>String</code> returned represents the settings of the
-  * <code>MathContext</code> object as four blank-delimited words
-  * separated by a single blank and with no leading or trailing blanks,
-  * as follows:
-  * <ol>
-  * <li>
-  * <code>digits=</code>, immediately followed by
-  * the value of the digits setting as a numeric word.
-  * <li>
-  * <code>form=</code>, immediately followed by
-  * the value of the form setting as an uppercase word
-  * (one of <code>SCIENTIFIC</code>, <code>PLAIN</code>, or
-  * <code>ENGINEERING</code>).
-  * <li>
-  * <code>lostDigits=</code>, immediately followed by
-  * the value of the lostDigits setting
-  * (<code>1</code> if enabled, <code>0</code> if disabled).
-  * <li>
-  * <code>roundingMode=</code>, immediately followed by
-  * the value of the roundingMode setting as a word.
-  * This word will be the same as the name of the corresponding public
-  * constant.
-  * </ol>
-  * <p>
-  * For example:
-  * <br><code>
-  * digits=9 form=SCIENTIFIC lostDigits=0 roundingMode=ROUND_HALF_UP
-  * </code>
-  * <p>
-  * Additional words may be appended to the result of
-  * <code>toString</code> in the future if more properties are added
-  * to the class.
-  *
-  * @return a <code>String</code> representing the context settings.
-  * @stable ICU 2.0
-  */
- 
- public java.lang.String toString(){
-  java.lang.String formstr=null;
-  int r=0;
-  java.lang.String roundword=null;
-  {/*select*/
-  if (form==SCIENTIFIC)
-   formstr="SCIENTIFIC";
-  else if (form==ENGINEERING)
-   formstr="ENGINEERING";
-  else{
-   formstr="PLAIN";/* form=PLAIN */
-  }
-  }
-  {int $1=ROUNDS.length;r=0;r:for(;$1>0;$1--,r++){
-   if (roundingMode==ROUNDS[r]) 
-    {
-     roundword=ROUNDWORDS[r];
-     break r;
-    }
-   }
-  }/*r*/
-  return "digits="+digits+" "+"form="+formstr+" "+"lostDigits="+(lostDigits?"1":"0")+" "+"roundingMode="+roundword;
-  }
-
- 
- /* <sgml> Test whether round is valid. </sgml> */
- // This could be made shared for use by BigDecimal for setScale.
- 
- private static boolean isValidRound(int testround){
-  int r=0;
-  {int $2=ROUNDS.length;for(r=0;$2>0;$2--,r++){
-   if (testround==ROUNDS[r]) 
-    return true;
-   }
-  }/*r*/
-  return false;
-  }
- }
+/* Generated from 'MathContext.nrx' 8 Sep 2000 11:07:48 [v2.00] */
+/* Options: Binary Comments Crossref Format Java Logo Strictargs Strictcase Trace2 Verbose3 */
+package com.ibm.icu.math;
+
+/* ------------------------------------------------------------------ */
+/* MathContext -- Math context settings                               */
+/* ------------------------------------------------------------------ */
+/* Copyright IBM Corporation, 1997-2011.  All Rights Reserved.        */
+/*                                                                    */
+/*   The MathContext object encapsulates the settings used by the     */
+/*   BigDecimal class; it could also be used by other arithmetics.    */
+/* ------------------------------------------------------------------ */
+/* Notes:                                                             */
+/*                                                                    */
+/* 1. The properties are checked for validity on construction, so     */
+/*    the BigDecimal class may assume that they are correct.          */
+/* ------------------------------------------------------------------ */
+/* Author:    Mike Cowlishaw                                          */
+/* 1997.09.03 Initial version (edited from netrexx.lang.RexxSet)      */
+/* 1997.09.12 Add lostDigits property                                 */
+/* 1998.05.02 Make the class immutable and final; drop set methods    */
+/* 1998.06.05 Add Round (rounding modes) property                     */
+/* 1998.06.25 Rename from DecimalContext; allow digits=0              */
+/* 1998.10.12 change to com.ibm.icu.math package                          */
+/* 1999.02.06 add javadoc comments                                    */
+/* 1999.03.05 simplify; changes from discussion with J. Bloch         */
+/* 1999.03.13 1.00 release to IBM Centre for Java Technology          */
+/* 1999.07.10 1.04 flag serialization unused                          */
+/* 2000.01.01 1.06 copyright update                                   */
+/* ------------------------------------------------------------------ */
+
+
+
+
+/**
+ * The <code>MathContext</code> immutable class encapsulates the
+ * settings understood by the operator methods of the {@link BigDecimal}
+ * class (and potentially other classes).  Operator methods are those
+ * that effect an operation on a number or a pair of numbers.
+ * <p>
+ * The settings, which are not base-dependent, comprise:
+ * <ol>
+ * <li><code>digits</code>:
+ * the number of digits (precision) to be used for an operation
+ * <li><code>form</code>:
+ * the form of any exponent that results from the operation
+ * <li><code>lostDigits</code>:
+ * whether checking for lost digits is enabled
+ * <li><code>roundingMode</code>:
+ * the algorithm to be used for rounding.
+ * </ol>
+ * <p>
+ * When provided, a <code>MathContext</code> object supplies the
+ * settings for an operation directly.
+ * <p>
+ * When <code>MathContext.DEFAULT</code> is provided for a
+ * <code>MathContext</code> parameter then the default settings are used
+ * (<code>9, SCIENTIFIC, false, ROUND_HALF_UP</code>).
+ * <p>
+ * In the <code>BigDecimal</code> class, all methods which accept a
+ * <code>MathContext</code> object defaults) also have a version of the
+ * method which does not accept a MathContext parameter.  These versions
+ * carry out unlimited precision fixed point arithmetic (as though the
+ * settings were (<code>0, PLAIN, false, ROUND_HALF_UP</code>).
+ * <p>
+ * The instance variables are shared with default access (so they are
+ * directly accessible to the <code>BigDecimal</code> class), but must
+ * never be changed.
+ * <p>
+ * The rounding mode constants have the same names and values as the
+ * constants of the same name in <code>java.math.BigDecimal</code>, to
+ * maintain compatibility with earlier versions of
+ * <code>BigDecimal</code>.
+ *
+ * @see     BigDecimal
+ * @author  Mike Cowlishaw
+ * @stable ICU 2.0
+ */
+
+public final class MathContext implements java.io.Serializable{
+ //private static final java.lang.String $0="MathContext.nrx";
+ 
+ /* ----- Properties ----- */
+ /* properties public constant */
+ /**
+  * Plain (fixed point) notation, without any exponent.
+  * Used as a setting to control the form of the result of a
+  * <code>BigDecimal</code> operation.
+  * A zero result in plain form may have a decimal part of one or
+  * more zeros.
+  *
+  * @see #ENGINEERING
+  * @see #SCIENTIFIC
+  * @stable ICU 2.0
+  */
+ public static final int PLAIN=0; // [no exponent]
+ 
+ /**
+  * Standard floating point notation (with scientific exponential
+  * format, where there is one digit before any decimal point).
+  * Used as a setting to control the form of the result of a
+  * <code>BigDecimal</code> operation.
+  * A zero result in plain form may have a decimal part of one or
+  * more zeros.
+  *
+  * @see #ENGINEERING
+  * @see #PLAIN
+  * @stable ICU 2.0
+  */
+ public static final int SCIENTIFIC=1; // 1 digit before .
+ 
+ /**
+  * Standard floating point notation (with engineering exponential
+  * format, where the power of ten is a multiple of 3).
+  * Used as a setting to control the form of the result of a
+  * <code>BigDecimal</code> operation.
+  * A zero result in plain form may have a decimal part of one or
+  * more zeros.
+  *
+  * @see #PLAIN
+  * @see #SCIENTIFIC
+  * @stable ICU 2.0
+  */
+ public static final int ENGINEERING=2; // 1-3 digits before .
+ 
+ // The rounding modes match the original BigDecimal class values
+ /**
+  * Rounding mode to round to a more positive number.
+  * Used as a setting to control the rounding mode used during a
+  * <code>BigDecimal</code> operation.
+  * <p>
+  * If any of the discarded digits are non-zero then the result
+  * should be rounded towards the next more positive digit.
+  * @stable ICU 2.0
+  */
+ public static final int ROUND_CEILING=2;
+ 
+ /**
+  * Rounding mode to round towards zero.
+  * Used as a setting to control the rounding mode used during a
+  * <code>BigDecimal</code> operation.
+  * <p>
+  * All discarded digits are ignored (truncated).  The result is
+  * neither incremented nor decremented.
+  * @stable ICU 2.0
+  */
+ public static final int ROUND_DOWN=1;
+ 
+ /**
+  * Rounding mode to round to a more negative number.
+  * Used as a setting to control the rounding mode used during a
+  * <code>BigDecimal</code> operation.
+  * <p>
+  * If any of the discarded digits are non-zero then the result
+  * should be rounded towards the next more negative digit.
+  * @stable ICU 2.0
+  */
+ public static final int ROUND_FLOOR=3;
+ 
+ /**
+  * Rounding mode to round to nearest neighbor, where an equidistant
+  * value is rounded down.
+  * Used as a setting to control the rounding mode used during a
+  * <code>BigDecimal</code> operation.
+  * <p>
+  * If the discarded digits represent greater than half (0.5 times)
+  * the value of a one in the next position then the result should be
+  * rounded up (away from zero).  Otherwise the discarded digits are
+  * ignored.
+  * @stable ICU 2.0
+  */
+ public static final int ROUND_HALF_DOWN=5;
+ 
+ /**
+  * Rounding mode to round to nearest neighbor, where an equidistant
+  * value is rounded to the nearest even neighbor.
+  * Used as a setting to control the rounding mode used during a
+  * <code>BigDecimal</code> operation.
+  * <p>
+  * If the discarded digits represent greater than half (0.5 times)
+  * the value of a one in the next position then the result should be
+  * rounded up (away from zero).  If they represent less than half,
+  * then the result should be rounded down.
+  * <p>
+  * Otherwise (they represent exactly half) the result is rounded
+  * down if its rightmost digit is even, or rounded up if its
+  * rightmost digit is odd (to make an even digit).
+  * @stable ICU 2.0
+  */
+ public static final int ROUND_HALF_EVEN=6;
+ 
+ /**
+  * Rounding mode to round to nearest neighbor, where an equidistant
+  * value is rounded up.
+  * Used as a setting to control the rounding mode used during a
+  * <code>BigDecimal</code> operation.
+  * <p>
+  * If the discarded digits represent greater than or equal to half
+  * (0.5 times) the value of a one in the next position then the result
+  * should be rounded up (away from zero).  Otherwise the discarded
+  * digits are ignored.
+  * @stable ICU 2.0
+  */
+ public static final int ROUND_HALF_UP=4;
+ 
+ /**
+  * Rounding mode to assert that no rounding is necessary.
+  * Used as a setting to control the rounding mode used during a
+  * <code>BigDecimal</code> operation.
+  * <p>
+  * Rounding (potential loss of information) is not permitted.
+  * If any of the discarded digits are non-zero then an
+  * <code>ArithmeticException</code> should be thrown.
+  * @stable ICU 2.0
+  */
+ public static final int ROUND_UNNECESSARY=7;
+ 
+ /**
+  * Rounding mode to round away from zero.
+  * Used as a setting to control the rounding mode used during a
+  * <code>BigDecimal</code> operation.
+  * <p>
+  * If any of the discarded digits are non-zero then the result will
+  * be rounded up (away from zero).
+  * @stable ICU 2.0
+  */
+ public static final int ROUND_UP=0;
+ 
+ 
+ /* properties shared */
+ /**
+  * The number of digits (precision) to be used for an operation.
+  * A value of 0 indicates that unlimited precision (as many digits
+  * as are required) will be used.
+  * <p>
+  * The {@link BigDecimal} operator methods use this value to
+  * determine the precision of results.
+  * Note that leading zeros (in the integer part of a number) are
+  * never significant.
+  * <p>
+  * <code>digits</code> will always be non-negative.
+  *
+  * @serial
+  */
+ int digits;
+ 
+ /**
+  * The form of results from an operation.
+  * <p>
+  * The {@link BigDecimal} operator methods use this value to
+  * determine the form of results, in particular whether and how
+  * exponential notation should be used.
+  *
+  * @see #ENGINEERING
+  * @see #PLAIN
+  * @see #SCIENTIFIC
+  * @serial
+  */
+ int form; // values for this must fit in a byte
+ 
+ /**
+  * Controls whether lost digits checking is enabled for an
+  * operation.
+  * Set to <code>true</code> to enable checking, or
+  * to <code>false</code> to disable checking.
+  * <p>
+  * When enabled, the {@link BigDecimal} operator methods check
+  * the precision of their operand or operands, and throw an
+  * <code>ArithmeticException</code> if an operand is more precise
+  * than the digits setting (that is, digits would be lost).
+  * When disabled, operands are rounded to the specified digits.
+  *
+  * @serial
+  */
+ boolean lostDigits;
+ 
+ /**
+  * The rounding algorithm to be used for an operation.
+  * <p>
+  * The {@link BigDecimal} operator methods use this value to
+  * determine the algorithm to be used when non-zero digits have to
+  * be discarded in order to reduce the precision of a result.
+  * The value must be one of the public constants whose name starts
+  * with <code>ROUND_</code>.
+  *
+  * @see #ROUND_CEILING
+  * @see #ROUND_DOWN
+  * @see #ROUND_FLOOR
+  * @see #ROUND_HALF_DOWN
+  * @see #ROUND_HALF_EVEN
+  * @see #ROUND_HALF_UP
+  * @see #ROUND_UNNECESSARY
+  * @see #ROUND_UP
+  * @serial
+  */
+ int roundingMode;
+ 
+ /* properties private constant */
+ // default settings
+ private static final int DEFAULT_FORM=SCIENTIFIC;
+ private static final int DEFAULT_DIGITS=9;
+ private static final boolean DEFAULT_LOSTDIGITS=false;
+ private static final int DEFAULT_ROUNDINGMODE=ROUND_HALF_UP;
+ 
+ /* properties private constant */
+ 
+ private static final int MIN_DIGITS=0; // smallest value for DIGITS.
+ private static final int MAX_DIGITS=999999999; // largest value for DIGITS.  If increased,
+ // the BigDecimal class may need update.
+ // list of valid rounding mode values, most common two first
+ private static final int ROUNDS[]=new int[]{ROUND_HALF_UP,ROUND_UNNECESSARY,ROUND_CEILING,ROUND_DOWN,ROUND_FLOOR,ROUND_HALF_DOWN,ROUND_HALF_EVEN,ROUND_UP};
+ 
+ 
+ private static final java.lang.String ROUNDWORDS[]=new java.lang.String[]{"ROUND_HALF_UP","ROUND_UNNECESSARY","ROUND_CEILING","ROUND_DOWN","ROUND_FLOOR","ROUND_HALF_DOWN","ROUND_HALF_EVEN","ROUND_UP"}; // matching names of the ROUNDS values
+ 
+ 
+ 
+ 
+ /* properties private constant unused */
+ 
+ // Serialization version
+ private static final long serialVersionUID=7163376998892515376L;
+ 
+ /* properties public constant */
+ /**
+  * A <code>MathContext</code> object initialized to the default
+  * settings for general-purpose arithmetic.  That is,
+  * <code>digits=9 form=SCIENTIFIC lostDigits=false
+  * roundingMode=ROUND_HALF_UP</code>.
+  *
+  * @see #SCIENTIFIC
+  * @see #ROUND_HALF_UP
+  * @stable ICU 2.0
+  */
+ public static final com.ibm.icu.math.MathContext DEFAULT=new com.ibm.icu.math.MathContext(DEFAULT_DIGITS,DEFAULT_FORM,DEFAULT_LOSTDIGITS,DEFAULT_ROUNDINGMODE);
+
+ 
+ 
+ 
+ /* ----- Constructors ----- */
+ 
+ /**
+  * Constructs a new <code>MathContext</code> with a specified
+  * precision.
+  * The other settings are set to the default values
+  * (see {@link #DEFAULT}).
+  *
+  * An <code>IllegalArgumentException</code> is thrown if the
+  * <code>setdigits</code> parameter is out of range
+  * (&lt;0 or &gt;999999999).
+  *
+  * @param setdigits     The <code>int</code> digits setting
+  *                      for this <code>MathContext</code>.
+  * @throws IllegalArgumentException parameter out of range.
+  * @stable ICU 2.0
+  */
+ 
+ public MathContext(int setdigits){
+  this(setdigits,DEFAULT_FORM,DEFAULT_LOSTDIGITS,DEFAULT_ROUNDINGMODE);
+  return;}
+
+ 
+ /**
+  * Constructs a new <code>MathContext</code> with a specified
+  * precision and form.
+  * The other settings are set to the default values
+  * (see {@link #DEFAULT}).
+  *
+  * An <code>IllegalArgumentException</code> is thrown if the
+  * <code>setdigits</code> parameter is out of range
+  * (&lt;0 or &gt;999999999), or if the value given for the
+  * <code>setform</code> parameter is not one of the appropriate
+  * constants.
+  *
+  * @param setdigits     The <code>int</code> digits setting
+  *                      for this <code>MathContext</code>.
+  * @param setform       The <code>int</code> form setting
+  *                      for this <code>MathContext</code>.
+  * @throws IllegalArgumentException parameter out of range.
+  * @stable ICU 2.0
+  */
+ 
+ public MathContext(int setdigits,int setform){
+  this(setdigits,setform,DEFAULT_LOSTDIGITS,DEFAULT_ROUNDINGMODE);
+  return;}
+
+ /**
+  * Constructs a new <code>MathContext</code> with a specified
+  * precision, form, and lostDigits setting.
+  * The roundingMode setting is set to its default value
+  * (see {@link #DEFAULT}).
+  *
+  * An <code>IllegalArgumentException</code> is thrown if the
+  * <code>setdigits</code> parameter is out of range
+  * (&lt;0 or &gt;999999999), or if the value given for the
+  * <code>setform</code> parameter is not one of the appropriate
+  * constants.
+  *
+  * @param setdigits     The <code>int</code> digits setting
+  *                      for this <code>MathContext</code>.
+  * @param setform       The <code>int</code> form setting
+  *                      for this <code>MathContext</code>.
+  * @param setlostdigits The <code>boolean</code> lostDigits
+  *                      setting for this <code>MathContext</code>.
+  * @throws IllegalArgumentException parameter out of range.
+  * @stable ICU 2.0
+  */
+ 
+ public MathContext(int setdigits,int setform,boolean setlostdigits){
+  this(setdigits,setform,setlostdigits,DEFAULT_ROUNDINGMODE);
+  return;}
+
+ /**
+  * Constructs a new <code>MathContext</code> with a specified
+  * precision, form, lostDigits, and roundingMode setting.
+  *
+  * An <code>IllegalArgumentException</code> is thrown if the
+  * <code>setdigits</code> parameter is out of range
+  * (&lt;0 or &gt;999999999), or if the value given for the
+  * <code>setform</code> or <code>setroundingmode</code> parameters is
+  * not one of the appropriate constants.
+  *
+  * @param setdigits       The <code>int</code> digits setting
+  *                        for this <code>MathContext</code>.
+  * @param setform         The <code>int</code> form setting
+  *                        for this <code>MathContext</code>.
+  * @param setlostdigits   The <code>boolean</code> lostDigits
+  *                        setting for this <code>MathContext</code>.
+  * @param setroundingmode The <code>int</code> roundingMode setting
+  *                        for this <code>MathContext</code>.
+  * @throws IllegalArgumentException parameter out of range.
+  * @stable ICU 2.0
+  */
+ 
+ public MathContext(int setdigits,int setform,boolean setlostdigits,int setroundingmode){super();
+  
+  
+  // set values, after checking
+  if (setdigits!=DEFAULT_DIGITS) 
+   {
+    if (setdigits<MIN_DIGITS) 
+     throw new java.lang.IllegalArgumentException("Digits too small:"+" "+setdigits);
+    if (setdigits>MAX_DIGITS) 
+     throw new java.lang.IllegalArgumentException("Digits too large:"+" "+setdigits);
+   }
+  {/*select*/
+  if (setform==SCIENTIFIC){
+   // [most common]
+  }else if (setform==ENGINEERING){
+  }else if (setform==PLAIN){
+  }else{
+   throw new java.lang.IllegalArgumentException("Bad form value:"+" "+setform);
+  }
+  }
+  if ((!(isValidRound(setroundingmode)))) 
+   throw new java.lang.IllegalArgumentException("Bad roundingMode value:"+" "+setroundingmode);
+  digits=setdigits;
+  form=setform;
+  lostDigits=setlostdigits; // [no bad value possible]
+  roundingMode=setroundingmode;
+  return;}
+
+ /**
+  * Returns the digits setting.
+  * This value is always non-negative.
+  *
+  * @return an <code>int</code> which is the value of the digits
+  *         setting
+  * @stable ICU 2.0
+  */
+ 
+ public int getDigits(){
+  return digits;
+  }
+
+ /**
+  * Returns the form setting.
+  * This will be one of
+  * {@link #ENGINEERING},
+  * {@link #PLAIN}, or
+  * {@link #SCIENTIFIC}.
+  *
+  * @return an <code>int</code> which is the value of the form setting
+  * @stable ICU 2.0
+  */
+ 
+ public int getForm(){
+  return form;
+  }
+
+ /**
+  * Returns the lostDigits setting.
+  * This will be either <code>true</code> (enabled) or
+  * <code>false</code> (disabled).
+  *
+  * @return a <code>boolean</code> which is the value of the lostDigits
+  *           setting
+  * @stable ICU 2.0
+  */
+ 
+ public boolean getLostDigits(){
+  return lostDigits;
+  }
+
+ /**
+  * Returns the roundingMode setting.
+  * This will be one of
+  * {@link  #ROUND_CEILING},
+  * {@link  #ROUND_DOWN},
+  * {@link  #ROUND_FLOOR},
+  * {@link  #ROUND_HALF_DOWN},
+  * {@link  #ROUND_HALF_EVEN},
+  * {@link  #ROUND_HALF_UP},
+  * {@link  #ROUND_UNNECESSARY}, or
+  * {@link  #ROUND_UP}.
+  *
+  * @return an <code>int</code> which is the value of the roundingMode
+  *         setting
+  * @stable ICU 2.0
+  */
+ 
+ public int getRoundingMode(){
+  return roundingMode;
+  }
+
+ /** Returns the <code>MathContext</code> as a readable string.
+  * The <code>String</code> returned represents the settings of the
+  * <code>MathContext</code> object as four blank-delimited words
+  * separated by a single blank and with no leading or trailing blanks,
+  * as follows:
+  * <ol>
+  * <li>
+  * <code>digits=</code>, immediately followed by
+  * the value of the digits setting as a numeric word.
+  * <li>
+  * <code>form=</code>, immediately followed by
+  * the value of the form setting as an uppercase word
+  * (one of <code>SCIENTIFIC</code>, <code>PLAIN</code>, or
+  * <code>ENGINEERING</code>).
+  * <li>
+  * <code>lostDigits=</code>, immediately followed by
+  * the value of the lostDigits setting
+  * (<code>1</code> if enabled, <code>0</code> if disabled).
+  * <li>
+  * <code>roundingMode=</code>, immediately followed by
+  * the value of the roundingMode setting as a word.
+  * This word will be the same as the name of the corresponding public
+  * constant.
+  * </ol>
+  * <p>
+  * For example:
+  * <br><code>
+  * digits=9 form=SCIENTIFIC lostDigits=0 roundingMode=ROUND_HALF_UP
+  * </code>
+  * <p>
+  * Additional words may be appended to the result of
+  * <code>toString</code> in the future if more properties are added
+  * to the class.
+  *
+  * @return a <code>String</code> representing the context settings.
+  * @stable ICU 2.0
+  */
+ 
+ public java.lang.String toString(){
+  java.lang.String formstr=null;
+  int r=0;
+  java.lang.String roundword=null;
+  {/*select*/
+  if (form==SCIENTIFIC)
+   formstr="SCIENTIFIC";
+  else if (form==ENGINEERING)
+   formstr="ENGINEERING";
+  else{
+   formstr="PLAIN";/* form=PLAIN */
+  }
+  }
+  {int $1=ROUNDS.length;r=0;r:for(;$1>0;$1--,r++){
+   if (roundingMode==ROUNDS[r]) 
+    {
+     roundword=ROUNDWORDS[r];
+     break r;
+    }
+   }
+  }/*r*/
+  return "digits="+digits+" "+"form="+formstr+" "+"lostDigits="+(lostDigits?"1":"0")+" "+"roundingMode="+roundword;
+  }
+
+ 
+ /* <sgml> Test whether round is valid. </sgml> */
+ // This could be made shared for use by BigDecimal for setScale.
+ 
+ private static boolean isValidRound(int testround){
+  int r=0;
+  {int $2=ROUNDS.length;for(r=0;$2>0;$2--,r++){
+   if (testround==ROUNDS[r]) 
+    return true;
+   }
+  }/*r*/
+  return false;
+  }
+ }
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/Bidi.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/Bidi.java
index cb72af4..c37d385 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/Bidi.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/Bidi.java
@@ -1,2586 +1,2586 @@
-/*
-*******************************************************************************
-*   Copyright (C) 2001-2011, International Business Machines
-*   Corporation and others.  All Rights Reserved.
-*******************************************************************************
-*/
-
-/* FOOD FOR THOUGHT: currently the reordering modes are a mixture of
- * algorithm for direct BiDi, algorithm for inverse Bidi and the bizarre
- * concept of RUNS_ONLY which is a double operation.
- * It could be advantageous to divide this into 3 concepts:
- * a) Operation: direct / inverse / RUNS_ONLY
- * b) Direct algorithm: default / NUMBERS_SPECIAL / GROUP_NUMBERS_WITH_L
- * c) Inverse algorithm: default / INVERSE_LIKE_DIRECT / NUMBERS_SPECIAL
- * This would allow combinations not possible today like RUNS_ONLY with
- * NUMBERS_SPECIAL.
- * Also allow to set INSERT_MARKS for the direct step of RUNS_ONLY and
- * REMOVE_CONTROLS for the inverse step.
- * Not all combinations would be supported, and probably not all do make sense.
- * This would need to document which ones are supported and what are the
- * fallbacks for unsupported combinations.
- */
-
-//TODO: make sample program do something simple but real and complete
-
-package com.ibm.icu.text;
-
-import java.text.AttributedCharacterIterator;
-
-/**
- *
- * <h2>Bidi algorithm for ICU</h2>
- *
- * This is an implementation of the Unicode Bidirectional algorithm. The
- * algorithm is defined in the <a
- * href="http://www.unicode.org/unicode/reports/tr9/">Unicode Standard Annex #9</a>,
- * version 13, also described in The Unicode Standard, Version 4.0 .
- * <p>
- *
- * Note: Libraries that perform a bidirectional algorithm and reorder strings
- * accordingly are sometimes called "Storage Layout Engines". ICU's Bidi and
- * shaping (ArabicShaping) classes can be used at the core of such "Storage
- * Layout Engines".
- *
- * <h3>General remarks about the API:</h3>
- *
- * The &quot;limit&quot; of a sequence of characters is the position just after
- * their last character, i.e., one more than that position.
- * <p>
- *
- * Some of the API methods provide access to &quot;runs&quot;. Such a
- * &quot;run&quot; is defined as a sequence of characters that are at the same
- * embedding level after performing the Bidi algorithm.
- * <p>
- *
- * <h3>Basic concept: paragraph</h3>
- * A piece of text can be divided into several paragraphs by characters
- * with the Bidi class <code>Block Separator</code>. For handling of
- * paragraphs, see:
- * <ul>
- * <li>{@link #countParagraphs}
- * <li>{@link #getParaLevel}
- * <li>{@link #getParagraph}
- * <li>{@link #getParagraphByIndex}
- * </ul>
- *
- * <h3>Basic concept: text direction</h3>
- * The direction of a piece of text may be:
- * <ul>
- * <li>{@link #LTR}
- * <li>{@link #RTL}
- * <li>{@link #MIXED}
- * </ul>
- *
- * <h3>Basic concept: levels</h3>
- *
- * Levels in this API represent embedding levels according to the Unicode
- * Bidirectional Algorithm.
- * Their low-order bit (even/odd value) indicates the visual direction.<p>
- *
- * Levels can be abstract values when used for the
- * <code>paraLevel</code> and <code>embeddingLevels</code>
- * arguments of <code>setPara()</code>; there:
- * <ul>
- * <li>the high-order bit of an <code>embeddingLevels[]</code>
- * value indicates whether the using application is
- * specifying the level of a character to <i>override</i> whatever the
- * Bidi implementation would resolve it to.</li>
- * <li><code>paraLevel</code> can be set to the
- * pseudo-level values <code>LEVEL_DEFAULT_LTR</code>
- * and <code>LEVEL_DEFAULT_RTL</code>.</li>
- * </ul>
- *
- * <p>The related constants are not real, valid level values.
- * <code>DEFAULT_XXX</code> can be used to specify
- * a default for the paragraph level for
- * when the <code>setPara()</code> method
- * shall determine it but there is no
- * strongly typed character in the input.<p>
- *
- * Note that the value for <code>LEVEL_DEFAULT_LTR</code> is even
- * and the one for <code>LEVEL_DEFAULT_RTL</code> is odd,
- * just like with normal LTR and RTL level values -
- * these special values are designed that way. Also, the implementation
- * assumes that MAX_EXPLICIT_LEVEL is odd.
- *
- * <ul><b>See Also:</b>
- * <li>{@link #LEVEL_DEFAULT_LTR}
- * <li>{@link #LEVEL_DEFAULT_RTL}
- * <li>{@link #LEVEL_OVERRIDE}
- * <li>{@link #MAX_EXPLICIT_LEVEL}
- * <li>{@link #setPara}
- * </ul>
- *
- * <h3>Basic concept: Reordering Mode</h3>
- * Reordering mode values indicate which variant of the Bidi algorithm to
- * use.
- *
- * <ul><b>See Also:</b>
- * <li>{@link #setReorderingMode}
- * <li>{@link #REORDER_DEFAULT}
- * <li>{@link #REORDER_NUMBERS_SPECIAL}
- * <li>{@link #REORDER_GROUP_NUMBERS_WITH_R}
- * <li>{@link #REORDER_RUNS_ONLY}
- * <li>{@link #REORDER_INVERSE_NUMBERS_AS_L}
- * <li>{@link #REORDER_INVERSE_LIKE_DIRECT}
- * <li>{@link #REORDER_INVERSE_FOR_NUMBERS_SPECIAL}
- * </ul>
- *
- * <h3>Basic concept: Reordering Options</h3>
- * Reordering options can be applied during Bidi text transformations.
- * <ul><b>See Also:</b>
- * <li>{@link #setReorderingOptions}
- * <li>{@link #OPTION_DEFAULT}
- * <li>{@link #OPTION_INSERT_MARKS}
- * <li>{@link #OPTION_REMOVE_CONTROLS}
- * <li>{@link #OPTION_STREAMING}
- * </ul>
- *
- *
- * @author Simon Montagu, Matitiahu Allouche (ported from C code written by Markus W. Scherer)
- * @stable ICU 3.8
- *
- *
- * <h4> Sample code for the ICU Bidi API </h4>
- *
- * <h5>Rendering a paragraph with the ICU Bidi API</h5>
- *
- * This is (hypothetical) sample code that illustrates how the ICU Bidi API
- * could be used to render a paragraph of text. Rendering code depends highly on
- * the graphics system, therefore this sample code must make a lot of
- * assumptions, which may or may not match any existing graphics system's
- * properties.
- *
- * <p>
- * The basic assumptions are:
- * </p>
- * <ul>
- * <li>Rendering is done from left to right on a horizontal line.</li>
- * <li>A run of single-style, unidirectional text can be rendered at once.
- * </li>
- * <li>Such a run of text is passed to the graphics system with characters
- * (code units) in logical order.</li>
- * <li>The line-breaking algorithm is very complicated and Locale-dependent -
- * and therefore its implementation omitted from this sample code.</li>
- * </ul>
- *
- * <pre>
- *
- *  package com.ibm.icu.dev.test.bidi;
- *
- *  import com.ibm.icu.text.Bidi;
- *  import com.ibm.icu.text.BidiRun;
- *
- *  public class Sample {
- *
- *      static final int styleNormal = 0;
- *      static final int styleSelected = 1;
- *      static final int styleBold = 2;
- *      static final int styleItalics = 4;
- *      static final int styleSuper=8;
- *      static final int styleSub = 16;
- *
- *      static class StyleRun {
- *          int limit;
- *          int style;
- *
- *          public StyleRun(int limit, int style) {
- *              this.limit = limit;
- *              this.style = style;
- *          }
- *      }
- *
- *      static class Bounds {
- *          int start;
- *          int limit;
- *
- *          public Bounds(int start, int limit) {
- *              this.start = start;
- *              this.limit = limit;
- *          }
- *      }
- *
- *      static int getTextWidth(String text, int start, int limit,
- *                              StyleRun[] styleRuns, int styleRunCount) {
- *          // simplistic way to compute the width
- *          return limit - start;
- *      }
- *
- *      // set limit and StyleRun limit for a line
- *      // from text[start] and from styleRuns[styleRunStart]
- *      // using Bidi.getLogicalRun(...)
- *      // returns line width
- *      static int getLineBreak(String text, Bounds line, Bidi para,
- *                              StyleRun styleRuns[], Bounds styleRun) {
- *          // dummy return
- *          return 0;
- *      }
- *
- *      // render runs on a line sequentially, always from left to right
- *
- *      // prepare rendering a new line
- *      static void startLine(byte textDirection, int lineWidth) {
- *          System.out.println();
- *      }
- *
- *      // render a run of text and advance to the right by the run width
- *      // the text[start..limit-1] is always in logical order
- *      static void renderRun(String text, int start, int limit,
- *                            byte textDirection, int style) {
- *      }
- *
- *      // We could compute a cross-product
- *      // from the style runs with the directional runs
- *      // and then reorder it.
- *      // Instead, here we iterate over each run type
- *      // and render the intersections -
- *      // with shortcuts in simple (and common) cases.
- *      // renderParagraph() is the main function.
- *
- *      // render a directional run with
- *      // (possibly) multiple style runs intersecting with it
- *      static void renderDirectionalRun(String text, int start, int limit,
- *                                       byte direction, StyleRun styleRuns[],
- *                                       int styleRunCount) {
- *          int i;
- *
- *          // iterate over style runs
- *          if (direction == Bidi.LTR) {
- *              int styleLimit;
- *              for (i = 0; i < styleRunCount; ++i) {
- *                  styleLimit = styleRuns[i].limit;
- *                  if (start < styleLimit) {
- *                      if (styleLimit > limit) {
- *                          styleLimit = limit;
- *                      }
- *                      renderRun(text, start, styleLimit,
- *                                direction, styleRuns[i].style);
- *                      if (styleLimit == limit) {
- *                          break;
- *                      }
- *                      start = styleLimit;
- *                  }
- *              }
- *          } else {
- *              int styleStart;
- *
- *              for (i = styleRunCount-1; i >= 0; --i) {
- *                  if (i > 0) {
- *                      styleStart = styleRuns[i-1].limit;
- *                  } else {
- *                      styleStart = 0;
- *                  }
- *                  if (limit >= styleStart) {
- *                      if (styleStart < start) {
- *                          styleStart = start;
- *                      }
- *                      renderRun(text, styleStart, limit, direction,
- *                                styleRuns[i].style);
- *                      if (styleStart == start) {
- *                          break;
- *                      }
- *                      limit = styleStart;
- *                  }
- *              }
- *          }
- *      }
- *
- *      // the line object represents text[start..limit-1]
- *      static void renderLine(Bidi line, String text, int start, int limit,
- *                             StyleRun styleRuns[], int styleRunCount) {
- *          byte direction = line.getDirection();
- *          if (direction != Bidi.MIXED) {
- *              // unidirectional
- *              if (styleRunCount <= 1) {
- *                  renderRun(text, start, limit, direction, styleRuns[0].style);
- *              } else {
- *                  renderDirectionalRun(text, start, limit, direction,
- *                                       styleRuns, styleRunCount);
- *              }
- *          } else {
- *              // mixed-directional
- *              int count, i;
- *              BidiRun run;
- *
- *              try {
- *                  count = line.countRuns();
- *              } catch (IllegalStateException e) {
- *                  e.printStackTrace();
- *                  return;
- *              }
- *              if (styleRunCount <= 1) {
- *                  int style = styleRuns[0].style;
- *
- *                  // iterate over directional runs
- *                  for (i = 0; i < count; ++i) {
- *                      run = line.getVisualRun(i);
- *                      renderRun(text, run.getStart(), run.getLimit(),
- *                                run.getDirection(), style);
- *                  }
- *              } else {
- *                  // iterate over both directional and style runs
- *                  for (i = 0; i < count; ++i) {
- *                      run = line.getVisualRun(i);
- *                      renderDirectionalRun(text, run.getStart(),
- *                                           run.getLimit(), run.getDirection(),
- *                                           styleRuns, styleRunCount);
- *                  }
- *              }
- *          }
- *      }
- *
- *      static void renderParagraph(String text, byte textDirection,
- *                                  StyleRun styleRuns[], int styleRunCount,
- *                                  int lineWidth) {
- *          int length = text.length();
- *          Bidi para = new Bidi();
- *          try {
- *              para.setPara(text,
- *                           textDirection != 0 ? Bidi.LEVEL_DEFAULT_RTL
- *                                              : Bidi.LEVEL_DEFAULT_LTR,
- *                           null);
- *          } catch (Exception e) {
- *              e.printStackTrace();
- *              return;
- *          }
- *          byte paraLevel = (byte)(1 & para.getParaLevel());
- *          StyleRun styleRun = new StyleRun(length, styleNormal);
- *
- *          if (styleRuns == null || styleRunCount <= 0) {
- *              styleRuns = new StyleRun[1];
- *              styleRunCount = 1;
- *              styleRuns[0] = styleRun;
- *          }
- *          // assume styleRuns[styleRunCount-1].limit>=length
- *
- *          int width = getTextWidth(text, 0, length, styleRuns, styleRunCount);
- *          if (width <= lineWidth) {
- *              // everything fits onto one line
- *
- *              // prepare rendering a new line from either left or right
- *              startLine(paraLevel, width);
- *
- *              renderLine(para, text, 0, length, styleRuns, styleRunCount);
- *          } else {
- *              // we need to render several lines
- *              Bidi line = new Bidi(length, 0);
- *              int start = 0, limit;
- *              int styleRunStart = 0, styleRunLimit;
- *
- *              for (;;) {
- *                  limit = length;
- *                  styleRunLimit = styleRunCount;
- *                  width = getLineBreak(text, new Bounds(start, limit),
- *                                       para, styleRuns,
- *                                       new Bounds(styleRunStart, styleRunLimit));
- *                  try {
- *                      line = para.setLine(start, limit);
- *                  } catch (Exception e) {
- *                      e.printStackTrace();
- *                      return;
- *                  }
- *                  // prepare rendering a new line
- *                  // from either left or right
- *                  startLine(paraLevel, width);
- *
- *                  if (styleRunStart > 0) {
- *                      int newRunCount = styleRuns.length - styleRunStart;
- *                      StyleRun[] newRuns = new StyleRun[newRunCount];
- *                      System.arraycopy(styleRuns, styleRunStart, newRuns, 0,
- *                                       newRunCount);
- *                      renderLine(line, text, start, limit, newRuns,
- *                                 styleRunLimit - styleRunStart);
- *                  } else {
- *                      renderLine(line, text, start, limit, styleRuns,
- *                                 styleRunLimit - styleRunStart);
- *                  }
- *                  if (limit == length) {
- *                      break;
- *                  }
- *                  start = limit;
- *                  styleRunStart = styleRunLimit - 1;
- *                  if (start >= styleRuns[styleRunStart].limit) {
- *                      ++styleRunStart;
- *                  }
- *              }
- *          }
- *      }
- *
- *      public static void main(String[] args)
- *      {
- *          renderParagraph("Some Latin text...", Bidi.LTR, null, 0, 80);
- *          renderParagraph("Some Hebrew text...", Bidi.RTL, null, 0, 60);
- *      }
- *  }
- *
- * </pre>
- */
-
-public class Bidi {
-
-    private java.text.Bidi bidi;
-
-    private Bidi(java.text.Bidi delegate) {
-        this.bidi = delegate;
-    }
-
-    /** Paragraph level setting<p>
-     *
-     * Constant indicating that the base direction depends on the first strong
-     * directional character in the text according to the Unicode Bidirectional
-     * Algorithm. If no strong directional character is present,
-     * then set the paragraph level to 0 (left-to-right).<p>
-     *
-     * If this value is used in conjunction with reordering modes
-     * <code>REORDER_INVERSE_LIKE_DIRECT</code> or
-     * <code>REORDER_INVERSE_FOR_NUMBERS_SPECIAL</code>, the text to reorder
-     * is assumed to be visual LTR, and the text after reordering is required
-     * to be the corresponding logical string with appropriate contextual
-     * direction. The direction of the result string will be RTL if either
-     * the righmost or leftmost strong character of the source text is RTL
-     * or Arabic Letter, the direction will be LTR otherwise.<p>
-     *
-     * If reordering option <code>OPTION_INSERT_MARKS</code> is set, an RLM may
-     * be added at the beginning of the result string to ensure round trip
-     * (that the result string, when reordered back to visual, will produce
-     * the original source text).
-     * @see #REORDER_INVERSE_LIKE_DIRECT
-     * @see #REORDER_INVERSE_FOR_NUMBERS_SPECIAL
-     * @stable ICU 3.8
-     */
-    public static final byte LEVEL_DEFAULT_LTR = (byte)0x7e;
-
-    /** Paragraph level setting<p>
-     *
-     * Constant indicating that the base direction depends on the first strong
-     * directional character in the text according to the Unicode Bidirectional
-     * Algorithm. If no strong directional character is present,
-     * then set the paragraph level to 1 (right-to-left).<p>
-     *
-     * If this value is used in conjunction with reordering modes
-     * <code>REORDER_INVERSE_LIKE_DIRECT</code> or
-     * <code>REORDER_INVERSE_FOR_NUMBERS_SPECIAL</code>, the text to reorder
-     * is assumed to be visual LTR, and the text after reordering is required
-     * to be the corresponding logical string with appropriate contextual
-     * direction. The direction of the result string will be RTL if either
-     * the righmost or leftmost strong character of the source text is RTL
-     * or Arabic Letter, or if the text contains no strong character;
-     * the direction will be LTR otherwise.<p>
-     *
-     * If reordering option <code>OPTION_INSERT_MARKS</code> is set, an RLM may
-     * be added at the beginning of the result string to ensure round trip
-     * (that the result string, when reordered back to visual, will produce
-     * the original source text).
-     * @see #REORDER_INVERSE_LIKE_DIRECT
-     * @see #REORDER_INVERSE_FOR_NUMBERS_SPECIAL
-     * @stable ICU 3.8
-     */
-    public static final byte LEVEL_DEFAULT_RTL = (byte)0x7f;
-
-    /**
-     * Maximum explicit embedding level.
-     * (The maximum resolved level can be up to <code>MAX_EXPLICIT_LEVEL+1</code>).
-     * @stable ICU 3.8
-     */
-    public static final byte MAX_EXPLICIT_LEVEL = 61;
-
-    /**
-     * Bit flag for level input.
-     * Overrides directional properties.
-     * @stable ICU 3.8
-     */
-    public static final byte LEVEL_OVERRIDE = (byte)0x80;
-
-    /**
-     * Special value which can be returned by the mapping methods when a
-     * logical index has no corresponding visual index or vice-versa. This may
-     * happen for the logical-to-visual mapping of a Bidi control when option
-     * <code>OPTION_REMOVE_CONTROLS</code> is
-     * specified. This can also happen for the visual-to-logical mapping of a
-     * Bidi mark (LRM or RLM) inserted by option
-     * <code>OPTION_INSERT_MARKS</code>.
-     * @see #getVisualIndex
-     * @see #getVisualMap
-     * @see #getLogicalIndex
-     * @see #getLogicalMap
-     * @see #OPTION_INSERT_MARKS
-     * @see #OPTION_REMOVE_CONTROLS
-     * @stable ICU 3.8
-     */
-    public static final int MAP_NOWHERE = -1;
-
-    /**
-     * All left-to-right text.
-     * @stable ICU 3.8
-     */
-    public static final byte LTR = 0;
-
-    /**
-     * All right-to-left text.
-     * @stable ICU 3.8
-     */
-    public static final byte RTL = 1;
-
-    /**
-     * Mixed-directional text.
-     * @stable ICU 3.8
-     */
-    public static final byte MIXED = 2;
-
-    /**
-     * option bit for writeReordered():
-     * keep combining characters after their base characters in RTL runs
-     *
-     * @see #writeReordered
-     * @stable ICU 3.8
-     */
-    public static final short KEEP_BASE_COMBINING = 1;
-
-    /**
-     * option bit for writeReordered():
-     * replace characters with the "mirrored" property in RTL runs
-     * by their mirror-image mappings
-     *
-     * @see #writeReordered
-     * @stable ICU 3.8
-     */
-    public static final short DO_MIRRORING = 2;
-
-    /**
-     * option bit for writeReordered():
-     * surround the run with LRMs if necessary;
-     * this is part of the approximate "inverse Bidi" algorithm
-     *
-     * <p>This option does not imply corresponding adjustment of the index
-     * mappings.</p>
-     *
-     * @see #setInverse
-     * @see #writeReordered
-     * @stable ICU 3.8
-     */
-    public static final short INSERT_LRM_FOR_NUMERIC = 4;
-
-    /**
-     * option bit for writeReordered():
-     * remove Bidi control characters
-     * (this does not affect INSERT_LRM_FOR_NUMERIC)
-     *
-     * <p>This option does not imply corresponding adjustment of the index
-     * mappings.</p>
-     *
-     * @see #writeReordered
-     * @see #INSERT_LRM_FOR_NUMERIC
-     * @stable ICU 3.8
-     */
-    public static final short REMOVE_BIDI_CONTROLS = 8;
-
-    /**
-     * option bit for writeReordered():
-     * write the output in reverse order
-     *
-     * <p>This has the same effect as calling <code>writeReordered()</code>
-     * first without this option, and then calling
-     * <code>writeReverse()</code> without mirroring.
-     * Doing this in the same step is faster and avoids a temporary buffer.
-     * An example for using this option is output to a character terminal that
-     * is designed for RTL scripts and stores text in reverse order.</p>
-     *
-     * @see #writeReordered
-     * @stable ICU 3.8
-     */
-    public static final short OUTPUT_REVERSE = 16;
-
-    /** Reordering mode: Regular Logical to Visual Bidi algorithm according to Unicode.
-     * @see #setReorderingMode
-     * @stable ICU 3.8
-     */
-    public static final short REORDER_DEFAULT = 0;
-
-    /** Reordering mode: Logical to Visual algorithm which handles numbers in
-     * a way which mimicks the behavior of Windows XP.
-     * @see #setReorderingMode
-     * @stable ICU 3.8
-     */
-    public static final short REORDER_NUMBERS_SPECIAL = 1;
-
-    /** Reordering mode: Logical to Visual algorithm grouping numbers with
-     * adjacent R characters (reversible algorithm).
-     * @see #setReorderingMode
-     * @stable ICU 3.8
-     */
-    public static final short REORDER_GROUP_NUMBERS_WITH_R = 2;
-
-    /** Reordering mode: Reorder runs only to transform a Logical LTR string
-     * to the logical RTL string with the same display, or vice-versa.<br>
-     * If this mode is set together with option
-     * <code>OPTION_INSERT_MARKS</code>, some Bidi controls in the source
-     * text may be removed and other controls may be added to produce the
-     * minimum combination which has the required display.
-     * @see #OPTION_INSERT_MARKS
-     * @see #setReorderingMode
-     * @stable ICU 3.8
-     */
-    public static final short REORDER_RUNS_ONLY = 3;
-
-    /** Reordering mode: Visual to Logical algorithm which handles numbers
-     * like L (same algorithm as selected by <code>setInverse(true)</code>.
-     * @see #setInverse
-     * @see #setReorderingMode
-     * @stable ICU 3.8
-     */
-    public static final short REORDER_INVERSE_NUMBERS_AS_L = 4;
-
-    /** Reordering mode: Visual to Logical algorithm equivalent to the regular
-     * Logical to Visual algorithm.
-     * @see #setReorderingMode
-     * @stable ICU 3.8
-     */
-    public static final short REORDER_INVERSE_LIKE_DIRECT = 5;
-
-    /** Reordering mode: Inverse Bidi (Visual to Logical) algorithm for the
-     * <code>REORDER_NUMBERS_SPECIAL</code> Bidi algorithm.
-     * @see #setReorderingMode
-     * @stable ICU 3.8
-     */
-    public static final short REORDER_INVERSE_FOR_NUMBERS_SPECIAL = 6;
-
-    /**
-     * Option value for <code>setReorderingOptions</code>:
-     * disable all the options which can be set with this method
-     * @see #setReorderingOptions
-     * @stable ICU 3.8
-     */
-    public static final int OPTION_DEFAULT = 0;
-
-    /**
-     * Option bit for <code>setReorderingOptions</code>:
-     * insert Bidi marks (LRM or RLM) when needed to ensure correct result of
-     * a reordering to a Logical order
-     *
-     * <p>This option must be set or reset before calling
-     * <code>setPara</code>.</p>
-     *
-     * <p>This option is significant only with reordering modes which generate
-     * a result with Logical order, specifically.</p>
-     * <ul>
-     *   <li><code>REORDER_RUNS_ONLY</code></li>
-     *   <li><code>REORDER_INVERSE_NUMBERS_AS_L</code></li>
-     *   <li><code>REORDER_INVERSE_LIKE_DIRECT</code></li>
-     *   <li><code>REORDER_INVERSE_FOR_NUMBERS_SPECIAL</code></li>
-     * </ul>
-     *
-     * <p>If this option is set in conjunction with reordering mode
-     * <code>REORDER_INVERSE_NUMBERS_AS_L</code> or with calling
-     * <code>setInverse(true)</code>, it implies option
-     * <code>INSERT_LRM_FOR_NUMERIC</code> in calls to method
-     * <code>writeReordered()</code>.</p>
-     *
-     * <p>For other reordering modes, a minimum number of LRM or RLM characters
-     * will be added to the source text after reordering it so as to ensure
-     * round trip, i.e. when applying the inverse reordering mode on the
-     * resulting logical text with removal of Bidi marks
-     * (option <code>OPTION_REMOVE_CONTROLS</code> set before calling
-     * <code>setPara()</code> or option
-     * <code>REMOVE_BIDI_CONTROLS</code> in
-     * <code>writeReordered</code>), the result will be identical to the
-     * source text in the first transformation.
-     *
-     * <p>This option will be ignored if specified together with option
-     * <code>OPTION_REMOVE_CONTROLS</code>. It inhibits option
-     * <code>REMOVE_BIDI_CONTROLS</code> in calls to method
-     * <code>writeReordered()</code> and it implies option
-     * <code>INSERT_LRM_FOR_NUMERIC</code> in calls to method
-     * <code>writeReordered()</code> if the reordering mode is
-     * <code>REORDER_INVERSE_NUMBERS_AS_L</code>.</p>
-     *
-     * @see #setReorderingMode
-     * @see #setReorderingOptions
-     * @see #INSERT_LRM_FOR_NUMERIC
-     * @see #REMOVE_BIDI_CONTROLS
-     * @see #OPTION_REMOVE_CONTROLS
-     * @see #REORDER_RUNS_ONLY
-     * @see #REORDER_INVERSE_NUMBERS_AS_L
-     * @see #REORDER_INVERSE_LIKE_DIRECT
-     * @see #REORDER_INVERSE_FOR_NUMBERS_SPECIAL
-     * @stable ICU 3.8
-     */
-    public static final int OPTION_INSERT_MARKS = 1;
-
-    /**
-     * Option bit for <code>setReorderingOptions</code>:
-     * remove Bidi control characters
-     *
-     * <p>This option must be set or reset before calling
-     * <code>setPara</code>.</p>
-     *
-     * <p>This option nullifies option
-     * <code>OPTION_INSERT_MARKS</code>. It inhibits option
-     * <code>INSERT_LRM_FOR_NUMERIC</code> in calls to method
-     * <code>writeReordered()</code> and it implies option
-     * <code>REMOVE_BIDI_CONTROLS</code> in calls to that method.</p>
-     *
-     * @see #setReorderingMode
-     * @see #setReorderingOptions
-     * @see #OPTION_INSERT_MARKS
-     * @see #INSERT_LRM_FOR_NUMERIC
-     * @see #REMOVE_BIDI_CONTROLS
-     * @stable ICU 3.8
-     */
-    public static final int OPTION_REMOVE_CONTROLS = 2;
-
-    /**
-     * Option bit for <code>setReorderingOptions</code>:
-     * process the output as part of a stream to be continued
-     *
-     * <p>This option must be set or reset before calling
-     * <code>setPara</code>.</p>
-     *
-     * <p>This option specifies that the caller is interested in processing
-     * large text object in parts. The results of the successive calls are
-     * expected to be concatenated by the caller. Only the call for the last
-     * part will have this option bit off.</p>
-     *
-     * <p>When this option bit is on, <code>setPara()</code> may process
-     * less than the full source text in order to truncate the text at a
-     * meaningful boundary. The caller should call
-     * <code>getProcessedLength()</code> immediately after calling
-     * <code>setPara()</code> in order to determine how much of the source
-     * text has been processed. Source text beyond that length should be
-     * resubmitted in following calls to <code>setPara</code>. The
-     * processed length may be less than the length of the source text if a
-     * character preceding the last character of the source text constitutes a
-     * reasonable boundary (like a block separator) for text to be continued.<br>
-     * If the last character of the source text constitutes a reasonable
-     * boundary, the whole text will be processed at once.<br>
-     * If nowhere in the source text there exists
-     * such a reasonable boundary, the processed length will be zero.<br>
-     * The caller should check for such an occurrence and do one of the following:
-     * <ul><li>submit a larger amount of text with a better chance to include
-     *         a reasonable boundary.</li>
-     *     <li>resubmit the same text after turning off option
-     *         <code>OPTION_STREAMING</code>.</li></ul>
-     * In all cases, this option should be turned off before processing the last
-     * part of the text.</p>
-     *
-     * <p>When the <code>OPTION_STREAMING</code> option is used, it is
-     * recommended to call <code>orderParagraphsLTR(true)</code> before calling
-     * <code>setPara()</code> so that later paragraphs may be concatenated to
-     * previous paragraphs on the right.
-     * </p>
-     *
-     * @see #setReorderingMode
-     * @see #setReorderingOptions
-     * @see #getProcessedLength
-     * @stable ICU 3.8
-     */
-    public static final int OPTION_STREAMING = 4;
-
-    /**
-     * Value returned by <code>BidiClassifier</code> when there is no need to
-     * override the standard Bidi class for a given code point.
-     * @see BidiClassifier
-     * @stable ICU 3.8
-     */
-    public static final int CLASS_DEFAULT = 19; //UCharacterDirection.CHAR_DIRECTION_COUNT;
-
-    /**
-     * Allocate a <code>Bidi</code> object.
-     * Such an object is initially empty. It is assigned
-     * the Bidi properties of a piece of text containing one or more paragraphs
-     * by <code>setPara()</code>
-     * or the Bidi properties of a line within a paragraph by
-     * <code>setLine()</code>.<p>
-     * This object can be reused.<p>
-     * <code>setPara()</code> and <code>setLine()</code> will allocate
-     * additional memory for internal structures as necessary.
-     *
-     * @stable ICU 3.8
-     */
-    public Bidi()
-    {
-        throw new UnsupportedOperationException("Constructor not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Allocate a <code>Bidi</code> object with preallocated memory
-     * for internal structures.
-     * This method provides a <code>Bidi</code> object like the default constructor
-     * but it also preallocates memory for internal structures
-     * according to the sizings supplied by the caller.<p>
-     * The preallocation can be limited to some of the internal memory
-     * by setting some values to 0 here. That means that if, e.g.,
-     * <code>maxRunCount</code> cannot be reasonably predetermined and should not
-     * be set to <code>maxLength</code> (the only failproof value) to avoid
-     * wasting  memory, then <code>maxRunCount</code> could be set to 0 here
-     * and the internal structures that are associated with it will be allocated
-     * on demand, just like with the default constructor.
-     *
-     * @param maxLength is the maximum text or line length that internal memory
-     *        will be preallocated for. An attempt to associate this object with a
-     *        longer text will fail, unless this value is 0, which leaves the allocation
-     *        up to the implementation.
-     *
-     * @param maxRunCount is the maximum anticipated number of same-level runs
-     *        that internal memory will be preallocated for. An attempt to access
-     *        visual runs on an object that was not preallocated for as many runs
-     *        as the text was actually resolved to will fail,
-     *        unless this value is 0, which leaves the allocation up to the implementation.<br><br>
-     *        The number of runs depends on the actual text and maybe anywhere between
-     *        1 and <code>maxLength</code>. It is typically small.
-     *
-     * @throws IllegalArgumentException if maxLength or maxRunCount is less than 0
-     * @stable ICU 3.8
-     */
-    public Bidi(int maxLength, int maxRunCount)
-    {
-        throw new UnsupportedOperationException("Constructor not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Modify the operation of the Bidi algorithm such that it
-     * approximates an "inverse Bidi" algorithm. This method
-     * must be called before <code>setPara()</code>.
-     *
-     * <p>The normal operation of the Bidi algorithm as described
-     * in the Unicode Technical Report is to take text stored in logical
-     * (keyboard, typing) order and to determine the reordering of it for visual
-     * rendering.
-     * Some legacy systems store text in visual order, and for operations
-     * with standard, Unicode-based algorithms, the text needs to be transformed
-     * to logical order. This is effectively the inverse algorithm of the
-     * described Bidi algorithm. Note that there is no standard algorithm for
-     * this "inverse Bidi" and that the current implementation provides only an
-     * approximation of "inverse Bidi".</p>
-     *
-     * <p>With <code>isInversed</code> set to <code>true</code>,
-     * this method changes the behavior of some of the subsequent methods
-     * in a way that they can be used for the inverse Bidi algorithm.
-     * Specifically, runs of text with numeric characters will be treated in a
-     * special way and may need to be surrounded with LRM characters when they are
-     * written in reordered sequence.</p>
-     *
-     * <p>Output runs should be retrieved using <code>getVisualRun()</code>.
-     * Since the actual input for "inverse Bidi" is visually ordered text and
-     * <code>getVisualRun()</code> gets the reordered runs, these are actually
-     * the runs of the logically ordered output.</p>
-     *
-     * <p>Calling this method with argument <code>isInverse</code> set to
-     * <code>true</code> is equivalent to calling <code>setReorderingMode</code>
-     * with argument <code>reorderingMode</code>
-     * set to <code>REORDER_INVERSE_NUMBERS_AS_L</code>.<br>
-     * Calling this method with argument <code>isInverse</code> set to
-     * <code>false</code> is equivalent to calling <code>setReorderingMode</code>
-     * with argument <code>reorderingMode</code>
-     * set to <code>REORDER_DEFAULT</code>.
-     *
-     * @param isInverse specifies "forward" or "inverse" Bidi operation.
-     *
-     * @see #setPara
-     * @see #writeReordered
-     * @see #setReorderingMode
-     * @see #REORDER_INVERSE_NUMBERS_AS_L
-     * @see #REORDER_DEFAULT
-     * @stable ICU 3.8
-     */
-    public void setInverse(boolean isInverse) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Is this <code>Bidi</code> object set to perform the inverse Bidi
-     * algorithm?
-     * <p>Note: calling this method after setting the reordering mode with
-     * <code>setReorderingMode</code> will return <code>true</code> if the
-     * reordering mode was set to
-     * <code>REORDER_INVERSE_NUMBERS_AS_L<code>, <code>false</code>
-     * for all other values.</p>
-     *
-     * @return <code>true</code> if the <code>Bidi</code> object is set to
-     * perform the inverse Bidi algorithm by handling numbers as L.
-     *
-     * @see #setInverse
-     * @see #setReorderingMode
-     * @see #REORDER_INVERSE_NUMBERS_AS_L
-     * @stable ICU 3.8
-     */
-    public boolean isInverse() {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Modify the operation of the Bidi algorithm such that it implements some
-     * variant to the basic Bidi algorithm or approximates an "inverse Bidi"
-     * algorithm, depending on different values of the "reordering mode".
-     * This method must be called before <code>setPara()</code>, and stays in
-     * effect until called again with a different argument.
-     *
-     * <p>The normal operation of the Bidi algorithm as described in the Unicode
-     * Standard Annex #9 is to take text stored in logical (keyboard, typing)
-     * order and to determine how to reorder it for visual rendering.</p>
-     *
-     * <p>With the reordering mode set to a value other than
-     * <code>REORDER_DEFAULT</code>, this method changes the behavior of some of
-     * the subsequent methods in a way such that they implement an inverse Bidi
-     * algorithm or some other algorithm variants.</p>
-     *
-     * <p>Some legacy systems store text in visual order, and for operations
-     * with standard, Unicode-based algorithms, the text needs to be transformed
-     * into logical order. This is effectively the inverse algorithm of the
-     * described Bidi algorithm. Note that there is no standard algorithm for
-     * this "inverse Bidi", so a number of variants are implemented here.</p>
-     *
-     * <p>In other cases, it may be desirable to emulate some variant of the
-     * Logical to Visual algorithm (e.g. one used in MS Windows), or perform a
-     * Logical to Logical transformation.</p>
-     *
-     * <ul>
-     * <li>When the Reordering Mode is set to
-     * <code>REORDER_DEFAULT</code>,
-     * the standard Bidi Logical to Visual algorithm is applied.</li>
-     *
-     * <li>When the reordering mode is set to
-     * <code>REORDER_NUMBERS_SPECIAL</code>,
-     * the algorithm used to perform Bidi transformations when calling
-     * <code>setPara</code> should approximate the algorithm used in Microsoft
-     * Windows XP rather than strictly conform to the Unicode Bidi algorithm.
-     * <br>
-     * The differences between the basic algorithm and the algorithm addressed
-     * by this option are as follows:
-     * <ul>
-     *   <li>Within text at an even embedding level, the sequence "123AB"
-     *   (where AB represent R or AL letters) is transformed to "123BA" by the
-     *   Unicode algorithm and to "BA123" by the Windows algorithm.</li>
-     *
-     *   <li>Arabic-Indic numbers (AN) are handled by the Windows algorithm just
-     *   like regular numbers (EN).</li>
-     * </ul></li>
-     *
-     * <li>When the reordering mode is set to
-     * <code>REORDER_GROUP_NUMBERS_WITH_R</code>,
-     * numbers located between LTR text and RTL text are associated with the RTL
-     * text. For instance, an LTR paragraph with content "abc 123 DEF" (where
-     * upper case letters represent RTL characters) will be transformed to
-     * "abc FED 123" (and not "abc 123 FED"), "DEF 123 abc" will be transformed
-     * to "123 FED abc" and "123 FED abc" will be transformed to "DEF 123 abc".
-     * This makes the algorithm reversible and makes it useful when round trip
-     * (from visual to logical and back to visual) must be achieved without
-     * adding LRM characters. However, this is a variation from the standard
-     * Unicode Bidi algorithm.<br>
-     * The source text should not contain Bidi control characters other than LRM
-     * or RLM.</li>
-     *
-     * <li>When the reordering mode is set to
-     * <code>REORDER_RUNS_ONLY</code>,
-     * a "Logical to Logical" transformation must be performed:
-     * <ul>
-     * <li>If the default text level of the source text (argument
-     * <code>paraLevel</code> in <code>setPara</code>) is even, the source text
-     * will be handled as LTR logical text and will be transformed to the RTL
-     * logical text which has the same LTR visual display.</li>
-     * <li>If the default level of the source text is odd, the source text
-     * will be handled as RTL logical text and will be transformed to the
-     * LTR logical text which has the same LTR visual display.</li>
-     * </ul>
-     * This mode may be needed when logical text which is basically Arabic or
-     * Hebrew, with possible included numbers or phrases in English, has to be
-     * displayed as if it had an even embedding level (this can happen if the
-     * displaying application treats all text as if it was basically LTR).
-     * <br>
-     * This mode may also be needed in the reverse case, when logical text which
-     * is basically English, with possible included phrases in Arabic or Hebrew,
-     * has to be displayed as if it had an odd embedding level.
-     * <br>
-     * Both cases could be handled by adding LRE or RLE at the head of the
-     * text, if the display subsystem supports these formatting controls. If it
-     * does not, the problem may be handled by transforming the source text in
-     * this mode before displaying it, so that it will be displayed properly.
-     * <br>
-     * The source text should not contain Bidi control characters other than LRM
-     * or RLM.</li>
-     *
-     * <li>When the reordering mode is set to
-     * <code>REORDER_INVERSE_NUMBERS_AS_L</code>, an "inverse Bidi"
-     * algorithm is applied.
-     * Runs of text with numeric characters will be treated like LTR letters and
-     * may need to be surrounded with LRM characters when they are written in
-     * reordered sequence (the option <code>INSERT_LRM_FOR_NUMERIC</code> can
-     * be used with method <code>writeReordered</code> to this end. This mode
-     * is equivalent to calling <code>setInverse()</code> with
-     * argument <code>isInverse</code> set to <code>true</code>.</li>
-     *
-     * <li>When the reordering mode is set to
-     * <code>REORDER_INVERSE_LIKE_DIRECT</code>, the "direct" Logical to
-     * Visual Bidi algorithm is used as an approximation of an "inverse Bidi"
-     * algorithm. This mode is similar to mode
-     * <code>REORDER_INVERSE_NUMBERS_AS_L</code> but is closer to the
-     * regular Bidi algorithm.
-     * <br>
-     * For example, an LTR paragraph with the content "FED 123 456 CBA" (where
-     * upper case represents RTL characters) will be transformed to
-     * "ABC 456 123 DEF", as opposed to "DEF 123 456 ABC"
-     * with mode <code>REORDER_INVERSE_NUMBERS_AS_L</code>.<br>
-     * When used in conjunction with option
-     * <code>OPTION_INSERT_MARKS</code>, this mode generally
-     * adds Bidi marks to the output significantly more sparingly than mode
-     * <code>REORDER_INVERSE_NUMBERS_AS_L</code>.<br> with option
-     * <code>INSERT_LRM_FOR_NUMERIC</code> in calls to
-     * <code>writeReordered</code>.</li>
-     *
-     * <li>When the reordering mode is set to
-     * <code>REORDER_INVERSE_FOR_NUMBERS_SPECIAL</code>, the Logical to Visual
-     * Bidi algorithm used in Windows XP is used as an approximation of an "inverse
-     * Bidi" algorithm.
-     * <br>
-     * For example, an LTR paragraph with the content "abc FED123" (where
-     * upper case represents RTL characters) will be transformed to
-     * "abc 123DEF.</li>
-     * </ul>
-     *
-     * <p>In all the reordering modes specifying an "inverse Bidi" algorithm
-     * (i.e. those with a name starting with <code>REORDER_INVERSE</code>),
-     * output runs should be retrieved using <code>getVisualRun()</code>, and
-     * the output text with <code>writeReordered()</code>. The caller should
-     * keep in mind that in "inverse Bidi" modes the input is actually visually
-     * ordered text and reordered output returned by <code>getVisualRun()</code>
-     * or <code>writeReordered()</code> are actually runs or character string
-     * of logically ordered output.<br>
-     * For all the "inverse Bidi" modes, the source text should not contain
-     * Bidi control characters other than LRM or RLM.</p>
-     *
-     * <p>Note that option <code>OUTPUT_REVERSE</code> of
-     * <code>writeReordered</code> has no useful meaning and should not be used
-     * in conjunction with any value of the reordering mode specifying "inverse
-     * Bidi" or with value <code>REORDER_RUNS_ONLY</code>.
-     *
-     * @param reorderingMode specifies the required variant of the Bidi
-     *                       algorithm.
-     *
-     * @see #setInverse
-     * @see #setPara
-     * @see #writeReordered
-     * @see #INSERT_LRM_FOR_NUMERIC
-     * @see #OUTPUT_REVERSE
-     * @see #REORDER_DEFAULT
-     * @see #REORDER_NUMBERS_SPECIAL
-     * @see #REORDER_GROUP_NUMBERS_WITH_R
-     * @see #REORDER_RUNS_ONLY
-     * @see #REORDER_INVERSE_NUMBERS_AS_L
-     * @see #REORDER_INVERSE_LIKE_DIRECT
-     * @see #REORDER_INVERSE_FOR_NUMBERS_SPECIAL
-     * @stable ICU 3.8
-     */
-    public void setReorderingMode(int reorderingMode) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * What is the requested reordering mode for a given Bidi object?
-     *
-     * @return the current reordering mode of the Bidi object
-     *
-     * @see #setReorderingMode
-     * @stable ICU 3.8
-     */
-    public int getReorderingMode() {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Specify which of the reordering options should be applied during Bidi
-     * transformations.
-     *
-     * @param options A combination of zero or more of the following
-     * reordering options:
-     * <code>OPTION_DEFAULT</code>, <code>OPTION_INSERT_MARKS</code>,
-     * <code>OPTION_REMOVE_CONTROLS</code>, <code>OPTION_STREAMING</code>.
-     *
-     * @see #getReorderingOptions
-     * @see #OPTION_DEFAULT
-     * @see #OPTION_INSERT_MARKS
-     * @see #OPTION_REMOVE_CONTROLS
-     * @see #OPTION_STREAMING
-     * @stable ICU 3.8
-     */
-    public void setReorderingOptions(int options) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * What are the reordering options applied to a given Bidi object?
-     *
-     * @return the current reordering options of the Bidi object
-     *
-     * @see #setReorderingOptions
-     * @stable ICU 3.8
-     */
-    public int getReorderingOptions() {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Perform the Unicode Bidi algorithm. It is defined in the
-     * <a href="http://www.unicode.org/unicode/reports/tr9/">Unicode Standard Annex #9</a>,
-     * version 13,
-     * also described in The Unicode Standard, Version 4.0 .<p>
-     *
-     * This method takes a piece of plain text containing one or more paragraphs,
-     * with or without externally specified embedding levels from <i>styled</i>
-     * text and computes the left-right-directionality of each character.<p>
-     *
-     * If the entire text is all of the same directionality, then
-     * the method may not perform all the steps described by the algorithm,
-     * i.e., some levels may not be the same as if all steps were performed.
-     * This is not relevant for unidirectional text.<br>
-     * For example, in pure LTR text with numbers the numbers would get
-     * a resolved level of 2 higher than the surrounding text according to
-     * the algorithm. This implementation may set all resolved levels to
-     * the same value in such a case.<p>
-     *
-     * The text can be composed of multiple paragraphs. Occurrence of a block
-     * separator in the text terminates a paragraph, and whatever comes next starts
-     * a new paragraph. The exception to this rule is when a Carriage Return (CR)
-     * is followed by a Line Feed (LF). Both CR and LF are block separators, but
-     * in that case, the pair of characters is considered as terminating the
-     * preceding paragraph, and a new paragraph will be started by a character
-     * coming after the LF.
-     *
-     * Although the text is passed here as a <code>String</code>, it is
-     * stored internally as an array of characters. Therefore the
-     * documentation will refer to indexes of the characters in the text.
-     *
-     * @param text contains the text that the Bidi algorithm will be performed
-     *        on. This text can be retrieved with <code>getText()</code> or
-     *        <code>getTextAsString</code>.<br>
-     *
-     * @param paraLevel specifies the default level for the text;
-     *        it is typically 0 (LTR) or 1 (RTL).
-     *        If the method shall determine the paragraph level from the text,
-     *        then <code>paraLevel</code> can be set to
-     *        either <code>LEVEL_DEFAULT_LTR</code>
-     *        or <code>LEVEL_DEFAULT_RTL</code>; if the text contains multiple
-     *        paragraphs, the paragraph level shall be determined separately for
-     *        each paragraph; if a paragraph does not include any strongly typed
-     *        character, then the desired default is used (0 for LTR or 1 for RTL).
-     *        Any other value between 0 and <code>MAX_EXPLICIT_LEVEL</code>
-     *        is also valid, with odd levels indicating RTL.
-     *
-     * @param embeddingLevels (in) may be used to preset the embedding and override levels,
-     *        ignoring characters like LRE and PDF in the text.
-     *        A level overrides the directional property of its corresponding
-     *        (same index) character if the level has the
-     *        <code>LEVEL_OVERRIDE</code> bit set.<br><br>
-     *        Except for that bit, it must be
-     *        <code>paraLevel<=embeddingLevels[]<=MAX_EXPLICIT_LEVEL</code>,
-     *        with one exception: a level of zero may be specified for a
-     *        paragraph separator even if <code>paraLevel&gt;0</code> when multiple
-     *        paragraphs are submitted in the same call to <code>setPara()</code>.<br><br>
-     *        <strong>Caution: </strong>A reference to this array, not a copy
-     *        of the levels, will be stored in the <code>Bidi</code> object;
-     *        the <code>embeddingLevels</code>
-     *        should not be modified to avoid unexpected results on subsequent
-     *        Bidi operations. However, the <code>setPara()</code> and
-     *        <code>setLine()</code> methods may modify some or all of the
-     *        levels.<br><br>
-     *        <strong>Note:</strong> the <code>embeddingLevels</code> array must
-     *        have one entry for each character in <code>text</code>.
-     *
-     * @throws IllegalArgumentException if the values in embeddingLevels are
-     *         not within the allowed range
-     *
-     * @see #LEVEL_DEFAULT_LTR
-     * @see #LEVEL_DEFAULT_RTL
-     * @see #LEVEL_OVERRIDE
-     * @see #MAX_EXPLICIT_LEVEL
-     * @stable ICU 3.8
-     */
-    public void setPara(String text, byte paraLevel, byte[] embeddingLevels)
-    {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Perform the Unicode Bidi algorithm. It is defined in the
-     * <a href="http://www.unicode.org/unicode/reports/tr9/">Unicode Standard Annex #9</a>,
-     * version 13,
-     * also described in The Unicode Standard, Version 4.0 .<p>
-     *
-     * This method takes a piece of plain text containing one or more paragraphs,
-     * with or without externally specified embedding levels from <i>styled</i>
-     * text and computes the left-right-directionality of each character.<p>
-     *
-     * If the entire text is all of the same directionality, then
-     * the method may not perform all the steps described by the algorithm,
-     * i.e., some levels may not be the same as if all steps were performed.
-     * This is not relevant for unidirectional text.<br>
-     * For example, in pure LTR text with numbers the numbers would get
-     * a resolved level of 2 higher than the surrounding text according to
-     * the algorithm. This implementation may set all resolved levels to
-     * the same value in such a case.<p>
-     *
-     * The text can be composed of multiple paragraphs. Occurrence of a block
-     * separator in the text terminates a paragraph, and whatever comes next starts
-     * a new paragraph. The exception to this rule is when a Carriage Return (CR)
-     * is followed by a Line Feed (LF). Both CR and LF are block separators, but
-     * in that case, the pair of characters is considered as terminating the
-     * preceding paragraph, and a new paragraph will be started by a character
-     * coming after the LF.
-     *
-     * The text is stored internally as an array of characters. Therefore the
-     * documentation will refer to indexes of the characters in the text.
-     *
-     * @param chars contains the text that the Bidi algorithm will be performed
-     *        on. This text can be retrieved with <code>getText()</code> or
-     *        <code>getTextAsString</code>.<br>
-     *
-     * @param paraLevel specifies the default level for the text;
-     *        it is typically 0 (LTR) or 1 (RTL).
-     *        If the method shall determine the paragraph level from the text,
-     *        then <code>paraLevel</code> can be set to
-     *        either <code>LEVEL_DEFAULT_LTR</code>
-     *        or <code>LEVEL_DEFAULT_RTL</code>; if the text contains multiple
-     *        paragraphs, the paragraph level shall be determined separately for
-     *        each paragraph; if a paragraph does not include any strongly typed
-     *        character, then the desired default is used (0 for LTR or 1 for RTL).
-     *        Any other value between 0 and <code>MAX_EXPLICIT_LEVEL</code>
-     *        is also valid, with odd levels indicating RTL.
-     *
-     * @param embeddingLevels (in) may be used to preset the embedding and
-     *        override levels, ignoring characters like LRE and PDF in the text.
-     *        A level overrides the directional property of its corresponding
-     *        (same index) character if the level has the
-     *        <code>LEVEL_OVERRIDE</code> bit set.<br><br>
-     *        Except for that bit, it must be
-     *        <code>paraLevel<=embeddingLevels[]<=MAX_EXPLICIT_LEVEL</code>,
-     *        with one exception: a level of zero may be specified for a
-     *        paragraph separator even if <code>paraLevel&gt;0</code> when multiple
-     *        paragraphs are submitted in the same call to <code>setPara()</code>.<br><br>
-     *        <strong>Caution: </strong>A reference to this array, not a copy
-     *        of the levels, will be stored in the <code>Bidi</code> object;
-     *        the <code>embeddingLevels</code>
-     *        should not be modified to avoid unexpected results on subsequent
-     *        Bidi operations. However, the <code>setPara()</code> and
-     *        <code>setLine()</code> methods may modify some or all of the
-     *        levels.<br><br>
-     *        <strong>Note:</strong> the <code>embeddingLevels</code> array must
-     *        have one entry for each character in <code>text</code>.
-     *
-     * @throws IllegalArgumentException if the values in embeddingLevels are
-     *         not within the allowed range
-     *
-     * @see #LEVEL_DEFAULT_LTR
-     * @see #LEVEL_DEFAULT_RTL
-     * @see #LEVEL_OVERRIDE
-     * @see #MAX_EXPLICIT_LEVEL
-     * @stable ICU 3.8
-     */
-    public void setPara(char[] chars, byte paraLevel, byte[] embeddingLevels)
-    {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Perform the Unicode Bidi algorithm on a given paragraph, as defined in the
-     * <a href="http://www.unicode.org/unicode/reports/tr9/">Unicode Standard Annex #9</a>,
-     * version 13,
-     * also described in The Unicode Standard, Version 4.0 .<p>
-     *
-     * This method takes a paragraph of text and computes the
-     * left-right-directionality of each character. The text should not
-     * contain any Unicode block separators.<p>
-     *
-     * The RUN_DIRECTION attribute in the text, if present, determines the base
-     * direction (left-to-right or right-to-left). If not present, the base
-     * direction is computed using the Unicode Bidirectional Algorithm,
-     * defaulting to left-to-right if there are no strong directional characters
-     * in the text. This attribute, if present, must be applied to all the text
-     * in the paragraph.<p>
-     *
-     * The BIDI_EMBEDDING attribute in the text, if present, represents
-     * embedding level information. Negative values from -1 to -62 indicate
-     * overrides at the absolute value of the level. Positive values from 1 to
-     * 62 indicate embeddings. Where values are zero or not defined, the base
-     * embedding level as determined by the base direction is assumed.<p>
-     *
-     * The NUMERIC_SHAPING attribute in the text, if present, converts European
-     * digits to other decimal digits before running the bidi algorithm. This
-     * attribute, if present, must be applied to all the text in the paragraph.
-     *
-     * If the entire text is all of the same directionality, then
-     * the method may not perform all the steps described by the algorithm,
-     * i.e., some levels may not be the same as if all steps were performed.
-     * This is not relevant for unidirectional text.<br>
-     * For example, in pure LTR text with numbers the numbers would get
-     * a resolved level of 2 higher than the surrounding text according to
-     * the algorithm. This implementation may set all resolved levels to
-     * the same value in such a case.<p>
-     *
-     * @param paragraph a paragraph of text with optional character and
-     *        paragraph attribute information
-     * @stable ICU 3.8
-     */
-    public void setPara(AttributedCharacterIterator paragraph)
-    {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Specify whether block separators must be allocated level zero,
-     * so that successive paragraphs will progress from left to right.
-     * This method must be called before <code>setPara()</code>.
-     * Paragraph separators (B) may appear in the text.  Setting them to level zero
-     * means that all paragraph separators (including one possibly appearing
-     * in the last text position) are kept in the reordered text after the text
-     * that they follow in the source text.
-     * When this feature is not enabled, a paragraph separator at the last
-     * position of the text before reordering will go to the first position
-     * of the reordered text when the paragraph level is odd.
-     *
-     * @param ordarParaLTR specifies whether paragraph separators (B) must
-     * receive level 0, so that successive paragraphs progress from left to right.
-     *
-     * @see #setPara
-     * @stable ICU 3.8
-     */
-    public void orderParagraphsLTR(boolean ordarParaLTR) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Is this <code>Bidi</code> object set to allocate level 0 to block
-     * separators so that successive paragraphs progress from left to right?
-     *
-     * @return <code>true</code> if the <code>Bidi</code> object is set to
-     *         allocate level 0 to block separators.
-     *
-     * @stable ICU 3.8
-     */
-    public boolean isOrderParagraphsLTR() {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Get the directionality of the text.
-     *
-     * @return a value of <code>LTR</code>, <code>RTL</code> or <code>MIXED</code>
-     *         that indicates if the entire text
-     *         represented by this object is unidirectional,
-     *         and which direction, or if it is mixed-directional.
-     *
-     * @throws IllegalStateException if this call is not preceded by a successful
-     *         call to <code>setPara</code> or <code>setLine</code>
-     *
-     * @see #LTR
-     * @see #RTL
-     * @see #MIXED
-     * @stable ICU 3.8
-     */
-    public byte getDirection()
-    {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Get the text.
-     *
-     * @return A <code>String</code> containing the text that the
-     *         <code>Bidi</code> object was created for.
-     *
-     * @throws IllegalStateException if this call is not preceded by a successful
-     *         call to <code>setPara</code> or <code>setLine</code>
-     *
-     * @see #setPara
-     * @see #setLine
-     * @stable ICU 3.8
-     */
-    public String getTextAsString()
-    {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Get the text.
-     *
-     * @return A <code>char</code> array containing the text that the
-     *         <code>Bidi</code> object was created for.
-     *
-     * @throws IllegalStateException if this call is not preceded by a successful
-     *         call to <code>setPara</code> or <code>setLine</code>
-     *
-     * @see #setPara
-     * @see #setLine
-     * @stable ICU 3.8
-     */
-    public char[] getText()
-    {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Get the length of the text.
-     *
-     * @return The length of the text that the <code>Bidi</code> object was
-     *         created for.
-     *
-     * @throws IllegalStateException if this call is not preceded by a successful
-     *         call to <code>setPara</code> or <code>setLine</code>
-     * @stable ICU 3.8
-     */
-    public int getLength()
-    {
-        return bidi.getLength();
-    }
-
-    /**
-     * Get the length of the source text processed by the last call to
-     * <code>setPara()</code>. This length may be different from the length of
-     * the source text if option <code>OPTION_STREAMING</code> has been
-     * set.
-     * <br>
-     * Note that whenever the length of the text affects the execution or the
-     * result of a method, it is the processed length which must be considered,
-     * except for <code>setPara</code> (which receives unprocessed source text)
-     * and <code>getLength</code> (which returns the original length of the
-     * source text).<br>
-     * In particular, the processed length is the one to consider in the
-     * following cases:
-     * <ul>
-     * <li>maximum value of the <code>limit</code> argument of
-     * <code>setLine</code></li>
-     * <li>maximum value of the <code>charIndex</code> argument of
-     * <code>getParagraph</code></li>
-     * <li>maximum value of the <code>charIndex</code> argument of
-     * <code>getLevelAt</code></li>
-     * <li>number of elements in the array returned by <code>getLevels</code>
-     * </li>
-     * <li>maximum value of the <code>logicalStart</code> argument of
-     * <code>getLogicalRun</code></li>
-     * <li>maximum value of the <code>logicalIndex</code> argument of
-     * <code>getVisualIndex</code></li>
-     * <li>number of elements returned by <code>getLogicalMap</code></li>
-     * <li>length of text processed by <code>writeReordered</code></li>
-     * </ul>
-     *
-     * @return The length of the part of the source text processed by
-     *         the last call to <code>setPara</code>.
-     *
-     * @throws IllegalStateException if this call is not preceded by a successful
-     *         call to <code>setPara</code> or <code>setLine</code>
-     *
-     * @see #setPara
-     * @see #OPTION_STREAMING
-     * @stable ICU 3.8
-     */
-    public int getProcessedLength() {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Get the length of the reordered text resulting from the last call to
-     * <code>setPara()</code>. This length may be different from the length
-     * of the source text if option <code>OPTION_INSERT_MARKS</code>
-     * or option <code>OPTION_REMOVE_CONTROLS</code> has been set.
-     * <br>
-     * This resulting length is the one to consider in the following cases:
-     * <ul>
-     * <li>maximum value of the <code>visualIndex</code> argument of
-     * <code>getLogicalIndex</code></li>
-     * <li>number of elements returned by <code>getVisualMap</code></li>
-     * </ul>
-     * Note that this length stays identical to the source text length if
-     * Bidi marks are inserted or removed using option bits of
-     * <code>writeReordered</code>, or if option
-     * <code>REORDER_INVERSE_NUMBERS_AS_L</code> has been set.
-     *
-     * @return The length of the reordered text resulting from
-     *         the last call to <code>setPara</code>.
-     *
-     * @throws IllegalStateException if this call is not preceded by a successful
-     *         call to <code>setPara</code> or <code>setLine</code>
-     *
-     * @see #setPara
-     * @see #OPTION_INSERT_MARKS
-     * @see #OPTION_REMOVE_CONTROLS
-     * @see #REORDER_INVERSE_NUMBERS_AS_L
-     * @stable ICU 3.8
-     */
-    public int getResultLength() {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /* paragraphs API methods ------------------------------------------------- */
-
-    /**
-     * Get the paragraph level of the text.
-     *
-     * @return The paragraph level. If there are multiple paragraphs, their
-     *         level may vary if the required paraLevel is LEVEL_DEFAULT_LTR or
-     *         LEVEL_DEFAULT_RTL.  In that case, the level of the first paragraph
-     *         is returned.
-     *
-     * @throws IllegalStateException if this call is not preceded by a successful
-     *         call to <code>setPara</code> or <code>setLine</code>
-     *
-     * @see #LEVEL_DEFAULT_LTR
-     * @see #LEVEL_DEFAULT_RTL
-     * @see #getParagraph
-     * @see #getParagraphByIndex
-     * @stable ICU 3.8
-     */
-    public byte getParaLevel()
-    {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Get the number of paragraphs.
-     *
-     * @return The number of paragraphs.
-     *
-     * @throws IllegalStateException if this call is not preceded by a successful
-     *         call to <code>setPara</code> or <code>setLine</code>
-     * @stable ICU 3.8
-     */
-    public int countParagraphs()
-    {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Get a paragraph, given the index of this paragraph.
-     *
-     * This method returns information about a paragraph.<p>
-     *
-     * @param paraIndex is the number of the paragraph, in the
-     *        range <code>[0..countParagraphs()-1]</code>.
-     *
-     * @return a BidiRun object with the details of the paragraph:<br>
-     *        <code>start</code> will receive the index of the first character
-     *        of the paragraph in the text.<br>
-     *        <code>limit</code> will receive the limit of the paragraph.<br>
-     *        <code>embeddingLevel</code> will receive the level of the paragraph.
-     *
-     * @throws IllegalStateException if this call is not preceded by a successful
-     *         call to <code>setPara</code> or <code>setLine</code>
-     * @throws IllegalArgumentException if paraIndex is not in the range
-     *        <code>[0..countParagraphs()-1]</code>
-     *
-     * @see com.ibm.icu.text.BidiRun
-     * @stable ICU 3.8
-     */
-    public BidiRun getParagraphByIndex(int paraIndex)
-    {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Get a paragraph, given a position within the text.
-     * This method returns information about a paragraph.<br>
-     * Note: if the paragraph index is known, it is more efficient to
-     * retrieve the paragraph information using getParagraphByIndex().<p>
-     *
-     * @param charIndex is the index of a character within the text, in the
-     *        range <code>[0..getProcessedLength()-1]</code>.
-     *
-     * @return a BidiRun object with the details of the paragraph:<br>
-     *        <code>start</code> will receive the index of the first character
-     *        of the paragraph in the text.<br>
-     *        <code>limit</code> will receive the limit of the paragraph.<br>
-     *        <code>embeddingLevel</code> will receive the level of the paragraph.
-     *
-     * @throws IllegalStateException if this call is not preceded by a successful
-     *         call to <code>setPara</code> or <code>setLine</code>
-     * @throws IllegalArgumentException if charIndex is not within the legal range
-     *
-     * @see com.ibm.icu.text.BidiRun
-     * @see #getParagraphByIndex
-     * @see #getProcessedLength
-     * @stable ICU 3.8
-     */
-    public BidiRun getParagraph(int charIndex)
-    {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Get the index of a paragraph, given a position within the text.<p>
-     *
-     * @param charIndex is the index of a character within the text, in the
-     *        range <code>[0..getProcessedLength()-1]</code>.
-     *
-     * @return The index of the paragraph containing the specified position,
-     *         starting from 0.
-     *
-     * @throws IllegalStateException if this call is not preceded by a successful
-     *         call to <code>setPara</code> or <code>setLine</code>
-     * @throws IllegalArgumentException if charIndex is not within the legal range
-     *
-     * @see com.ibm.icu.text.BidiRun
-     * @see #getProcessedLength
-     * @stable ICU 3.8
-     */
-    public int getParagraphIndex(int charIndex)
-    {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Set a custom Bidi classifier used by the UBA implementation for Bidi
-     * class determination.
-     *
-     * @param classifier A new custom classifier. This can be null.
-     *
-     * @see #getCustomClassifier
-     * @stable ICU 3.8
-     */
-    public void setCustomClassifier(BidiClassifier classifier) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Gets the current custom class classifier used for Bidi class
-     * determination.
-     *
-     * @return An instance of class <code>BidiClassifier</code>
-     *
-     * @see #setCustomClassifier
-     * @stable ICU 3.8
-     */
-    public BidiClassifier getCustomClassifier() {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Retrieves the Bidi class for a given code point.
-     * <p>If a <code>BidiClassifier</code> is defined and returns a value
-     * other than <code>CLASS_DEFAULT</code>, that value is used; otherwise
-     * the default class determination mechanism is invoked.</p>
-     *
-     * @param c The code point to get a Bidi class for.
-     *
-     * @return The Bidi class for the character <code>c</code> that is in effect
-     *         for this <code>Bidi</code> instance.
-     *
-     * @see BidiClassifier
-     * @stable ICU 3.8
-     */
-    public int getCustomizedClass(int c) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * <code>setLine()</code> returns a <code>Bidi</code> object to
-     * contain the reordering information, especially the resolved levels,
-     * for all the characters in a line of text. This line of text is
-     * specified by referring to a <code>Bidi</code> object representing
-     * this information for a piece of text containing one or more paragraphs,
-     * and by specifying a range of indexes in this text.<p>
-     * In the new line object, the indexes will range from 0 to <code>limit-start-1</code>.<p>
-     *
-     * This is used after calling <code>setPara()</code>
-     * for a piece of text, and after line-breaking on that text.
-     * It is not necessary if each paragraph is treated as a single line.<p>
-     *
-     * After line-breaking, rules (L1) and (L2) for the treatment of
-     * trailing WS and for reordering are performed on
-     * a <code>Bidi</code> object that represents a line.<p>
-     *
-     * <strong>Important: </strong>the line <code>Bidi</code> object may
-     * reference data within the global text <code>Bidi</code> object.
-     * You should not alter the content of the global text object until
-     * you are finished using the line object.
-     *
-     * @param start is the line's first index into the text.
-     *
-     * @param limit is just behind the line's last index into the text
-     *        (its last index +1).
-     *
-     * @return a <code>Bidi</code> object that will now represent a line of the text.
-     *
-     * @throws IllegalStateException if this call is not preceded by a successful
-     *         call to <code>setPara</code>
-     * @throws IllegalArgumentException if start and limit are not in the range
-     *         <code>0&lt;=start&lt;limit&lt;=getProcessedLength()</code>,
-     *         or if the specified line crosses a paragraph boundary
-     *
-     * @see #setPara
-     * @see #getProcessedLength
-     * @stable ICU 3.8
-     */
-    public Bidi setLine(int start, int limit)
-    {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Get the level for one character.
-     *
-     * @param charIndex the index of a character.
-     *
-     * @return The level for the character at <code>charIndex</code>.
-     *
-     * @throws IllegalStateException if this call is not preceded by a successful
-     *         call to <code>setPara</code> or <code>setLine</code>
-     * @throws IllegalArgumentException if charIndex is not in the range
-     *         <code>0&lt;=charIndex&lt;getProcessedLength()</code>
-     *
-     * @see #getProcessedLength
-     * @stable ICU 3.8
-     */
-    public byte getLevelAt(int charIndex)
-    {
-        return (byte)bidi.getLevelAt(charIndex);
-    }
-
-    /**
-     * Get an array of levels for each character.<p>
-     *
-     * Note that this method may allocate memory under some
-     * circumstances, unlike <code>getLevelAt()</code>.
-     *
-     * @return The levels array for the text,
-     *         or <code>null</code> if an error occurs.
-     *
-     * @throws IllegalStateException if this call is not preceded by a successful
-     *         call to <code>setPara</code> or <code>setLine</code>
-     * @stable ICU 3.8
-     */
-    public byte[] getLevels()
-    {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Get a logical run.
-     * This method returns information about a run and is used
-     * to retrieve runs in logical order.<p>
-     * This is especially useful for line-breaking on a paragraph.
-     *
-     * @param logicalPosition is a logical position within the source text.
-     *
-     * @return a BidiRun object filled with <code>start</code> containing
-     *        the first character of the run, <code>limit</code> containing
-     *        the limit of the run, and <code>embeddingLevel</code> containing
-     *        the level of the run.
-     *
-     * @throws IllegalStateException if this call is not preceded by a successful
-     *         call to <code>setPara</code> or <code>setLine</code>
-     * @throws IllegalArgumentException if logicalPosition is not in the range
-     *         <code>0&lt;=logicalPosition&lt;getProcessedLength()</code>
-     *
-     * @see com.ibm.icu.text.BidiRun
-     * @see com.ibm.icu.text.BidiRun#getStart()
-     * @see com.ibm.icu.text.BidiRun#getLimit()
-     * @see com.ibm.icu.text.BidiRun#getEmbeddingLevel()
-     *
-     * @stable ICU 3.8
-     */
-    public BidiRun getLogicalRun(int logicalPosition)
-    {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Get the number of runs.
-     * This method may invoke the actual reordering on the
-     * <code>Bidi</code> object, after <code>setPara()</code>
-     * may have resolved only the levels of the text. Therefore,
-     * <code>countRuns()</code> may have to allocate memory,
-     * and may throw an exception if it fails to do so.
-     *
-     * @return The number of runs.
-     *
-     * @throws IllegalStateException if this call is not preceded by a successful
-     *         call to <code>setPara</code> or <code>setLine</code>
-     * @stable ICU 3.8
-     */
-    public int countRuns()
-    {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     *
-     * Get a <code>BidiRun</code> object according to its index. BidiRun methods
-     * may be used to retrieve the run's logical start, length and level,
-     * which can be even for an LTR run or odd for an RTL run.
-     * In an RTL run, the character at the logical start is
-     * visually on the right of the displayed run.
-     * The length is the number of characters in the run.<p>
-     * <code>countRuns()</code> is normally called
-     * before the runs are retrieved.
-     *
-     * <p>
-     *  Example:
-     * <pre>
-     *  Bidi bidi = new Bidi();
-     *  String text = "abc 123 DEFG xyz";
-     *  bidi.setPara(text, Bidi.RTL, null);
-     *  int i, count=bidi.countRuns(), logicalStart, visualIndex=0, length;
-     *  BidiRun run;
-     *  for (i = 0; i &lt; count; ++i) {
-     *      run = bidi.getVisualRun(i);
-     *      logicalStart = run.getStart();
-     *      length = run.getLength();
-     *      if (Bidi.LTR == run.getEmbeddingLevel()) {
-     *          do { // LTR
-     *              show_char(text.charAt(logicalStart++), visualIndex++);
-     *          } while (--length &gt; 0);
-     *      } else {
-     *          logicalStart += length;  // logicalLimit
-     *          do { // RTL
-     *              show_char(text.charAt(--logicalStart), visualIndex++);
-     *          } while (--length &gt; 0);
-     *      }
-     *  }
-     * </pre>
-     * <p>
-     * Note that in right-to-left runs, code like this places
-     * second surrogates before first ones (which is generally a bad idea)
-     * and combining characters before base characters.
-     * <p>
-     * Use of <code>{@link #writeReordered}</code>, optionally with the
-     * <code>{@link #KEEP_BASE_COMBINING}</code> option, can be considered in
-     * order to avoid these issues.
-     *
-     * @param runIndex is the number of the run in visual order, in the
-     *        range <code>[0..countRuns()-1]</code>.
-     *
-     * @return a BidiRun object containing the details of the run. The
-     *         directionality of the run is
-     *         <code>LTR==0</code> or <code>RTL==1</code>,
-     *         never <code>MIXED</code>.
-     *
-     * @throws IllegalStateException if this call is not preceded by a successful
-     *         call to <code>setPara</code> or <code>setLine</code>
-     * @throws IllegalArgumentException if <code>runIndex</code> is not in
-     *         the range <code>0&lt;=runIndex&lt;countRuns()</code>
-     *
-     * @see #countRuns()
-     * @see com.ibm.icu.text.BidiRun
-     * @see com.ibm.icu.text.BidiRun#getStart()
-     * @see com.ibm.icu.text.BidiRun#getLength()
-     * @see com.ibm.icu.text.BidiRun#getEmbeddingLevel()
-     * @stable ICU 3.8
-     */
-    public BidiRun getVisualRun(int runIndex)
-    {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Get the visual position from a logical text position.
-     * If such a mapping is used many times on the same
-     * <code>Bidi</code> object, then calling
-     * <code>getLogicalMap()</code> is more efficient.
-     * <p>
-     * The value returned may be <code>MAP_NOWHERE</code> if there is no
-     * visual position because the corresponding text character is a Bidi
-     * control removed from output by the option
-     * <code>OPTION_REMOVE_CONTROLS</code>.
-     * <p>
-     * When the visual output is altered by using options of
-     * <code>writeReordered()</code> such as <code>INSERT_LRM_FOR_NUMERIC</code>,
-     * <code>KEEP_BASE_COMBINING</code>, <code>OUTPUT_REVERSE</code>,
-     * <code>REMOVE_BIDI_CONTROLS</code>, the visual position returned may not
-     * be correct. It is advised to use, when possible, reordering options
-     * such as {@link #OPTION_INSERT_MARKS} and {@link #OPTION_REMOVE_CONTROLS}.
-     * <p>
-     * Note that in right-to-left runs, this mapping places
-     * second surrogates before first ones (which is generally a bad idea)
-     * and combining characters before base characters.
-     * Use of <code>{@link #writeReordered}</code>, optionally with the
-     * <code>{@link #KEEP_BASE_COMBINING}</code> option can be considered instead
-     * of using the mapping, in order to avoid these issues.
-     *
-     * @param logicalIndex is the index of a character in the text.
-     *
-     * @return The visual position of this character.
-     *
-     * @throws IllegalStateException if this call is not preceded by a successful
-     *         call to <code>setPara</code> or <code>setLine</code>
-     * @throws IllegalArgumentException if <code>logicalIndex</code> is not in
-     *         the range <code>0&lt;=logicalIndex&lt;getProcessedLength()</code>
-     *
-     * @see #getLogicalMap
-     * @see #getLogicalIndex
-     * @see #getProcessedLength
-     * @see #MAP_NOWHERE
-     * @see #OPTION_REMOVE_CONTROLS
-     * @see #writeReordered
-     * @stable ICU 3.8
-     */
-    public int getVisualIndex(int logicalIndex)
-    {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-
-    /**
-     * Get the logical text position from a visual position.
-     * If such a mapping is used many times on the same
-     * <code>Bidi</code> object, then calling
-     * <code>getVisualMap()</code> is more efficient.
-     * <p>
-     * The value returned may be <code>MAP_NOWHERE</code> if there is no
-     * logical position because the corresponding text character is a Bidi
-     * mark inserted in the output by option
-     * <code>OPTION_INSERT_MARKS</code>.
-     * <p>
-     * This is the inverse method to <code>getVisualIndex()</code>.
-     * <p>
-     * When the visual output is altered by using options of
-     * <code>writeReordered()</code> such as <code>INSERT_LRM_FOR_NUMERIC</code>,
-     * <code>KEEP_BASE_COMBINING</code>, <code>OUTPUT_REVERSE</code>,
-     * <code>REMOVE_BIDI_CONTROLS</code>, the logical position returned may not
-     * be correct. It is advised to use, when possible, reordering options
-     * such as {@link #OPTION_INSERT_MARKS} and {@link #OPTION_REMOVE_CONTROLS}.
-     *
-     * @param visualIndex is the visual position of a character.
-     *
-     * @return The index of this character in the text.
-     *
-     * @throws IllegalStateException if this call is not preceded by a successful
-     *         call to <code>setPara</code> or <code>setLine</code>
-     * @throws IllegalArgumentException if <code>visualIndex</code> is not in
-     *         the range <code>0&lt;=visualIndex&lt;getResultLength()</code>
-     *
-     * @see #getVisualMap
-     * @see #getVisualIndex
-     * @see #getResultLength
-     * @see #MAP_NOWHERE
-     * @see #OPTION_INSERT_MARKS
-     * @see #writeReordered
-     * @stable ICU 3.8
-     */
-    public int getLogicalIndex(int visualIndex)
-    {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Get a logical-to-visual index map (array) for the characters in the
-     * <code>Bidi</code> (paragraph or line) object.
-     * <p>
-     * Some values in the map may be <code>MAP_NOWHERE</code> if the
-     * corresponding text characters are Bidi controls removed from the visual
-     * output by the option <code>OPTION_REMOVE_CONTROLS</code>.
-     * <p>
-     * When the visual output is altered by using options of
-     * <code>writeReordered()</code> such as <code>INSERT_LRM_FOR_NUMERIC</code>,
-     * <code>KEEP_BASE_COMBINING</code>, <code>OUTPUT_REVERSE</code>,
-     * <code>REMOVE_BIDI_CONTROLS</code>, the visual positions returned may not
-     * be correct. It is advised to use, when possible, reordering options
-     * such as {@link #OPTION_INSERT_MARKS} and {@link #OPTION_REMOVE_CONTROLS}.
-     * <p>
-     * Note that in right-to-left runs, this mapping places
-     * second surrogates before first ones (which is generally a bad idea)
-     * and combining characters before base characters.
-     * Use of <code>{@link #writeReordered}</code>, optionally with the
-     * <code>{@link #KEEP_BASE_COMBINING}</code> option can be considered instead
-     * of using the mapping, in order to avoid these issues.
-     *
-     * @return an array of <code>getProcessedLength()</code>
-     *        indexes which will reflect the reordering of the characters.<br><br>
-     *        The index map will result in
-     *        <code>indexMap[logicalIndex]==visualIndex</code>, where
-     *        <code>indexMap</code> represents the returned array.
-     *
-     * @throws IllegalStateException if this call is not preceded by a successful
-     *         call to <code>setPara</code> or <code>setLine</code>
-     *
-     * @see #getVisualMap
-     * @see #getVisualIndex
-     * @see #getProcessedLength
-     * @see #MAP_NOWHERE
-     * @see #OPTION_REMOVE_CONTROLS
-     * @see #writeReordered
-     * @stable ICU 3.8
-     */
-    public int[] getLogicalMap()
-    {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Get a visual-to-logical index map (array) for the characters in the
-     * <code>Bidi</code> (paragraph or line) object.
-     * <p>
-     * Some values in the map may be <code>MAP_NOWHERE</code> if the
-     * corresponding text characters are Bidi marks inserted in the visual
-     * output by the option <code>OPTION_INSERT_MARKS</code>.
-     * <p>
-     * When the visual output is altered by using options of
-     * <code>writeReordered()</code> such as <code>INSERT_LRM_FOR_NUMERIC</code>,
-     * <code>KEEP_BASE_COMBINING</code>, <code>OUTPUT_REVERSE</code>,
-     * <code>REMOVE_BIDI_CONTROLS</code>, the logical positions returned may not
-     * be correct. It is advised to use, when possible, reordering options
-     * such as {@link #OPTION_INSERT_MARKS} and {@link #OPTION_REMOVE_CONTROLS}.
-     *
-     * @return an array of <code>getResultLength()</code>
-     *        indexes which will reflect the reordering of the characters.<br><br>
-     *        The index map will result in
-     *        <code>indexMap[visualIndex]==logicalIndex</code>, where
-     *        <code>indexMap</code> represents the returned array.
-     *
-     * @throws IllegalStateException if this call is not preceded by a successful
-     *         call to <code>setPara</code> or <code>setLine</code>
-     *
-     * @see #getLogicalMap
-     * @see #getLogicalIndex
-     * @see #getResultLength
-     * @see #MAP_NOWHERE
-     * @see #OPTION_INSERT_MARKS
-     * @see #writeReordered
-     * @stable ICU 3.8
-     */
-    public int[] getVisualMap()
-    {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * This is a convenience method that does not use a <code>Bidi</code> object.
-     * It is intended to be used for when an application has determined the levels
-     * of objects (character sequences) and just needs to have them reordered (L2).
-     * This is equivalent to using <code>getLogicalMap()</code> on a
-     * <code>Bidi</code> object.
-     *
-     * @param levels is an array of levels that have been determined by
-     *        the application.
-     *
-     * @return an array of <code>levels.length</code>
-     *        indexes which will reflect the reordering of the characters.<p>
-     *        The index map will result in
-     *        <code>indexMap[logicalIndex]==visualIndex</code>, where
-     *        <code>indexMap</code> represents the returned array.
-     *
-     * @stable ICU 3.8
-     */
-    public static int[] reorderLogical(byte[] levels)
-    {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * This is a convenience method that does not use a <code>Bidi</code> object.
-     * It is intended to be used for when an application has determined the levels
-     * of objects (character sequences) and just needs to have them reordered (L2).
-     * This is equivalent to using <code>getVisualMap()</code> on a
-     * <code>Bidi</code> object.
-     *
-     * @param levels is an array of levels that have been determined by
-     *        the application.
-     *
-     * @return an array of <code>levels.length</code>
-     *        indexes which will reflect the reordering of the characters.<p>
-     *        The index map will result in
-     *        <code>indexMap[visualIndex]==logicalIndex</code>, where
-     *        <code>indexMap</code> represents the returned array.
-     *
-     * @stable ICU 3.8
-     */
-    public static int[] reorderVisual(byte[] levels)
-    {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Invert an index map.
-     * The index mapping of the argument map is inverted and returned as
-     * an array of indexes that we will call the inverse map.
-     *
-     * @param srcMap is an array whose elements define the original mapping
-     * from a source array to a destination array.
-     * Some elements of the source array may have no mapping in the
-     * destination array. In that case, their value will be
-     * the special value <code>MAP_NOWHERE</code>.
-     * All elements must be >=0 or equal to <code>MAP_NOWHERE</code>.
-     * Some elements in the source map may have a value greater than the
-     * srcMap.length if the destination array has more elements than the
-     * source array.
-     * There must be no duplicate indexes (two or more elements with the
-     * same value except <code>MAP_NOWHERE</code>).
-     *
-     * @return an array representing the inverse map.
-     *         This array has a number of elements equal to 1 + the highest
-     *         value in <code>srcMap</code>.
-     *         For elements of the result array which have no matching elements
-     *         in the source array, the corresponding elements in the inverse
-     *         map will receive a value equal to <code>MAP_NOWHERE</code>.
-     *         If element with index i in <code>srcMap</code> has a value k different
-     *         from <code>MAP_NOWHERE</code>, this means that element i of
-     *         the source array maps to element k in the destination array.
-     *         The inverse map will have value i in its k-th element.
-     *         For all elements of the destination array which do not map to
-     *         an element in the source array, the corresponding element in the
-     *         inverse map will have a value equal to <code>MAP_NOWHERE</code>.
-     *
-     * @see #MAP_NOWHERE
-     * @stable ICU 3.8
-     */
-    public static int[] invertMap(int[] srcMap)
-    {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /*
-     * Fields and methods for compatibility with java.text.bidi (Sun implementation)
-     */
-
-    /**
-     * Constant indicating base direction is left-to-right.
-     * @stable ICU 3.8
-     */
-    public static final int DIRECTION_LEFT_TO_RIGHT = LTR;
-
-    /**
-     * Constant indicating base direction is right-to-left.
-     * @stable ICU 3.8
-     */
-    public static final int DIRECTION_RIGHT_TO_LEFT = RTL;
-
-    /**
-     * Constant indicating that the base direction depends on the first strong
-     * directional character in the text according to the Unicode Bidirectional
-     * Algorithm. If no strong directional character is present, the base
-     * direction is left-to-right.
-     * @stable ICU 3.8
-     */
-    public static final int DIRECTION_DEFAULT_LEFT_TO_RIGHT = LEVEL_DEFAULT_LTR;
-
-    /**
-     * Constant indicating that the base direction depends on the first strong
-     * directional character in the text according to the Unicode Bidirectional
-     * Algorithm. If no strong directional character is present, the base
-     * direction is right-to-left.
-     * @stable ICU 3.8
-     */
-    public static final int DIRECTION_DEFAULT_RIGHT_TO_LEFT = LEVEL_DEFAULT_RTL;
-
-    /**
-     * Create Bidi from the given paragraph of text and base direction.
-     *
-     * @param paragraph a paragraph of text
-     * @param flags a collection of flags that control the algorithm. The
-     *        algorithm understands the flags DIRECTION_LEFT_TO_RIGHT,
-     *        DIRECTION_RIGHT_TO_LEFT, DIRECTION_DEFAULT_LEFT_TO_RIGHT, and
-     *        DIRECTION_DEFAULT_RIGHT_TO_LEFT. Other values are reserved.
-     * @see #DIRECTION_LEFT_TO_RIGHT
-     * @see #DIRECTION_RIGHT_TO_LEFT
-     * @see #DIRECTION_DEFAULT_LEFT_TO_RIGHT
-     * @see #DIRECTION_DEFAULT_RIGHT_TO_LEFT
-     * @stable ICU 3.8
-     */
-    public Bidi(String paragraph, int flags)
-    {
-        // Note: ICU and Oracle JDK are using the
-        // same DIRECTION_* flags definitions.
-        this(new java.text.Bidi(paragraph, flags));
-    }
-
-    /**
-     * Create Bidi from the given paragraph of text.<p>
-     *
-     * The RUN_DIRECTION attribute in the text, if present, determines the base
-     * direction (left-to-right or right-to-left). If not present, the base
-     * direction is computed using the Unicode Bidirectional Algorithm,
-     * defaulting to left-to-right if there are no strong directional characters
-     * in the text. This attribute, if present, must be applied to all the text
-     * in the paragraph.<p>
-     *
-     * The BIDI_EMBEDDING attribute in the text, if present, represents
-     * embedding level information. Negative values from -1 to -62 indicate
-     * overrides at the absolute value of the level. Positive values from 1 to
-     * 62 indicate embeddings. Where values are zero or not defined, the base
-     * embedding level as determined by the base direction is assumed.<p>
-     *
-     * The NUMERIC_SHAPING attribute in the text, if present, converts European
-     * digits to other decimal digits before running the bidi algorithm. This
-     * attribute, if present, must be applied to all the text in the paragraph.<p>
-     *
-     * Note: this constructor calls setPara() internally.
-     *
-     * @param paragraph a paragraph of text with optional character and
-     *        paragraph attribute information
-     * @stable ICU 3.8
-     */
-    public Bidi(AttributedCharacterIterator paragraph)
-    {
-        // ICU does not define its own attributes and just
-        // use java.awt.font.TextAttribute. Thus, no mappings
-        // are necessary.
-        this(new java.text.Bidi(paragraph));
-    }
-
-    /**
-     * Create Bidi from the given text, embedding, and direction information.
-     * The embeddings array may be null. If present, the values represent
-     * embedding level information. Negative values from -1 to -61 indicate
-     * overrides at the absolute value of the level. Positive values from 1 to
-     * 61 indicate embeddings. Where values are zero, the base embedding level
-     * as determined by the base direction is assumed.<p>
-     *
-     * Note: this constructor calls setPara() internally.
-     *
-     * @param text an array containing the paragraph of text to process.
-     * @param textStart the index into the text array of the start of the
-     *        paragraph.
-     * @param embeddings an array containing embedding values for each character
-     *        in the paragraph. This can be null, in which case it is assumed
-     *        that there is no external embedding information.
-     * @param embStart the index into the embedding array of the start of the
-     *        paragraph.
-     * @param paragraphLength the length of the paragraph in the text and
-     *        embeddings arrays.
-     * @param flags a collection of flags that control the algorithm. The
-     *        algorithm understands the flags DIRECTION_LEFT_TO_RIGHT,
-     *        DIRECTION_RIGHT_TO_LEFT, DIRECTION_DEFAULT_LEFT_TO_RIGHT, and
-     *        DIRECTION_DEFAULT_RIGHT_TO_LEFT. Other values are reserved.
-     *
-     * @throws IllegalArgumentException if the values in embeddings are
-     *         not within the allowed range
-     *
-     * @see #DIRECTION_LEFT_TO_RIGHT
-     * @see #DIRECTION_RIGHT_TO_LEFT
-     * @see #DIRECTION_DEFAULT_LEFT_TO_RIGHT
-     * @see #DIRECTION_DEFAULT_RIGHT_TO_LEFT
-     * @stable ICU 3.8
-     */
-    public Bidi(char[] text,
-            int textStart,
-            byte[] embeddings,
-            int embStart,
-            int paragraphLength,
-            int flags)
-    {
-        // Note: ICU and Oracle JDK are using the
-        // same DIRECTION_* flags definitions.
-        this(new java.text.Bidi(text, textStart, embeddings, embStart, paragraphLength, flags));
-    }
-
-    /**
-     * Create a Bidi object representing the bidi information on a line of text
-     * within the paragraph represented by the current Bidi. This call is not
-     * required if the entire paragraph fits on one line.
-     *
-     * @param lineStart the offset from the start of the paragraph to the start
-     *        of the line.
-     * @param lineLimit the offset from the start of the paragraph to the limit
-     *        of the line.
-     *
-     * @throws IllegalStateException if this call is not preceded by a successful
-     *         call to <code>setPara</code>
-     * @throws IllegalArgumentException if lineStart and lineLimit are not in the range
-     *         <code>0&lt;=lineStart&lt;lineLimit&lt;=getProcessedLength()</code>,
-     *         or if the specified line crosses a paragraph boundary
-     * @stable ICU 3.8
-     */
-    public Bidi createLineBidi(int lineStart, int lineLimit)
-    {
-        return new Bidi(bidi.createLineBidi(lineStart, lineLimit));
-    }
-
-    /**
-     * Return true if the line is not left-to-right or right-to-left. This means
-     * it either has mixed runs of left-to-right and right-to-left text, or the
-     * base direction differs from the direction of the only run of text.
-     *
-     * @return true if the line is not left-to-right or right-to-left.
-     *
-     * @throws IllegalStateException if this call is not preceded by a successful
-     *         call to <code>setPara</code>
-     * @stable ICU 3.8
-     */
-    public boolean isMixed()
-    {
-        return bidi.isMixed();
-    }
-
-    /**
-     * Return true if the line is all left-to-right text and the base direction
-     * is left-to-right.
-     *
-     * @return true if the line is all left-to-right text and the base direction
-     *         is left-to-right.
-     *
-     * @throws IllegalStateException if this call is not preceded by a successful
-     *         call to <code>setPara</code>
-     * @stable ICU 3.8
-     */
-    public boolean isLeftToRight()
-    {
-        return bidi.isLeftToRight();
-    }
-
-    /**
-     * Return true if the line is all right-to-left text, and the base direction
-     * is right-to-left
-     *
-     * @return true if the line is all right-to-left text, and the base
-     *         direction is right-to-left
-     *
-     * @throws IllegalStateException if this call is not preceded by a successful
-     *         call to <code>setPara</code>
-     * @stable ICU 3.8
-     */
-    public boolean isRightToLeft()
-    {
-        return bidi.isRightToLeft();
-    }
-
-    /**
-     * Return true if the base direction is left-to-right
-     *
-     * @return true if the base direction is left-to-right
-     *
-     * @throws IllegalStateException if this call is not preceded by a successful
-     *         call to <code>setPara</code> or <code>setLine</code>
-     *
-     * @stable ICU 3.8
-     */
-    public boolean baseIsLeftToRight()
-    {
-        return bidi.baseIsLeftToRight();
-    }
-
-    /**
-     * Return the base level (0 if left-to-right, 1 if right-to-left).
-     *
-     * @return the base level
-     *
-     * @throws IllegalStateException if this call is not preceded by a successful
-     *         call to <code>setPara</code> or <code>setLine</code>
-     *
-     * @stable ICU 3.8
-     */
-    public int getBaseLevel()
-    {
-        return bidi.getBaseLevel();
-    }
-
-    /**
-     * Return the number of level runs.
-     *
-     * @return the number of level runs
-     *
-     * @throws IllegalStateException if this call is not preceded by a successful
-     *         call to <code>setPara</code> or <code>setLine</code>
-     *
-     * @stable ICU 3.8
-     */
-    public int getRunCount()
-    {
-        return bidi.getRunCount();
-    }
-
-    /**
-     * Return the level of the nth logical run in this line.
-     *
-     * @param run the index of the run, between 0 and <code>countRuns()-1</code>
-     *
-     * @return the level of the run
-     *
-     * @throws IllegalStateException if this call is not preceded by a successful
-     *         call to <code>setPara</code> or <code>setLine</code>
-     * @throws IllegalArgumentException if <code>run</code> is not in
-     *         the range <code>0&lt;=run&lt;countRuns()</code>
-     * @stable ICU 3.8
-     */
-    public int getRunLevel(int run)
-    {
-        return bidi.getRunLevel(run);
-    }
-
-    /**
-     * Return the index of the character at the start of the nth logical run in
-     * this line, as an offset from the start of the line.
-     *
-     * @param run the index of the run, between 0 and <code>countRuns()</code>
-     *
-     * @return the start of the run
-     *
-     * @throws IllegalStateException if this call is not preceded by a successful
-     *         call to <code>setPara</code> or <code>setLine</code>
-     * @throws IllegalArgumentException if <code>run</code> is not in
-     *         the range <code>0&lt;=run&lt;countRuns()</code>
-     * @stable ICU 3.8
-     */
-    public int getRunStart(int run)
-    {
-        return bidi.getRunStart(run);
-    }
-
-    /**
-     * Return the index of the character past the end of the nth logical run in
-     * this line, as an offset from the start of the line. For example, this
-     * will return the length of the line for the last run on the line.
-     *
-     * @param run the index of the run, between 0 and <code>countRuns()</code>
-     *
-     * @return the limit of the run
-     *
-     * @throws IllegalStateException if this call is not preceded by a successful
-     *         call to <code>setPara</code> or <code>setLine</code>
-     * @throws IllegalArgumentException if <code>run</code> is not in
-     *         the range <code>0&lt;=run&lt;countRuns()</code>
-     * @stable ICU 3.8
-     */
-    public int getRunLimit(int run)
-    {
-        return bidi.getRunLimit(run);
-    }
-
-    /**
-     * Return true if the specified text requires bidi analysis. If this returns
-     * false, the text will display left-to-right. Clients can then avoid
-     * constructing a Bidi object. Text in the Arabic Presentation Forms area of
-     * Unicode is presumed to already be shaped and ordered for display, and so
-     * will not cause this method to return true.
-     *
-     * @param text the text containing the characters to test
-     * @param start the start of the range of characters to test
-     * @param limit the limit of the range of characters to test
-     *
-     * @return true if the range of characters requires bidi analysis
-     *
-     * @stable ICU 3.8
-     */
-    public static boolean requiresBidi(char[] text,
-            int start,
-            int limit)
-    {
-        return java.text.Bidi.requiresBidi(text, start, limit);
-    }
-
-    /**
-     * Reorder the objects in the array into visual order based on their levels.
-     * This is a utility method to use when you have a collection of objects
-     * representing runs of text in logical order, each run containing text at a
-     * single level. The elements at <code>index</code> from
-     * <code>objectStart</code> up to <code>objectStart + count</code> in the
-     * objects array will be reordered into visual order assuming
-     * each run of text has the level indicated by the corresponding element in
-     * the levels array (at <code>index - objectStart + levelStart</code>).
-     *
-     * @param levels an array representing the bidi level of each object
-     * @param levelStart the start position in the levels array
-     * @param objects the array of objects to be reordered into visual order
-     * @param objectStart the start position in the objects array
-     * @param count the number of objects to reorder
-     * @stable ICU 3.8
-     */
-    public static void reorderVisually(byte[] levels,
-            int levelStart,
-            Object[] objects,
-            int objectStart,
-            int count)
-    {
-        java.text.Bidi.reorderVisually(levels, levelStart, objects, objectStart, count);
-    }
-
-    /**
-     * Take a <code>Bidi</code> object containing the reordering
-     * information for a piece of text (one or more paragraphs) set by
-     * <code>setPara()</code> or for a line of text set by <code>setLine()</code>
-     * and return a string containing the reordered text.
-     *
-     * <p>The text may have been aliased (only a reference was stored
-     * without copying the contents), thus it must not have been modified
-     * since the <code>setPara()</code> call.</p>
-     *
-     * This method preserves the integrity of characters with multiple
-     * code units and (optionally) combining characters.
-     * Characters in RTL runs can be replaced by mirror-image characters
-     * in the returned string. Note that "real" mirroring has to be done in a
-     * rendering engine by glyph selection and that for many "mirrored"
-     * characters there are no Unicode characters as mirror-image equivalents.
-     * There are also options to insert or remove Bidi control
-     * characters; see the descriptions of the return value and the
-     * <code>options</code> parameter, and of the option bit flags.
-     *
-     * @param options A bit set of options for the reordering that control
-     *                how the reordered text is written.
-     *                The options include mirroring the characters on a code
-     *                point basis and inserting LRM characters, which is used
-     *                especially for transforming visually stored text
-     *                to logically stored text (although this is still an
-     *                imperfect implementation of an "inverse Bidi" algorithm
-     *                because it uses the "forward Bidi" algorithm at its core).
-     *                The available options are:
-     *                <code>DO_MIRRORING</code>,
-     *                <code>INSERT_LRM_FOR_NUMERIC</code>,
-     *                <code>KEEP_BASE_COMBINING</code>,
-     *                <code>OUTPUT_REVERSE</code>,
-     *                <code>REMOVE_BIDI_CONTROLS</code>,
-     *                <code>STREAMING</code>
-     *
-     * @return The reordered text.
-     *         If the <code>INSERT_LRM_FOR_NUMERIC</code> option is set, then
-     *         the length of the returned string could be as large as
-     *         <code>getLength()+2*countRuns()</code>.<br>
-     *         If the <code>REMOVE_BIDI_CONTROLS</code> option is set, then the
-     *         length of the returned string may be less than
-     *         <code>getLength()</code>.<br>
-     *         If none of these options is set, then the length of the returned
-     *         string will be exactly <code>getProcessedLength()</code>.
-     *
-     * @throws IllegalStateException if this call is not preceded by a successful
-     *         call to <code>setPara</code> or <code>setLine</code>
-     *
-     * @see #DO_MIRRORING
-     * @see #INSERT_LRM_FOR_NUMERIC
-     * @see #KEEP_BASE_COMBINING
-     * @see #OUTPUT_REVERSE
-     * @see #REMOVE_BIDI_CONTROLS
-     * @see #OPTION_STREAMING
-     * @see #getProcessedLength
-     * @stable ICU 3.8
-     */
-    public String writeReordered(int options)
-    {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Reverse a Right-To-Left run of Unicode text.
-     *
-     * This method preserves the integrity of characters with multiple
-     * code units and (optionally) combining characters.
-     * Characters can be replaced by mirror-image characters
-     * in the destination buffer. Note that "real" mirroring has
-     * to be done in a rendering engine by glyph selection
-     * and that for many "mirrored" characters there are no
-     * Unicode characters as mirror-image equivalents.
-     * There are also options to insert or remove Bidi control
-     * characters.
-     *
-     * This method is the implementation for reversing RTL runs as part
-     * of <code>writeReordered()</code>. For detailed descriptions
-     * of the parameters, see there.
-     * Since no Bidi controls are inserted here, the output string length
-     * will never exceed <code>src.length()</code>.
-     *
-     * @see #writeReordered
-     *
-     * @param src The RTL run text.
-     *
-     * @param options A bit set of options for the reordering that control
-     *                how the reordered text is written.
-     *                See the <code>options</code> parameter in <code>writeReordered()</code>.
-     *
-     * @return The reordered text.
-     *         If the <code>REMOVE_BIDI_CONTROLS</code> option
-     *         is set, then the length of the returned string may be less than
-     *         <code>src.length()</code>. If this option is not set,
-     *         then the length of the returned string will be exactly
-     *         <code>src.length()</code>.
-     *
-     * @throws IllegalArgumentException if <code>src</code> is null.
-     * @stable ICU 3.8
-     */
-    public static String writeReverse(String src, int options)
-    {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-}
+/*
+*******************************************************************************
+*   Copyright (C) 2001-2011, International Business Machines
+*   Corporation and others.  All Rights Reserved.
+*******************************************************************************
+*/
+
+/* FOOD FOR THOUGHT: currently the reordering modes are a mixture of
+ * algorithm for direct BiDi, algorithm for inverse Bidi and the bizarre
+ * concept of RUNS_ONLY which is a double operation.
+ * It could be advantageous to divide this into 3 concepts:
+ * a) Operation: direct / inverse / RUNS_ONLY
+ * b) Direct algorithm: default / NUMBERS_SPECIAL / GROUP_NUMBERS_WITH_L
+ * c) Inverse algorithm: default / INVERSE_LIKE_DIRECT / NUMBERS_SPECIAL
+ * This would allow combinations not possible today like RUNS_ONLY with
+ * NUMBERS_SPECIAL.
+ * Also allow to set INSERT_MARKS for the direct step of RUNS_ONLY and
+ * REMOVE_CONTROLS for the inverse step.
+ * Not all combinations would be supported, and probably not all do make sense.
+ * This would need to document which ones are supported and what are the
+ * fallbacks for unsupported combinations.
+ */
+
+//TODO: make sample program do something simple but real and complete
+
+package com.ibm.icu.text;
+
+import java.text.AttributedCharacterIterator;
+
+/**
+ *
+ * <h2>Bidi algorithm for ICU</h2>
+ *
+ * This is an implementation of the Unicode Bidirectional algorithm. The
+ * algorithm is defined in the <a
+ * href="http://www.unicode.org/unicode/reports/tr9/">Unicode Standard Annex #9</a>,
+ * version 13, also described in The Unicode Standard, Version 4.0 .
+ * <p>
+ *
+ * Note: Libraries that perform a bidirectional algorithm and reorder strings
+ * accordingly are sometimes called "Storage Layout Engines". ICU's Bidi and
+ * shaping (ArabicShaping) classes can be used at the core of such "Storage
+ * Layout Engines".
+ *
+ * <h3>General remarks about the API:</h3>
+ *
+ * The &quot;limit&quot; of a sequence of characters is the position just after
+ * their last character, i.e., one more than that position.
+ * <p>
+ *
+ * Some of the API methods provide access to &quot;runs&quot;. Such a
+ * &quot;run&quot; is defined as a sequence of characters that are at the same
+ * embedding level after performing the Bidi algorithm.
+ * <p>
+ *
+ * <h3>Basic concept: paragraph</h3>
+ * A piece of text can be divided into several paragraphs by characters
+ * with the Bidi class <code>Block Separator</code>. For handling of
+ * paragraphs, see:
+ * <ul>
+ * <li>{@link #countParagraphs}
+ * <li>{@link #getParaLevel}
+ * <li>{@link #getParagraph}
+ * <li>{@link #getParagraphByIndex}
+ * </ul>
+ *
+ * <h3>Basic concept: text direction</h3>
+ * The direction of a piece of text may be:
+ * <ul>
+ * <li>{@link #LTR}
+ * <li>{@link #RTL}
+ * <li>{@link #MIXED}
+ * </ul>
+ *
+ * <h3>Basic concept: levels</h3>
+ *
+ * Levels in this API represent embedding levels according to the Unicode
+ * Bidirectional Algorithm.
+ * Their low-order bit (even/odd value) indicates the visual direction.<p>
+ *
+ * Levels can be abstract values when used for the
+ * <code>paraLevel</code> and <code>embeddingLevels</code>
+ * arguments of <code>setPara()</code>; there:
+ * <ul>
+ * <li>the high-order bit of an <code>embeddingLevels[]</code>
+ * value indicates whether the using application is
+ * specifying the level of a character to <i>override</i> whatever the
+ * Bidi implementation would resolve it to.</li>
+ * <li><code>paraLevel</code> can be set to the
+ * pseudo-level values <code>LEVEL_DEFAULT_LTR</code>
+ * and <code>LEVEL_DEFAULT_RTL</code>.</li>
+ * </ul>
+ *
+ * <p>The related constants are not real, valid level values.
+ * <code>DEFAULT_XXX</code> can be used to specify
+ * a default for the paragraph level for
+ * when the <code>setPara()</code> method
+ * shall determine it but there is no
+ * strongly typed character in the input.<p>
+ *
+ * Note that the value for <code>LEVEL_DEFAULT_LTR</code> is even
+ * and the one for <code>LEVEL_DEFAULT_RTL</code> is odd,
+ * just like with normal LTR and RTL level values -
+ * these special values are designed that way. Also, the implementation
+ * assumes that MAX_EXPLICIT_LEVEL is odd.
+ *
+ * <ul><b>See Also:</b>
+ * <li>{@link #LEVEL_DEFAULT_LTR}
+ * <li>{@link #LEVEL_DEFAULT_RTL}
+ * <li>{@link #LEVEL_OVERRIDE}
+ * <li>{@link #MAX_EXPLICIT_LEVEL}
+ * <li>{@link #setPara}
+ * </ul>
+ *
+ * <h3>Basic concept: Reordering Mode</h3>
+ * Reordering mode values indicate which variant of the Bidi algorithm to
+ * use.
+ *
+ * <ul><b>See Also:</b>
+ * <li>{@link #setReorderingMode}
+ * <li>{@link #REORDER_DEFAULT}
+ * <li>{@link #REORDER_NUMBERS_SPECIAL}
+ * <li>{@link #REORDER_GROUP_NUMBERS_WITH_R}
+ * <li>{@link #REORDER_RUNS_ONLY}
+ * <li>{@link #REORDER_INVERSE_NUMBERS_AS_L}
+ * <li>{@link #REORDER_INVERSE_LIKE_DIRECT}
+ * <li>{@link #REORDER_INVERSE_FOR_NUMBERS_SPECIAL}
+ * </ul>
+ *
+ * <h3>Basic concept: Reordering Options</h3>
+ * Reordering options can be applied during Bidi text transformations.
+ * <ul><b>See Also:</b>
+ * <li>{@link #setReorderingOptions}
+ * <li>{@link #OPTION_DEFAULT}
+ * <li>{@link #OPTION_INSERT_MARKS}
+ * <li>{@link #OPTION_REMOVE_CONTROLS}
+ * <li>{@link #OPTION_STREAMING}
+ * </ul>
+ *
+ *
+ * @author Simon Montagu, Matitiahu Allouche (ported from C code written by Markus W. Scherer)
+ * @stable ICU 3.8
+ *
+ *
+ * <h4> Sample code for the ICU Bidi API </h4>
+ *
+ * <h5>Rendering a paragraph with the ICU Bidi API</h5>
+ *
+ * This is (hypothetical) sample code that illustrates how the ICU Bidi API
+ * could be used to render a paragraph of text. Rendering code depends highly on
+ * the graphics system, therefore this sample code must make a lot of
+ * assumptions, which may or may not match any existing graphics system's
+ * properties.
+ *
+ * <p>
+ * The basic assumptions are:
+ * </p>
+ * <ul>
+ * <li>Rendering is done from left to right on a horizontal line.</li>
+ * <li>A run of single-style, unidirectional text can be rendered at once.
+ * </li>
+ * <li>Such a run of text is passed to the graphics system with characters
+ * (code units) in logical order.</li>
+ * <li>The line-breaking algorithm is very complicated and Locale-dependent -
+ * and therefore its implementation omitted from this sample code.</li>
+ * </ul>
+ *
+ * <pre>
+ *
+ *  package com.ibm.icu.dev.test.bidi;
+ *
+ *  import com.ibm.icu.text.Bidi;
+ *  import com.ibm.icu.text.BidiRun;
+ *
+ *  public class Sample {
+ *
+ *      static final int styleNormal = 0;
+ *      static final int styleSelected = 1;
+ *      static final int styleBold = 2;
+ *      static final int styleItalics = 4;
+ *      static final int styleSuper=8;
+ *      static final int styleSub = 16;
+ *
+ *      static class StyleRun {
+ *          int limit;
+ *          int style;
+ *
+ *          public StyleRun(int limit, int style) {
+ *              this.limit = limit;
+ *              this.style = style;
+ *          }
+ *      }
+ *
+ *      static class Bounds {
+ *          int start;
+ *          int limit;
+ *
+ *          public Bounds(int start, int limit) {
+ *              this.start = start;
+ *              this.limit = limit;
+ *          }
+ *      }
+ *
+ *      static int getTextWidth(String text, int start, int limit,
+ *                              StyleRun[] styleRuns, int styleRunCount) {
+ *          // simplistic way to compute the width
+ *          return limit - start;
+ *      }
+ *
+ *      // set limit and StyleRun limit for a line
+ *      // from text[start] and from styleRuns[styleRunStart]
+ *      // using Bidi.getLogicalRun(...)
+ *      // returns line width
+ *      static int getLineBreak(String text, Bounds line, Bidi para,
+ *                              StyleRun styleRuns[], Bounds styleRun) {
+ *          // dummy return
+ *          return 0;
+ *      }
+ *
+ *      // render runs on a line sequentially, always from left to right
+ *
+ *      // prepare rendering a new line
+ *      static void startLine(byte textDirection, int lineWidth) {
+ *          System.out.println();
+ *      }
+ *
+ *      // render a run of text and advance to the right by the run width
+ *      // the text[start..limit-1] is always in logical order
+ *      static void renderRun(String text, int start, int limit,
+ *                            byte textDirection, int style) {
+ *      }
+ *
+ *      // We could compute a cross-product
+ *      // from the style runs with the directional runs
+ *      // and then reorder it.
+ *      // Instead, here we iterate over each run type
+ *      // and render the intersections -
+ *      // with shortcuts in simple (and common) cases.
+ *      // renderParagraph() is the main function.
+ *
+ *      // render a directional run with
+ *      // (possibly) multiple style runs intersecting with it
+ *      static void renderDirectionalRun(String text, int start, int limit,
+ *                                       byte direction, StyleRun styleRuns[],
+ *                                       int styleRunCount) {
+ *          int i;
+ *
+ *          // iterate over style runs
+ *          if (direction == Bidi.LTR) {
+ *              int styleLimit;
+ *              for (i = 0; i < styleRunCount; ++i) {
+ *                  styleLimit = styleRuns[i].limit;
+ *                  if (start < styleLimit) {
+ *                      if (styleLimit > limit) {
+ *                          styleLimit = limit;
+ *                      }
+ *                      renderRun(text, start, styleLimit,
+ *                                direction, styleRuns[i].style);
+ *                      if (styleLimit == limit) {
+ *                          break;
+ *                      }
+ *                      start = styleLimit;
+ *                  }
+ *              }
+ *          } else {
+ *              int styleStart;
+ *
+ *              for (i = styleRunCount-1; i >= 0; --i) {
+ *                  if (i > 0) {
+ *                      styleStart = styleRuns[i-1].limit;
+ *                  } else {
+ *                      styleStart = 0;
+ *                  }
+ *                  if (limit >= styleStart) {
+ *                      if (styleStart < start) {
+ *                          styleStart = start;
+ *                      }
+ *                      renderRun(text, styleStart, limit, direction,
+ *                                styleRuns[i].style);
+ *                      if (styleStart == start) {
+ *                          break;
+ *                      }
+ *                      limit = styleStart;
+ *                  }
+ *              }
+ *          }
+ *      }
+ *
+ *      // the line object represents text[start..limit-1]
+ *      static void renderLine(Bidi line, String text, int start, int limit,
+ *                             StyleRun styleRuns[], int styleRunCount) {
+ *          byte direction = line.getDirection();
+ *          if (direction != Bidi.MIXED) {
+ *              // unidirectional
+ *              if (styleRunCount <= 1) {
+ *                  renderRun(text, start, limit, direction, styleRuns[0].style);
+ *              } else {
+ *                  renderDirectionalRun(text, start, limit, direction,
+ *                                       styleRuns, styleRunCount);
+ *              }
+ *          } else {
+ *              // mixed-directional
+ *              int count, i;
+ *              BidiRun run;
+ *
+ *              try {
+ *                  count = line.countRuns();
+ *              } catch (IllegalStateException e) {
+ *                  e.printStackTrace();
+ *                  return;
+ *              }
+ *              if (styleRunCount <= 1) {
+ *                  int style = styleRuns[0].style;
+ *
+ *                  // iterate over directional runs
+ *                  for (i = 0; i < count; ++i) {
+ *                      run = line.getVisualRun(i);
+ *                      renderRun(text, run.getStart(), run.getLimit(),
+ *                                run.getDirection(), style);
+ *                  }
+ *              } else {
+ *                  // iterate over both directional and style runs
+ *                  for (i = 0; i < count; ++i) {
+ *                      run = line.getVisualRun(i);
+ *                      renderDirectionalRun(text, run.getStart(),
+ *                                           run.getLimit(), run.getDirection(),
+ *                                           styleRuns, styleRunCount);
+ *                  }
+ *              }
+ *          }
+ *      }
+ *
+ *      static void renderParagraph(String text, byte textDirection,
+ *                                  StyleRun styleRuns[], int styleRunCount,
+ *                                  int lineWidth) {
+ *          int length = text.length();
+ *          Bidi para = new Bidi();
+ *          try {
+ *              para.setPara(text,
+ *                           textDirection != 0 ? Bidi.LEVEL_DEFAULT_RTL
+ *                                              : Bidi.LEVEL_DEFAULT_LTR,
+ *                           null);
+ *          } catch (Exception e) {
+ *              e.printStackTrace();
+ *              return;
+ *          }
+ *          byte paraLevel = (byte)(1 & para.getParaLevel());
+ *          StyleRun styleRun = new StyleRun(length, styleNormal);
+ *
+ *          if (styleRuns == null || styleRunCount <= 0) {
+ *              styleRuns = new StyleRun[1];
+ *              styleRunCount = 1;
+ *              styleRuns[0] = styleRun;
+ *          }
+ *          // assume styleRuns[styleRunCount-1].limit>=length
+ *
+ *          int width = getTextWidth(text, 0, length, styleRuns, styleRunCount);
+ *          if (width <= lineWidth) {
+ *              // everything fits onto one line
+ *
+ *              // prepare rendering a new line from either left or right
+ *              startLine(paraLevel, width);
+ *
+ *              renderLine(para, text, 0, length, styleRuns, styleRunCount);
+ *          } else {
+ *              // we need to render several lines
+ *              Bidi line = new Bidi(length, 0);
+ *              int start = 0, limit;
+ *              int styleRunStart = 0, styleRunLimit;
+ *
+ *              for (;;) {
+ *                  limit = length;
+ *                  styleRunLimit = styleRunCount;
+ *                  width = getLineBreak(text, new Bounds(start, limit),
+ *                                       para, styleRuns,
+ *                                       new Bounds(styleRunStart, styleRunLimit));
+ *                  try {
+ *                      line = para.setLine(start, limit);
+ *                  } catch (Exception e) {
+ *                      e.printStackTrace();
+ *                      return;
+ *                  }
+ *                  // prepare rendering a new line
+ *                  // from either left or right
+ *                  startLine(paraLevel, width);
+ *
+ *                  if (styleRunStart > 0) {
+ *                      int newRunCount = styleRuns.length - styleRunStart;
+ *                      StyleRun[] newRuns = new StyleRun[newRunCount];
+ *                      System.arraycopy(styleRuns, styleRunStart, newRuns, 0,
+ *                                       newRunCount);
+ *                      renderLine(line, text, start, limit, newRuns,
+ *                                 styleRunLimit - styleRunStart);
+ *                  } else {
+ *                      renderLine(line, text, start, limit, styleRuns,
+ *                                 styleRunLimit - styleRunStart);
+ *                  }
+ *                  if (limit == length) {
+ *                      break;
+ *                  }
+ *                  start = limit;
+ *                  styleRunStart = styleRunLimit - 1;
+ *                  if (start >= styleRuns[styleRunStart].limit) {
+ *                      ++styleRunStart;
+ *                  }
+ *              }
+ *          }
+ *      }
+ *
+ *      public static void main(String[] args)
+ *      {
+ *          renderParagraph("Some Latin text...", Bidi.LTR, null, 0, 80);
+ *          renderParagraph("Some Hebrew text...", Bidi.RTL, null, 0, 60);
+ *      }
+ *  }
+ *
+ * </pre>
+ */
+
+public class Bidi {
+
+    private java.text.Bidi bidi;
+
+    private Bidi(java.text.Bidi delegate) {
+        this.bidi = delegate;
+    }
+
+    /** Paragraph level setting<p>
+     *
+     * Constant indicating that the base direction depends on the first strong
+     * directional character in the text according to the Unicode Bidirectional
+     * Algorithm. If no strong directional character is present,
+     * then set the paragraph level to 0 (left-to-right).<p>
+     *
+     * If this value is used in conjunction with reordering modes
+     * <code>REORDER_INVERSE_LIKE_DIRECT</code> or
+     * <code>REORDER_INVERSE_FOR_NUMBERS_SPECIAL</code>, the text to reorder
+     * is assumed to be visual LTR, and the text after reordering is required
+     * to be the corresponding logical string with appropriate contextual
+     * direction. The direction of the result string will be RTL if either
+     * the righmost or leftmost strong character of the source text is RTL
+     * or Arabic Letter, the direction will be LTR otherwise.<p>
+     *
+     * If reordering option <code>OPTION_INSERT_MARKS</code> is set, an RLM may
+     * be added at the beginning of the result string to ensure round trip
+     * (that the result string, when reordered back to visual, will produce
+     * the original source text).
+     * @see #REORDER_INVERSE_LIKE_DIRECT
+     * @see #REORDER_INVERSE_FOR_NUMBERS_SPECIAL
+     * @stable ICU 3.8
+     */
+    public static final byte LEVEL_DEFAULT_LTR = (byte)0x7e;
+
+    /** Paragraph level setting<p>
+     *
+     * Constant indicating that the base direction depends on the first strong
+     * directional character in the text according to the Unicode Bidirectional
+     * Algorithm. If no strong directional character is present,
+     * then set the paragraph level to 1 (right-to-left).<p>
+     *
+     * If this value is used in conjunction with reordering modes
+     * <code>REORDER_INVERSE_LIKE_DIRECT</code> or
+     * <code>REORDER_INVERSE_FOR_NUMBERS_SPECIAL</code>, the text to reorder
+     * is assumed to be visual LTR, and the text after reordering is required
+     * to be the corresponding logical string with appropriate contextual
+     * direction. The direction of the result string will be RTL if either
+     * the righmost or leftmost strong character of the source text is RTL
+     * or Arabic Letter, or if the text contains no strong character;
+     * the direction will be LTR otherwise.<p>
+     *
+     * If reordering option <code>OPTION_INSERT_MARKS</code> is set, an RLM may
+     * be added at the beginning of the result string to ensure round trip
+     * (that the result string, when reordered back to visual, will produce
+     * the original source text).
+     * @see #REORDER_INVERSE_LIKE_DIRECT
+     * @see #REORDER_INVERSE_FOR_NUMBERS_SPECIAL
+     * @stable ICU 3.8
+     */
+    public static final byte LEVEL_DEFAULT_RTL = (byte)0x7f;
+
+    /**
+     * Maximum explicit embedding level.
+     * (The maximum resolved level can be up to <code>MAX_EXPLICIT_LEVEL+1</code>).
+     * @stable ICU 3.8
+     */
+    public static final byte MAX_EXPLICIT_LEVEL = 61;
+
+    /**
+     * Bit flag for level input.
+     * Overrides directional properties.
+     * @stable ICU 3.8
+     */
+    public static final byte LEVEL_OVERRIDE = (byte)0x80;
+
+    /**
+     * Special value which can be returned by the mapping methods when a
+     * logical index has no corresponding visual index or vice-versa. This may
+     * happen for the logical-to-visual mapping of a Bidi control when option
+     * <code>OPTION_REMOVE_CONTROLS</code> is
+     * specified. This can also happen for the visual-to-logical mapping of a
+     * Bidi mark (LRM or RLM) inserted by option
+     * <code>OPTION_INSERT_MARKS</code>.
+     * @see #getVisualIndex
+     * @see #getVisualMap
+     * @see #getLogicalIndex
+     * @see #getLogicalMap
+     * @see #OPTION_INSERT_MARKS
+     * @see #OPTION_REMOVE_CONTROLS
+     * @stable ICU 3.8
+     */
+    public static final int MAP_NOWHERE = -1;
+
+    /**
+     * All left-to-right text.
+     * @stable ICU 3.8
+     */
+    public static final byte LTR = 0;
+
+    /**
+     * All right-to-left text.
+     * @stable ICU 3.8
+     */
+    public static final byte RTL = 1;
+
+    /**
+     * Mixed-directional text.
+     * @stable ICU 3.8
+     */
+    public static final byte MIXED = 2;
+
+    /**
+     * option bit for writeReordered():
+     * keep combining characters after their base characters in RTL runs
+     *
+     * @see #writeReordered
+     * @stable ICU 3.8
+     */
+    public static final short KEEP_BASE_COMBINING = 1;
+
+    /**
+     * option bit for writeReordered():
+     * replace characters with the "mirrored" property in RTL runs
+     * by their mirror-image mappings
+     *
+     * @see #writeReordered
+     * @stable ICU 3.8
+     */
+    public static final short DO_MIRRORING = 2;
+
+    /**
+     * option bit for writeReordered():
+     * surround the run with LRMs if necessary;
+     * this is part of the approximate "inverse Bidi" algorithm
+     *
+     * <p>This option does not imply corresponding adjustment of the index
+     * mappings.</p>
+     *
+     * @see #setInverse
+     * @see #writeReordered
+     * @stable ICU 3.8
+     */
+    public static final short INSERT_LRM_FOR_NUMERIC = 4;
+
+    /**
+     * option bit for writeReordered():
+     * remove Bidi control characters
+     * (this does not affect INSERT_LRM_FOR_NUMERIC)
+     *
+     * <p>This option does not imply corresponding adjustment of the index
+     * mappings.</p>
+     *
+     * @see #writeReordered
+     * @see #INSERT_LRM_FOR_NUMERIC
+     * @stable ICU 3.8
+     */
+    public static final short REMOVE_BIDI_CONTROLS = 8;
+
+    /**
+     * option bit for writeReordered():
+     * write the output in reverse order
+     *
+     * <p>This has the same effect as calling <code>writeReordered()</code>
+     * first without this option, and then calling
+     * <code>writeReverse()</code> without mirroring.
+     * Doing this in the same step is faster and avoids a temporary buffer.
+     * An example for using this option is output to a character terminal that
+     * is designed for RTL scripts and stores text in reverse order.</p>
+     *
+     * @see #writeReordered
+     * @stable ICU 3.8
+     */
+    public static final short OUTPUT_REVERSE = 16;
+
+    /** Reordering mode: Regular Logical to Visual Bidi algorithm according to Unicode.
+     * @see #setReorderingMode
+     * @stable ICU 3.8
+     */
+    public static final short REORDER_DEFAULT = 0;
+
+    /** Reordering mode: Logical to Visual algorithm which handles numbers in
+     * a way which mimicks the behavior of Windows XP.
+     * @see #setReorderingMode
+     * @stable ICU 3.8
+     */
+    public static final short REORDER_NUMBERS_SPECIAL = 1;
+
+    /** Reordering mode: Logical to Visual algorithm grouping numbers with
+     * adjacent R characters (reversible algorithm).
+     * @see #setReorderingMode
+     * @stable ICU 3.8
+     */
+    public static final short REORDER_GROUP_NUMBERS_WITH_R = 2;
+
+    /** Reordering mode: Reorder runs only to transform a Logical LTR string
+     * to the logical RTL string with the same display, or vice-versa.<br>
+     * If this mode is set together with option
+     * <code>OPTION_INSERT_MARKS</code>, some Bidi controls in the source
+     * text may be removed and other controls may be added to produce the
+     * minimum combination which has the required display.
+     * @see #OPTION_INSERT_MARKS
+     * @see #setReorderingMode
+     * @stable ICU 3.8
+     */
+    public static final short REORDER_RUNS_ONLY = 3;
+
+    /** Reordering mode: Visual to Logical algorithm which handles numbers
+     * like L (same algorithm as selected by <code>setInverse(true)</code>.
+     * @see #setInverse
+     * @see #setReorderingMode
+     * @stable ICU 3.8
+     */
+    public static final short REORDER_INVERSE_NUMBERS_AS_L = 4;
+
+    /** Reordering mode: Visual to Logical algorithm equivalent to the regular
+     * Logical to Visual algorithm.
+     * @see #setReorderingMode
+     * @stable ICU 3.8
+     */
+    public static final short REORDER_INVERSE_LIKE_DIRECT = 5;
+
+    /** Reordering mode: Inverse Bidi (Visual to Logical) algorithm for the
+     * <code>REORDER_NUMBERS_SPECIAL</code> Bidi algorithm.
+     * @see #setReorderingMode
+     * @stable ICU 3.8
+     */
+    public static final short REORDER_INVERSE_FOR_NUMBERS_SPECIAL = 6;
+
+    /**
+     * Option value for <code>setReorderingOptions</code>:
+     * disable all the options which can be set with this method
+     * @see #setReorderingOptions
+     * @stable ICU 3.8
+     */
+    public static final int OPTION_DEFAULT = 0;
+
+    /**
+     * Option bit for <code>setReorderingOptions</code>:
+     * insert Bidi marks (LRM or RLM) when needed to ensure correct result of
+     * a reordering to a Logical order
+     *
+     * <p>This option must be set or reset before calling
+     * <code>setPara</code>.</p>
+     *
+     * <p>This option is significant only with reordering modes which generate
+     * a result with Logical order, specifically.</p>
+     * <ul>
+     *   <li><code>REORDER_RUNS_ONLY</code></li>
+     *   <li><code>REORDER_INVERSE_NUMBERS_AS_L</code></li>
+     *   <li><code>REORDER_INVERSE_LIKE_DIRECT</code></li>
+     *   <li><code>REORDER_INVERSE_FOR_NUMBERS_SPECIAL</code></li>
+     * </ul>
+     *
+     * <p>If this option is set in conjunction with reordering mode
+     * <code>REORDER_INVERSE_NUMBERS_AS_L</code> or with calling
+     * <code>setInverse(true)</code>, it implies option
+     * <code>INSERT_LRM_FOR_NUMERIC</code> in calls to method
+     * <code>writeReordered()</code>.</p>
+     *
+     * <p>For other reordering modes, a minimum number of LRM or RLM characters
+     * will be added to the source text after reordering it so as to ensure
+     * round trip, i.e. when applying the inverse reordering mode on the
+     * resulting logical text with removal of Bidi marks
+     * (option <code>OPTION_REMOVE_CONTROLS</code> set before calling
+     * <code>setPara()</code> or option
+     * <code>REMOVE_BIDI_CONTROLS</code> in
+     * <code>writeReordered</code>), the result will be identical to the
+     * source text in the first transformation.
+     *
+     * <p>This option will be ignored if specified together with option
+     * <code>OPTION_REMOVE_CONTROLS</code>. It inhibits option
+     * <code>REMOVE_BIDI_CONTROLS</code> in calls to method
+     * <code>writeReordered()</code> and it implies option
+     * <code>INSERT_LRM_FOR_NUMERIC</code> in calls to method
+     * <code>writeReordered()</code> if the reordering mode is
+     * <code>REORDER_INVERSE_NUMBERS_AS_L</code>.</p>
+     *
+     * @see #setReorderingMode
+     * @see #setReorderingOptions
+     * @see #INSERT_LRM_FOR_NUMERIC
+     * @see #REMOVE_BIDI_CONTROLS
+     * @see #OPTION_REMOVE_CONTROLS
+     * @see #REORDER_RUNS_ONLY
+     * @see #REORDER_INVERSE_NUMBERS_AS_L
+     * @see #REORDER_INVERSE_LIKE_DIRECT
+     * @see #REORDER_INVERSE_FOR_NUMBERS_SPECIAL
+     * @stable ICU 3.8
+     */
+    public static final int OPTION_INSERT_MARKS = 1;
+
+    /**
+     * Option bit for <code>setReorderingOptions</code>:
+     * remove Bidi control characters
+     *
+     * <p>This option must be set or reset before calling
+     * <code>setPara</code>.</p>
+     *
+     * <p>This option nullifies option
+     * <code>OPTION_INSERT_MARKS</code>. It inhibits option
+     * <code>INSERT_LRM_FOR_NUMERIC</code> in calls to method
+     * <code>writeReordered()</code> and it implies option
+     * <code>REMOVE_BIDI_CONTROLS</code> in calls to that method.</p>
+     *
+     * @see #setReorderingMode
+     * @see #setReorderingOptions
+     * @see #OPTION_INSERT_MARKS
+     * @see #INSERT_LRM_FOR_NUMERIC
+     * @see #REMOVE_BIDI_CONTROLS
+     * @stable ICU 3.8
+     */
+    public static final int OPTION_REMOVE_CONTROLS = 2;
+
+    /**
+     * Option bit for <code>setReorderingOptions</code>:
+     * process the output as part of a stream to be continued
+     *
+     * <p>This option must be set or reset before calling
+     * <code>setPara</code>.</p>
+     *
+     * <p>This option specifies that the caller is interested in processing
+     * large text object in parts. The results of the successive calls are
+     * expected to be concatenated by the caller. Only the call for the last
+     * part will have this option bit off.</p>
+     *
+     * <p>When this option bit is on, <code>setPara()</code> may process
+     * less than the full source text in order to truncate the text at a
+     * meaningful boundary. The caller should call
+     * <code>getProcessedLength()</code> immediately after calling
+     * <code>setPara()</code> in order to determine how much of the source
+     * text has been processed. Source text beyond that length should be
+     * resubmitted in following calls to <code>setPara</code>. The
+     * processed length may be less than the length of the source text if a
+     * character preceding the last character of the source text constitutes a
+     * reasonable boundary (like a block separator) for text to be continued.<br>
+     * If the last character of the source text constitutes a reasonable
+     * boundary, the whole text will be processed at once.<br>
+     * If nowhere in the source text there exists
+     * such a reasonable boundary, the processed length will be zero.<br>
+     * The caller should check for such an occurrence and do one of the following:
+     * <ul><li>submit a larger amount of text with a better chance to include
+     *         a reasonable boundary.</li>
+     *     <li>resubmit the same text after turning off option
+     *         <code>OPTION_STREAMING</code>.</li></ul>
+     * In all cases, this option should be turned off before processing the last
+     * part of the text.</p>
+     *
+     * <p>When the <code>OPTION_STREAMING</code> option is used, it is
+     * recommended to call <code>orderParagraphsLTR(true)</code> before calling
+     * <code>setPara()</code> so that later paragraphs may be concatenated to
+     * previous paragraphs on the right.
+     * </p>
+     *
+     * @see #setReorderingMode
+     * @see #setReorderingOptions
+     * @see #getProcessedLength
+     * @stable ICU 3.8
+     */
+    public static final int OPTION_STREAMING = 4;
+
+    /**
+     * Value returned by <code>BidiClassifier</code> when there is no need to
+     * override the standard Bidi class for a given code point.
+     * @see BidiClassifier
+     * @stable ICU 3.8
+     */
+    public static final int CLASS_DEFAULT = 19; //UCharacterDirection.CHAR_DIRECTION_COUNT;
+
+    /**
+     * Allocate a <code>Bidi</code> object.
+     * Such an object is initially empty. It is assigned
+     * the Bidi properties of a piece of text containing one or more paragraphs
+     * by <code>setPara()</code>
+     * or the Bidi properties of a line within a paragraph by
+     * <code>setLine()</code>.<p>
+     * This object can be reused.<p>
+     * <code>setPara()</code> and <code>setLine()</code> will allocate
+     * additional memory for internal structures as necessary.
+     *
+     * @stable ICU 3.8
+     */
+    public Bidi()
+    {
+        throw new UnsupportedOperationException("Constructor not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Allocate a <code>Bidi</code> object with preallocated memory
+     * for internal structures.
+     * This method provides a <code>Bidi</code> object like the default constructor
+     * but it also preallocates memory for internal structures
+     * according to the sizings supplied by the caller.<p>
+     * The preallocation can be limited to some of the internal memory
+     * by setting some values to 0 here. That means that if, e.g.,
+     * <code>maxRunCount</code> cannot be reasonably predetermined and should not
+     * be set to <code>maxLength</code> (the only failproof value) to avoid
+     * wasting  memory, then <code>maxRunCount</code> could be set to 0 here
+     * and the internal structures that are associated with it will be allocated
+     * on demand, just like with the default constructor.
+     *
+     * @param maxLength is the maximum text or line length that internal memory
+     *        will be preallocated for. An attempt to associate this object with a
+     *        longer text will fail, unless this value is 0, which leaves the allocation
+     *        up to the implementation.
+     *
+     * @param maxRunCount is the maximum anticipated number of same-level runs
+     *        that internal memory will be preallocated for. An attempt to access
+     *        visual runs on an object that was not preallocated for as many runs
+     *        as the text was actually resolved to will fail,
+     *        unless this value is 0, which leaves the allocation up to the implementation.<br><br>
+     *        The number of runs depends on the actual text and maybe anywhere between
+     *        1 and <code>maxLength</code>. It is typically small.
+     *
+     * @throws IllegalArgumentException if maxLength or maxRunCount is less than 0
+     * @stable ICU 3.8
+     */
+    public Bidi(int maxLength, int maxRunCount)
+    {
+        throw new UnsupportedOperationException("Constructor not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Modify the operation of the Bidi algorithm such that it
+     * approximates an "inverse Bidi" algorithm. This method
+     * must be called before <code>setPara()</code>.
+     *
+     * <p>The normal operation of the Bidi algorithm as described
+     * in the Unicode Technical Report is to take text stored in logical
+     * (keyboard, typing) order and to determine the reordering of it for visual
+     * rendering.
+     * Some legacy systems store text in visual order, and for operations
+     * with standard, Unicode-based algorithms, the text needs to be transformed
+     * to logical order. This is effectively the inverse algorithm of the
+     * described Bidi algorithm. Note that there is no standard algorithm for
+     * this "inverse Bidi" and that the current implementation provides only an
+     * approximation of "inverse Bidi".</p>
+     *
+     * <p>With <code>isInversed</code> set to <code>true</code>,
+     * this method changes the behavior of some of the subsequent methods
+     * in a way that they can be used for the inverse Bidi algorithm.
+     * Specifically, runs of text with numeric characters will be treated in a
+     * special way and may need to be surrounded with LRM characters when they are
+     * written in reordered sequence.</p>
+     *
+     * <p>Output runs should be retrieved using <code>getVisualRun()</code>.
+     * Since the actual input for "inverse Bidi" is visually ordered text and
+     * <code>getVisualRun()</code> gets the reordered runs, these are actually
+     * the runs of the logically ordered output.</p>
+     *
+     * <p>Calling this method with argument <code>isInverse</code> set to
+     * <code>true</code> is equivalent to calling <code>setReorderingMode</code>
+     * with argument <code>reorderingMode</code>
+     * set to <code>REORDER_INVERSE_NUMBERS_AS_L</code>.<br>
+     * Calling this method with argument <code>isInverse</code> set to
+     * <code>false</code> is equivalent to calling <code>setReorderingMode</code>
+     * with argument <code>reorderingMode</code>
+     * set to <code>REORDER_DEFAULT</code>.
+     *
+     * @param isInverse specifies "forward" or "inverse" Bidi operation.
+     *
+     * @see #setPara
+     * @see #writeReordered
+     * @see #setReorderingMode
+     * @see #REORDER_INVERSE_NUMBERS_AS_L
+     * @see #REORDER_DEFAULT
+     * @stable ICU 3.8
+     */
+    public void setInverse(boolean isInverse) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Is this <code>Bidi</code> object set to perform the inverse Bidi
+     * algorithm?
+     * <p>Note: calling this method after setting the reordering mode with
+     * <code>setReorderingMode</code> will return <code>true</code> if the
+     * reordering mode was set to
+     * <code>REORDER_INVERSE_NUMBERS_AS_L<code>, <code>false</code>
+     * for all other values.</p>
+     *
+     * @return <code>true</code> if the <code>Bidi</code> object is set to
+     * perform the inverse Bidi algorithm by handling numbers as L.
+     *
+     * @see #setInverse
+     * @see #setReorderingMode
+     * @see #REORDER_INVERSE_NUMBERS_AS_L
+     * @stable ICU 3.8
+     */
+    public boolean isInverse() {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Modify the operation of the Bidi algorithm such that it implements some
+     * variant to the basic Bidi algorithm or approximates an "inverse Bidi"
+     * algorithm, depending on different values of the "reordering mode".
+     * This method must be called before <code>setPara()</code>, and stays in
+     * effect until called again with a different argument.
+     *
+     * <p>The normal operation of the Bidi algorithm as described in the Unicode
+     * Standard Annex #9 is to take text stored in logical (keyboard, typing)
+     * order and to determine how to reorder it for visual rendering.</p>
+     *
+     * <p>With the reordering mode set to a value other than
+     * <code>REORDER_DEFAULT</code>, this method changes the behavior of some of
+     * the subsequent methods in a way such that they implement an inverse Bidi
+     * algorithm or some other algorithm variants.</p>
+     *
+     * <p>Some legacy systems store text in visual order, and for operations
+     * with standard, Unicode-based algorithms, the text needs to be transformed
+     * into logical order. This is effectively the inverse algorithm of the
+     * described Bidi algorithm. Note that there is no standard algorithm for
+     * this "inverse Bidi", so a number of variants are implemented here.</p>
+     *
+     * <p>In other cases, it may be desirable to emulate some variant of the
+     * Logical to Visual algorithm (e.g. one used in MS Windows), or perform a
+     * Logical to Logical transformation.</p>
+     *
+     * <ul>
+     * <li>When the Reordering Mode is set to
+     * <code>REORDER_DEFAULT</code>,
+     * the standard Bidi Logical to Visual algorithm is applied.</li>
+     *
+     * <li>When the reordering mode is set to
+     * <code>REORDER_NUMBERS_SPECIAL</code>,
+     * the algorithm used to perform Bidi transformations when calling
+     * <code>setPara</code> should approximate the algorithm used in Microsoft
+     * Windows XP rather than strictly conform to the Unicode Bidi algorithm.
+     * <br>
+     * The differences between the basic algorithm and the algorithm addressed
+     * by this option are as follows:
+     * <ul>
+     *   <li>Within text at an even embedding level, the sequence "123AB"
+     *   (where AB represent R or AL letters) is transformed to "123BA" by the
+     *   Unicode algorithm and to "BA123" by the Windows algorithm.</li>
+     *
+     *   <li>Arabic-Indic numbers (AN) are handled by the Windows algorithm just
+     *   like regular numbers (EN).</li>
+     * </ul></li>
+     *
+     * <li>When the reordering mode is set to
+     * <code>REORDER_GROUP_NUMBERS_WITH_R</code>,
+     * numbers located between LTR text and RTL text are associated with the RTL
+     * text. For instance, an LTR paragraph with content "abc 123 DEF" (where
+     * upper case letters represent RTL characters) will be transformed to
+     * "abc FED 123" (and not "abc 123 FED"), "DEF 123 abc" will be transformed
+     * to "123 FED abc" and "123 FED abc" will be transformed to "DEF 123 abc".
+     * This makes the algorithm reversible and makes it useful when round trip
+     * (from visual to logical and back to visual) must be achieved without
+     * adding LRM characters. However, this is a variation from the standard
+     * Unicode Bidi algorithm.<br>
+     * The source text should not contain Bidi control characters other than LRM
+     * or RLM.</li>
+     *
+     * <li>When the reordering mode is set to
+     * <code>REORDER_RUNS_ONLY</code>,
+     * a "Logical to Logical" transformation must be performed:
+     * <ul>
+     * <li>If the default text level of the source text (argument
+     * <code>paraLevel</code> in <code>setPara</code>) is even, the source text
+     * will be handled as LTR logical text and will be transformed to the RTL
+     * logical text which has the same LTR visual display.</li>
+     * <li>If the default level of the source text is odd, the source text
+     * will be handled as RTL logical text and will be transformed to the
+     * LTR logical text which has the same LTR visual display.</li>
+     * </ul>
+     * This mode may be needed when logical text which is basically Arabic or
+     * Hebrew, with possible included numbers or phrases in English, has to be
+     * displayed as if it had an even embedding level (this can happen if the
+     * displaying application treats all text as if it was basically LTR).
+     * <br>
+     * This mode may also be needed in the reverse case, when logical text which
+     * is basically English, with possible included phrases in Arabic or Hebrew,
+     * has to be displayed as if it had an odd embedding level.
+     * <br>
+     * Both cases could be handled by adding LRE or RLE at the head of the
+     * text, if the display subsystem supports these formatting controls. If it
+     * does not, the problem may be handled by transforming the source text in
+     * this mode before displaying it, so that it will be displayed properly.
+     * <br>
+     * The source text should not contain Bidi control characters other than LRM
+     * or RLM.</li>
+     *
+     * <li>When the reordering mode is set to
+     * <code>REORDER_INVERSE_NUMBERS_AS_L</code>, an "inverse Bidi"
+     * algorithm is applied.
+     * Runs of text with numeric characters will be treated like LTR letters and
+     * may need to be surrounded with LRM characters when they are written in
+     * reordered sequence (the option <code>INSERT_LRM_FOR_NUMERIC</code> can
+     * be used with method <code>writeReordered</code> to this end. This mode
+     * is equivalent to calling <code>setInverse()</code> with
+     * argument <code>isInverse</code> set to <code>true</code>.</li>
+     *
+     * <li>When the reordering mode is set to
+     * <code>REORDER_INVERSE_LIKE_DIRECT</code>, the "direct" Logical to
+     * Visual Bidi algorithm is used as an approximation of an "inverse Bidi"
+     * algorithm. This mode is similar to mode
+     * <code>REORDER_INVERSE_NUMBERS_AS_L</code> but is closer to the
+     * regular Bidi algorithm.
+     * <br>
+     * For example, an LTR paragraph with the content "FED 123 456 CBA" (where
+     * upper case represents RTL characters) will be transformed to
+     * "ABC 456 123 DEF", as opposed to "DEF 123 456 ABC"
+     * with mode <code>REORDER_INVERSE_NUMBERS_AS_L</code>.<br>
+     * When used in conjunction with option
+     * <code>OPTION_INSERT_MARKS</code>, this mode generally
+     * adds Bidi marks to the output significantly more sparingly than mode
+     * <code>REORDER_INVERSE_NUMBERS_AS_L</code>.<br> with option
+     * <code>INSERT_LRM_FOR_NUMERIC</code> in calls to
+     * <code>writeReordered</code>.</li>
+     *
+     * <li>When the reordering mode is set to
+     * <code>REORDER_INVERSE_FOR_NUMBERS_SPECIAL</code>, the Logical to Visual
+     * Bidi algorithm used in Windows XP is used as an approximation of an "inverse
+     * Bidi" algorithm.
+     * <br>
+     * For example, an LTR paragraph with the content "abc FED123" (where
+     * upper case represents RTL characters) will be transformed to
+     * "abc 123DEF.</li>
+     * </ul>
+     *
+     * <p>In all the reordering modes specifying an "inverse Bidi" algorithm
+     * (i.e. those with a name starting with <code>REORDER_INVERSE</code>),
+     * output runs should be retrieved using <code>getVisualRun()</code>, and
+     * the output text with <code>writeReordered()</code>. The caller should
+     * keep in mind that in "inverse Bidi" modes the input is actually visually
+     * ordered text and reordered output returned by <code>getVisualRun()</code>
+     * or <code>writeReordered()</code> are actually runs or character string
+     * of logically ordered output.<br>
+     * For all the "inverse Bidi" modes, the source text should not contain
+     * Bidi control characters other than LRM or RLM.</p>
+     *
+     * <p>Note that option <code>OUTPUT_REVERSE</code> of
+     * <code>writeReordered</code> has no useful meaning and should not be used
+     * in conjunction with any value of the reordering mode specifying "inverse
+     * Bidi" or with value <code>REORDER_RUNS_ONLY</code>.
+     *
+     * @param reorderingMode specifies the required variant of the Bidi
+     *                       algorithm.
+     *
+     * @see #setInverse
+     * @see #setPara
+     * @see #writeReordered
+     * @see #INSERT_LRM_FOR_NUMERIC
+     * @see #OUTPUT_REVERSE
+     * @see #REORDER_DEFAULT
+     * @see #REORDER_NUMBERS_SPECIAL
+     * @see #REORDER_GROUP_NUMBERS_WITH_R
+     * @see #REORDER_RUNS_ONLY
+     * @see #REORDER_INVERSE_NUMBERS_AS_L
+     * @see #REORDER_INVERSE_LIKE_DIRECT
+     * @see #REORDER_INVERSE_FOR_NUMBERS_SPECIAL
+     * @stable ICU 3.8
+     */
+    public void setReorderingMode(int reorderingMode) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * What is the requested reordering mode for a given Bidi object?
+     *
+     * @return the current reordering mode of the Bidi object
+     *
+     * @see #setReorderingMode
+     * @stable ICU 3.8
+     */
+    public int getReorderingMode() {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Specify which of the reordering options should be applied during Bidi
+     * transformations.
+     *
+     * @param options A combination of zero or more of the following
+     * reordering options:
+     * <code>OPTION_DEFAULT</code>, <code>OPTION_INSERT_MARKS</code>,
+     * <code>OPTION_REMOVE_CONTROLS</code>, <code>OPTION_STREAMING</code>.
+     *
+     * @see #getReorderingOptions
+     * @see #OPTION_DEFAULT
+     * @see #OPTION_INSERT_MARKS
+     * @see #OPTION_REMOVE_CONTROLS
+     * @see #OPTION_STREAMING
+     * @stable ICU 3.8
+     */
+    public void setReorderingOptions(int options) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * What are the reordering options applied to a given Bidi object?
+     *
+     * @return the current reordering options of the Bidi object
+     *
+     * @see #setReorderingOptions
+     * @stable ICU 3.8
+     */
+    public int getReorderingOptions() {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Perform the Unicode Bidi algorithm. It is defined in the
+     * <a href="http://www.unicode.org/unicode/reports/tr9/">Unicode Standard Annex #9</a>,
+     * version 13,
+     * also described in The Unicode Standard, Version 4.0 .<p>
+     *
+     * This method takes a piece of plain text containing one or more paragraphs,
+     * with or without externally specified embedding levels from <i>styled</i>
+     * text and computes the left-right-directionality of each character.<p>
+     *
+     * If the entire text is all of the same directionality, then
+     * the method may not perform all the steps described by the algorithm,
+     * i.e., some levels may not be the same as if all steps were performed.
+     * This is not relevant for unidirectional text.<br>
+     * For example, in pure LTR text with numbers the numbers would get
+     * a resolved level of 2 higher than the surrounding text according to
+     * the algorithm. This implementation may set all resolved levels to
+     * the same value in such a case.<p>
+     *
+     * The text can be composed of multiple paragraphs. Occurrence of a block
+     * separator in the text terminates a paragraph, and whatever comes next starts
+     * a new paragraph. The exception to this rule is when a Carriage Return (CR)
+     * is followed by a Line Feed (LF). Both CR and LF are block separators, but
+     * in that case, the pair of characters is considered as terminating the
+     * preceding paragraph, and a new paragraph will be started by a character
+     * coming after the LF.
+     *
+     * Although the text is passed here as a <code>String</code>, it is
+     * stored internally as an array of characters. Therefore the
+     * documentation will refer to indexes of the characters in the text.
+     *
+     * @param text contains the text that the Bidi algorithm will be performed
+     *        on. This text can be retrieved with <code>getText()</code> or
+     *        <code>getTextAsString</code>.<br>
+     *
+     * @param paraLevel specifies the default level for the text;
+     *        it is typically 0 (LTR) or 1 (RTL).
+     *        If the method shall determine the paragraph level from the text,
+     *        then <code>paraLevel</code> can be set to
+     *        either <code>LEVEL_DEFAULT_LTR</code>
+     *        or <code>LEVEL_DEFAULT_RTL</code>; if the text contains multiple
+     *        paragraphs, the paragraph level shall be determined separately for
+     *        each paragraph; if a paragraph does not include any strongly typed
+     *        character, then the desired default is used (0 for LTR or 1 for RTL).
+     *        Any other value between 0 and <code>MAX_EXPLICIT_LEVEL</code>
+     *        is also valid, with odd levels indicating RTL.
+     *
+     * @param embeddingLevels (in) may be used to preset the embedding and override levels,
+     *        ignoring characters like LRE and PDF in the text.
+     *        A level overrides the directional property of its corresponding
+     *        (same index) character if the level has the
+     *        <code>LEVEL_OVERRIDE</code> bit set.<br><br>
+     *        Except for that bit, it must be
+     *        <code>paraLevel<=embeddingLevels[]<=MAX_EXPLICIT_LEVEL</code>,
+     *        with one exception: a level of zero may be specified for a
+     *        paragraph separator even if <code>paraLevel&gt;0</code> when multiple
+     *        paragraphs are submitted in the same call to <code>setPara()</code>.<br><br>
+     *        <strong>Caution: </strong>A reference to this array, not a copy
+     *        of the levels, will be stored in the <code>Bidi</code> object;
+     *        the <code>embeddingLevels</code>
+     *        should not be modified to avoid unexpected results on subsequent
+     *        Bidi operations. However, the <code>setPara()</code> and
+     *        <code>setLine()</code> methods may modify some or all of the
+     *        levels.<br><br>
+     *        <strong>Note:</strong> the <code>embeddingLevels</code> array must
+     *        have one entry for each character in <code>text</code>.
+     *
+     * @throws IllegalArgumentException if the values in embeddingLevels are
+     *         not within the allowed range
+     *
+     * @see #LEVEL_DEFAULT_LTR
+     * @see #LEVEL_DEFAULT_RTL
+     * @see #LEVEL_OVERRIDE
+     * @see #MAX_EXPLICIT_LEVEL
+     * @stable ICU 3.8
+     */
+    public void setPara(String text, byte paraLevel, byte[] embeddingLevels)
+    {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Perform the Unicode Bidi algorithm. It is defined in the
+     * <a href="http://www.unicode.org/unicode/reports/tr9/">Unicode Standard Annex #9</a>,
+     * version 13,
+     * also described in The Unicode Standard, Version 4.0 .<p>
+     *
+     * This method takes a piece of plain text containing one or more paragraphs,
+     * with or without externally specified embedding levels from <i>styled</i>
+     * text and computes the left-right-directionality of each character.<p>
+     *
+     * If the entire text is all of the same directionality, then
+     * the method may not perform all the steps described by the algorithm,
+     * i.e., some levels may not be the same as if all steps were performed.
+     * This is not relevant for unidirectional text.<br>
+     * For example, in pure LTR text with numbers the numbers would get
+     * a resolved level of 2 higher than the surrounding text according to
+     * the algorithm. This implementation may set all resolved levels to
+     * the same value in such a case.<p>
+     *
+     * The text can be composed of multiple paragraphs. Occurrence of a block
+     * separator in the text terminates a paragraph, and whatever comes next starts
+     * a new paragraph. The exception to this rule is when a Carriage Return (CR)
+     * is followed by a Line Feed (LF). Both CR and LF are block separators, but
+     * in that case, the pair of characters is considered as terminating the
+     * preceding paragraph, and a new paragraph will be started by a character
+     * coming after the LF.
+     *
+     * The text is stored internally as an array of characters. Therefore the
+     * documentation will refer to indexes of the characters in the text.
+     *
+     * @param chars contains the text that the Bidi algorithm will be performed
+     *        on. This text can be retrieved with <code>getText()</code> or
+     *        <code>getTextAsString</code>.<br>
+     *
+     * @param paraLevel specifies the default level for the text;
+     *        it is typically 0 (LTR) or 1 (RTL).
+     *        If the method shall determine the paragraph level from the text,
+     *        then <code>paraLevel</code> can be set to
+     *        either <code>LEVEL_DEFAULT_LTR</code>
+     *        or <code>LEVEL_DEFAULT_RTL</code>; if the text contains multiple
+     *        paragraphs, the paragraph level shall be determined separately for
+     *        each paragraph; if a paragraph does not include any strongly typed
+     *        character, then the desired default is used (0 for LTR or 1 for RTL).
+     *        Any other value between 0 and <code>MAX_EXPLICIT_LEVEL</code>
+     *        is also valid, with odd levels indicating RTL.
+     *
+     * @param embeddingLevels (in) may be used to preset the embedding and
+     *        override levels, ignoring characters like LRE and PDF in the text.
+     *        A level overrides the directional property of its corresponding
+     *        (same index) character if the level has the
+     *        <code>LEVEL_OVERRIDE</code> bit set.<br><br>
+     *        Except for that bit, it must be
+     *        <code>paraLevel<=embeddingLevels[]<=MAX_EXPLICIT_LEVEL</code>,
+     *        with one exception: a level of zero may be specified for a
+     *        paragraph separator even if <code>paraLevel&gt;0</code> when multiple
+     *        paragraphs are submitted in the same call to <code>setPara()</code>.<br><br>
+     *        <strong>Caution: </strong>A reference to this array, not a copy
+     *        of the levels, will be stored in the <code>Bidi</code> object;
+     *        the <code>embeddingLevels</code>
+     *        should not be modified to avoid unexpected results on subsequent
+     *        Bidi operations. However, the <code>setPara()</code> and
+     *        <code>setLine()</code> methods may modify some or all of the
+     *        levels.<br><br>
+     *        <strong>Note:</strong> the <code>embeddingLevels</code> array must
+     *        have one entry for each character in <code>text</code>.
+     *
+     * @throws IllegalArgumentException if the values in embeddingLevels are
+     *         not within the allowed range
+     *
+     * @see #LEVEL_DEFAULT_LTR
+     * @see #LEVEL_DEFAULT_RTL
+     * @see #LEVEL_OVERRIDE
+     * @see #MAX_EXPLICIT_LEVEL
+     * @stable ICU 3.8
+     */
+    public void setPara(char[] chars, byte paraLevel, byte[] embeddingLevels)
+    {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Perform the Unicode Bidi algorithm on a given paragraph, as defined in the
+     * <a href="http://www.unicode.org/unicode/reports/tr9/">Unicode Standard Annex #9</a>,
+     * version 13,
+     * also described in The Unicode Standard, Version 4.0 .<p>
+     *
+     * This method takes a paragraph of text and computes the
+     * left-right-directionality of each character. The text should not
+     * contain any Unicode block separators.<p>
+     *
+     * The RUN_DIRECTION attribute in the text, if present, determines the base
+     * direction (left-to-right or right-to-left). If not present, the base
+     * direction is computed using the Unicode Bidirectional Algorithm,
+     * defaulting to left-to-right if there are no strong directional characters
+     * in the text. This attribute, if present, must be applied to all the text
+     * in the paragraph.<p>
+     *
+     * The BIDI_EMBEDDING attribute in the text, if present, represents
+     * embedding level information. Negative values from -1 to -62 indicate
+     * overrides at the absolute value of the level. Positive values from 1 to
+     * 62 indicate embeddings. Where values are zero or not defined, the base
+     * embedding level as determined by the base direction is assumed.<p>
+     *
+     * The NUMERIC_SHAPING attribute in the text, if present, converts European
+     * digits to other decimal digits before running the bidi algorithm. This
+     * attribute, if present, must be applied to all the text in the paragraph.
+     *
+     * If the entire text is all of the same directionality, then
+     * the method may not perform all the steps described by the algorithm,
+     * i.e., some levels may not be the same as if all steps were performed.
+     * This is not relevant for unidirectional text.<br>
+     * For example, in pure LTR text with numbers the numbers would get
+     * a resolved level of 2 higher than the surrounding text according to
+     * the algorithm. This implementation may set all resolved levels to
+     * the same value in such a case.<p>
+     *
+     * @param paragraph a paragraph of text with optional character and
+     *        paragraph attribute information
+     * @stable ICU 3.8
+     */
+    public void setPara(AttributedCharacterIterator paragraph)
+    {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Specify whether block separators must be allocated level zero,
+     * so that successive paragraphs will progress from left to right.
+     * This method must be called before <code>setPara()</code>.
+     * Paragraph separators (B) may appear in the text.  Setting them to level zero
+     * means that all paragraph separators (including one possibly appearing
+     * in the last text position) are kept in the reordered text after the text
+     * that they follow in the source text.
+     * When this feature is not enabled, a paragraph separator at the last
+     * position of the text before reordering will go to the first position
+     * of the reordered text when the paragraph level is odd.
+     *
+     * @param ordarParaLTR specifies whether paragraph separators (B) must
+     * receive level 0, so that successive paragraphs progress from left to right.
+     *
+     * @see #setPara
+     * @stable ICU 3.8
+     */
+    public void orderParagraphsLTR(boolean ordarParaLTR) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Is this <code>Bidi</code> object set to allocate level 0 to block
+     * separators so that successive paragraphs progress from left to right?
+     *
+     * @return <code>true</code> if the <code>Bidi</code> object is set to
+     *         allocate level 0 to block separators.
+     *
+     * @stable ICU 3.8
+     */
+    public boolean isOrderParagraphsLTR() {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Get the directionality of the text.
+     *
+     * @return a value of <code>LTR</code>, <code>RTL</code> or <code>MIXED</code>
+     *         that indicates if the entire text
+     *         represented by this object is unidirectional,
+     *         and which direction, or if it is mixed-directional.
+     *
+     * @throws IllegalStateException if this call is not preceded by a successful
+     *         call to <code>setPara</code> or <code>setLine</code>
+     *
+     * @see #LTR
+     * @see #RTL
+     * @see #MIXED
+     * @stable ICU 3.8
+     */
+    public byte getDirection()
+    {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Get the text.
+     *
+     * @return A <code>String</code> containing the text that the
+     *         <code>Bidi</code> object was created for.
+     *
+     * @throws IllegalStateException if this call is not preceded by a successful
+     *         call to <code>setPara</code> or <code>setLine</code>
+     *
+     * @see #setPara
+     * @see #setLine
+     * @stable ICU 3.8
+     */
+    public String getTextAsString()
+    {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Get the text.
+     *
+     * @return A <code>char</code> array containing the text that the
+     *         <code>Bidi</code> object was created for.
+     *
+     * @throws IllegalStateException if this call is not preceded by a successful
+     *         call to <code>setPara</code> or <code>setLine</code>
+     *
+     * @see #setPara
+     * @see #setLine
+     * @stable ICU 3.8
+     */
+    public char[] getText()
+    {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Get the length of the text.
+     *
+     * @return The length of the text that the <code>Bidi</code> object was
+     *         created for.
+     *
+     * @throws IllegalStateException if this call is not preceded by a successful
+     *         call to <code>setPara</code> or <code>setLine</code>
+     * @stable ICU 3.8
+     */
+    public int getLength()
+    {
+        return bidi.getLength();
+    }
+
+    /**
+     * Get the length of the source text processed by the last call to
+     * <code>setPara()</code>. This length may be different from the length of
+     * the source text if option <code>OPTION_STREAMING</code> has been
+     * set.
+     * <br>
+     * Note that whenever the length of the text affects the execution or the
+     * result of a method, it is the processed length which must be considered,
+     * except for <code>setPara</code> (which receives unprocessed source text)
+     * and <code>getLength</code> (which returns the original length of the
+     * source text).<br>
+     * In particular, the processed length is the one to consider in the
+     * following cases:
+     * <ul>
+     * <li>maximum value of the <code>limit</code> argument of
+     * <code>setLine</code></li>
+     * <li>maximum value of the <code>charIndex</code> argument of
+     * <code>getParagraph</code></li>
+     * <li>maximum value of the <code>charIndex</code> argument of
+     * <code>getLevelAt</code></li>
+     * <li>number of elements in the array returned by <code>getLevels</code>
+     * </li>
+     * <li>maximum value of the <code>logicalStart</code> argument of
+     * <code>getLogicalRun</code></li>
+     * <li>maximum value of the <code>logicalIndex</code> argument of
+     * <code>getVisualIndex</code></li>
+     * <li>number of elements returned by <code>getLogicalMap</code></li>
+     * <li>length of text processed by <code>writeReordered</code></li>
+     * </ul>
+     *
+     * @return The length of the part of the source text processed by
+     *         the last call to <code>setPara</code>.
+     *
+     * @throws IllegalStateException if this call is not preceded by a successful
+     *         call to <code>setPara</code> or <code>setLine</code>
+     *
+     * @see #setPara
+     * @see #OPTION_STREAMING
+     * @stable ICU 3.8
+     */
+    public int getProcessedLength() {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Get the length of the reordered text resulting from the last call to
+     * <code>setPara()</code>. This length may be different from the length
+     * of the source text if option <code>OPTION_INSERT_MARKS</code>
+     * or option <code>OPTION_REMOVE_CONTROLS</code> has been set.
+     * <br>
+     * This resulting length is the one to consider in the following cases:
+     * <ul>
+     * <li>maximum value of the <code>visualIndex</code> argument of
+     * <code>getLogicalIndex</code></li>
+     * <li>number of elements returned by <code>getVisualMap</code></li>
+     * </ul>
+     * Note that this length stays identical to the source text length if
+     * Bidi marks are inserted or removed using option bits of
+     * <code>writeReordered</code>, or if option
+     * <code>REORDER_INVERSE_NUMBERS_AS_L</code> has been set.
+     *
+     * @return The length of the reordered text resulting from
+     *         the last call to <code>setPara</code>.
+     *
+     * @throws IllegalStateException if this call is not preceded by a successful
+     *         call to <code>setPara</code> or <code>setLine</code>
+     *
+     * @see #setPara
+     * @see #OPTION_INSERT_MARKS
+     * @see #OPTION_REMOVE_CONTROLS
+     * @see #REORDER_INVERSE_NUMBERS_AS_L
+     * @stable ICU 3.8
+     */
+    public int getResultLength() {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /* paragraphs API methods ------------------------------------------------- */
+
+    /**
+     * Get the paragraph level of the text.
+     *
+     * @return The paragraph level. If there are multiple paragraphs, their
+     *         level may vary if the required paraLevel is LEVEL_DEFAULT_LTR or
+     *         LEVEL_DEFAULT_RTL.  In that case, the level of the first paragraph
+     *         is returned.
+     *
+     * @throws IllegalStateException if this call is not preceded by a successful
+     *         call to <code>setPara</code> or <code>setLine</code>
+     *
+     * @see #LEVEL_DEFAULT_LTR
+     * @see #LEVEL_DEFAULT_RTL
+     * @see #getParagraph
+     * @see #getParagraphByIndex
+     * @stable ICU 3.8
+     */
+    public byte getParaLevel()
+    {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Get the number of paragraphs.
+     *
+     * @return The number of paragraphs.
+     *
+     * @throws IllegalStateException if this call is not preceded by a successful
+     *         call to <code>setPara</code> or <code>setLine</code>
+     * @stable ICU 3.8
+     */
+    public int countParagraphs()
+    {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Get a paragraph, given the index of this paragraph.
+     *
+     * This method returns information about a paragraph.<p>
+     *
+     * @param paraIndex is the number of the paragraph, in the
+     *        range <code>[0..countParagraphs()-1]</code>.
+     *
+     * @return a BidiRun object with the details of the paragraph:<br>
+     *        <code>start</code> will receive the index of the first character
+     *        of the paragraph in the text.<br>
+     *        <code>limit</code> will receive the limit of the paragraph.<br>
+     *        <code>embeddingLevel</code> will receive the level of the paragraph.
+     *
+     * @throws IllegalStateException if this call is not preceded by a successful
+     *         call to <code>setPara</code> or <code>setLine</code>
+     * @throws IllegalArgumentException if paraIndex is not in the range
+     *        <code>[0..countParagraphs()-1]</code>
+     *
+     * @see com.ibm.icu.text.BidiRun
+     * @stable ICU 3.8
+     */
+    public BidiRun getParagraphByIndex(int paraIndex)
+    {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Get a paragraph, given a position within the text.
+     * This method returns information about a paragraph.<br>
+     * Note: if the paragraph index is known, it is more efficient to
+     * retrieve the paragraph information using getParagraphByIndex().<p>
+     *
+     * @param charIndex is the index of a character within the text, in the
+     *        range <code>[0..getProcessedLength()-1]</code>.
+     *
+     * @return a BidiRun object with the details of the paragraph:<br>
+     *        <code>start</code> will receive the index of the first character
+     *        of the paragraph in the text.<br>
+     *        <code>limit</code> will receive the limit of the paragraph.<br>
+     *        <code>embeddingLevel</code> will receive the level of the paragraph.
+     *
+     * @throws IllegalStateException if this call is not preceded by a successful
+     *         call to <code>setPara</code> or <code>setLine</code>
+     * @throws IllegalArgumentException if charIndex is not within the legal range
+     *
+     * @see com.ibm.icu.text.BidiRun
+     * @see #getParagraphByIndex
+     * @see #getProcessedLength
+     * @stable ICU 3.8
+     */
+    public BidiRun getParagraph(int charIndex)
+    {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Get the index of a paragraph, given a position within the text.<p>
+     *
+     * @param charIndex is the index of a character within the text, in the
+     *        range <code>[0..getProcessedLength()-1]</code>.
+     *
+     * @return The index of the paragraph containing the specified position,
+     *         starting from 0.
+     *
+     * @throws IllegalStateException if this call is not preceded by a successful
+     *         call to <code>setPara</code> or <code>setLine</code>
+     * @throws IllegalArgumentException if charIndex is not within the legal range
+     *
+     * @see com.ibm.icu.text.BidiRun
+     * @see #getProcessedLength
+     * @stable ICU 3.8
+     */
+    public int getParagraphIndex(int charIndex)
+    {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Set a custom Bidi classifier used by the UBA implementation for Bidi
+     * class determination.
+     *
+     * @param classifier A new custom classifier. This can be null.
+     *
+     * @see #getCustomClassifier
+     * @stable ICU 3.8
+     */
+    public void setCustomClassifier(BidiClassifier classifier) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Gets the current custom class classifier used for Bidi class
+     * determination.
+     *
+     * @return An instance of class <code>BidiClassifier</code>
+     *
+     * @see #setCustomClassifier
+     * @stable ICU 3.8
+     */
+    public BidiClassifier getCustomClassifier() {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Retrieves the Bidi class for a given code point.
+     * <p>If a <code>BidiClassifier</code> is defined and returns a value
+     * other than <code>CLASS_DEFAULT</code>, that value is used; otherwise
+     * the default class determination mechanism is invoked.</p>
+     *
+     * @param c The code point to get a Bidi class for.
+     *
+     * @return The Bidi class for the character <code>c</code> that is in effect
+     *         for this <code>Bidi</code> instance.
+     *
+     * @see BidiClassifier
+     * @stable ICU 3.8
+     */
+    public int getCustomizedClass(int c) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * <code>setLine()</code> returns a <code>Bidi</code> object to
+     * contain the reordering information, especially the resolved levels,
+     * for all the characters in a line of text. This line of text is
+     * specified by referring to a <code>Bidi</code> object representing
+     * this information for a piece of text containing one or more paragraphs,
+     * and by specifying a range of indexes in this text.<p>
+     * In the new line object, the indexes will range from 0 to <code>limit-start-1</code>.<p>
+     *
+     * This is used after calling <code>setPara()</code>
+     * for a piece of text, and after line-breaking on that text.
+     * It is not necessary if each paragraph is treated as a single line.<p>
+     *
+     * After line-breaking, rules (L1) and (L2) for the treatment of
+     * trailing WS and for reordering are performed on
+     * a <code>Bidi</code> object that represents a line.<p>
+     *
+     * <strong>Important: </strong>the line <code>Bidi</code> object may
+     * reference data within the global text <code>Bidi</code> object.
+     * You should not alter the content of the global text object until
+     * you are finished using the line object.
+     *
+     * @param start is the line's first index into the text.
+     *
+     * @param limit is just behind the line's last index into the text
+     *        (its last index +1).
+     *
+     * @return a <code>Bidi</code> object that will now represent a line of the text.
+     *
+     * @throws IllegalStateException if this call is not preceded by a successful
+     *         call to <code>setPara</code>
+     * @throws IllegalArgumentException if start and limit are not in the range
+     *         <code>0&lt;=start&lt;limit&lt;=getProcessedLength()</code>,
+     *         or if the specified line crosses a paragraph boundary
+     *
+     * @see #setPara
+     * @see #getProcessedLength
+     * @stable ICU 3.8
+     */
+    public Bidi setLine(int start, int limit)
+    {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Get the level for one character.
+     *
+     * @param charIndex the index of a character.
+     *
+     * @return The level for the character at <code>charIndex</code>.
+     *
+     * @throws IllegalStateException if this call is not preceded by a successful
+     *         call to <code>setPara</code> or <code>setLine</code>
+     * @throws IllegalArgumentException if charIndex is not in the range
+     *         <code>0&lt;=charIndex&lt;getProcessedLength()</code>
+     *
+     * @see #getProcessedLength
+     * @stable ICU 3.8
+     */
+    public byte getLevelAt(int charIndex)
+    {
+        return (byte)bidi.getLevelAt(charIndex);
+    }
+
+    /**
+     * Get an array of levels for each character.<p>
+     *
+     * Note that this method may allocate memory under some
+     * circumstances, unlike <code>getLevelAt()</code>.
+     *
+     * @return The levels array for the text,
+     *         or <code>null</code> if an error occurs.
+     *
+     * @throws IllegalStateException if this call is not preceded by a successful
+     *         call to <code>setPara</code> or <code>setLine</code>
+     * @stable ICU 3.8
+     */
+    public byte[] getLevels()
+    {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Get a logical run.
+     * This method returns information about a run and is used
+     * to retrieve runs in logical order.<p>
+     * This is especially useful for line-breaking on a paragraph.
+     *
+     * @param logicalPosition is a logical position within the source text.
+     *
+     * @return a BidiRun object filled with <code>start</code> containing
+     *        the first character of the run, <code>limit</code> containing
+     *        the limit of the run, and <code>embeddingLevel</code> containing
+     *        the level of the run.
+     *
+     * @throws IllegalStateException if this call is not preceded by a successful
+     *         call to <code>setPara</code> or <code>setLine</code>
+     * @throws IllegalArgumentException if logicalPosition is not in the range
+     *         <code>0&lt;=logicalPosition&lt;getProcessedLength()</code>
+     *
+     * @see com.ibm.icu.text.BidiRun
+     * @see com.ibm.icu.text.BidiRun#getStart()
+     * @see com.ibm.icu.text.BidiRun#getLimit()
+     * @see com.ibm.icu.text.BidiRun#getEmbeddingLevel()
+     *
+     * @stable ICU 3.8
+     */
+    public BidiRun getLogicalRun(int logicalPosition)
+    {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Get the number of runs.
+     * This method may invoke the actual reordering on the
+     * <code>Bidi</code> object, after <code>setPara()</code>
+     * may have resolved only the levels of the text. Therefore,
+     * <code>countRuns()</code> may have to allocate memory,
+     * and may throw an exception if it fails to do so.
+     *
+     * @return The number of runs.
+     *
+     * @throws IllegalStateException if this call is not preceded by a successful
+     *         call to <code>setPara</code> or <code>setLine</code>
+     * @stable ICU 3.8
+     */
+    public int countRuns()
+    {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     *
+     * Get a <code>BidiRun</code> object according to its index. BidiRun methods
+     * may be used to retrieve the run's logical start, length and level,
+     * which can be even for an LTR run or odd for an RTL run.
+     * In an RTL run, the character at the logical start is
+     * visually on the right of the displayed run.
+     * The length is the number of characters in the run.<p>
+     * <code>countRuns()</code> is normally called
+     * before the runs are retrieved.
+     *
+     * <p>
+     *  Example:
+     * <pre>
+     *  Bidi bidi = new Bidi();
+     *  String text = "abc 123 DEFG xyz";
+     *  bidi.setPara(text, Bidi.RTL, null);
+     *  int i, count=bidi.countRuns(), logicalStart, visualIndex=0, length;
+     *  BidiRun run;
+     *  for (i = 0; i &lt; count; ++i) {
+     *      run = bidi.getVisualRun(i);
+     *      logicalStart = run.getStart();
+     *      length = run.getLength();
+     *      if (Bidi.LTR == run.getEmbeddingLevel()) {
+     *          do { // LTR
+     *              show_char(text.charAt(logicalStart++), visualIndex++);
+     *          } while (--length &gt; 0);
+     *      } else {
+     *          logicalStart += length;  // logicalLimit
+     *          do { // RTL
+     *              show_char(text.charAt(--logicalStart), visualIndex++);
+     *          } while (--length &gt; 0);
+     *      }
+     *  }
+     * </pre>
+     * <p>
+     * Note that in right-to-left runs, code like this places
+     * second surrogates before first ones (which is generally a bad idea)
+     * and combining characters before base characters.
+     * <p>
+     * Use of <code>{@link #writeReordered}</code>, optionally with the
+     * <code>{@link #KEEP_BASE_COMBINING}</code> option, can be considered in
+     * order to avoid these issues.
+     *
+     * @param runIndex is the number of the run in visual order, in the
+     *        range <code>[0..countRuns()-1]</code>.
+     *
+     * @return a BidiRun object containing the details of the run. The
+     *         directionality of the run is
+     *         <code>LTR==0</code> or <code>RTL==1</code>,
+     *         never <code>MIXED</code>.
+     *
+     * @throws IllegalStateException if this call is not preceded by a successful
+     *         call to <code>setPara</code> or <code>setLine</code>
+     * @throws IllegalArgumentException if <code>runIndex</code> is not in
+     *         the range <code>0&lt;=runIndex&lt;countRuns()</code>
+     *
+     * @see #countRuns()
+     * @see com.ibm.icu.text.BidiRun
+     * @see com.ibm.icu.text.BidiRun#getStart()
+     * @see com.ibm.icu.text.BidiRun#getLength()
+     * @see com.ibm.icu.text.BidiRun#getEmbeddingLevel()
+     * @stable ICU 3.8
+     */
+    public BidiRun getVisualRun(int runIndex)
+    {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Get the visual position from a logical text position.
+     * If such a mapping is used many times on the same
+     * <code>Bidi</code> object, then calling
+     * <code>getLogicalMap()</code> is more efficient.
+     * <p>
+     * The value returned may be <code>MAP_NOWHERE</code> if there is no
+     * visual position because the corresponding text character is a Bidi
+     * control removed from output by the option
+     * <code>OPTION_REMOVE_CONTROLS</code>.
+     * <p>
+     * When the visual output is altered by using options of
+     * <code>writeReordered()</code> such as <code>INSERT_LRM_FOR_NUMERIC</code>,
+     * <code>KEEP_BASE_COMBINING</code>, <code>OUTPUT_REVERSE</code>,
+     * <code>REMOVE_BIDI_CONTROLS</code>, the visual position returned may not
+     * be correct. It is advised to use, when possible, reordering options
+     * such as {@link #OPTION_INSERT_MARKS} and {@link #OPTION_REMOVE_CONTROLS}.
+     * <p>
+     * Note that in right-to-left runs, this mapping places
+     * second surrogates before first ones (which is generally a bad idea)
+     * and combining characters before base characters.
+     * Use of <code>{@link #writeReordered}</code>, optionally with the
+     * <code>{@link #KEEP_BASE_COMBINING}</code> option can be considered instead
+     * of using the mapping, in order to avoid these issues.
+     *
+     * @param logicalIndex is the index of a character in the text.
+     *
+     * @return The visual position of this character.
+     *
+     * @throws IllegalStateException if this call is not preceded by a successful
+     *         call to <code>setPara</code> or <code>setLine</code>
+     * @throws IllegalArgumentException if <code>logicalIndex</code> is not in
+     *         the range <code>0&lt;=logicalIndex&lt;getProcessedLength()</code>
+     *
+     * @see #getLogicalMap
+     * @see #getLogicalIndex
+     * @see #getProcessedLength
+     * @see #MAP_NOWHERE
+     * @see #OPTION_REMOVE_CONTROLS
+     * @see #writeReordered
+     * @stable ICU 3.8
+     */
+    public int getVisualIndex(int logicalIndex)
+    {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+
+    /**
+     * Get the logical text position from a visual position.
+     * If such a mapping is used many times on the same
+     * <code>Bidi</code> object, then calling
+     * <code>getVisualMap()</code> is more efficient.
+     * <p>
+     * The value returned may be <code>MAP_NOWHERE</code> if there is no
+     * logical position because the corresponding text character is a Bidi
+     * mark inserted in the output by option
+     * <code>OPTION_INSERT_MARKS</code>.
+     * <p>
+     * This is the inverse method to <code>getVisualIndex()</code>.
+     * <p>
+     * When the visual output is altered by using options of
+     * <code>writeReordered()</code> such as <code>INSERT_LRM_FOR_NUMERIC</code>,
+     * <code>KEEP_BASE_COMBINING</code>, <code>OUTPUT_REVERSE</code>,
+     * <code>REMOVE_BIDI_CONTROLS</code>, the logical position returned may not
+     * be correct. It is advised to use, when possible, reordering options
+     * such as {@link #OPTION_INSERT_MARKS} and {@link #OPTION_REMOVE_CONTROLS}.
+     *
+     * @param visualIndex is the visual position of a character.
+     *
+     * @return The index of this character in the text.
+     *
+     * @throws IllegalStateException if this call is not preceded by a successful
+     *         call to <code>setPara</code> or <code>setLine</code>
+     * @throws IllegalArgumentException if <code>visualIndex</code> is not in
+     *         the range <code>0&lt;=visualIndex&lt;getResultLength()</code>
+     *
+     * @see #getVisualMap
+     * @see #getVisualIndex
+     * @see #getResultLength
+     * @see #MAP_NOWHERE
+     * @see #OPTION_INSERT_MARKS
+     * @see #writeReordered
+     * @stable ICU 3.8
+     */
+    public int getLogicalIndex(int visualIndex)
+    {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Get a logical-to-visual index map (array) for the characters in the
+     * <code>Bidi</code> (paragraph or line) object.
+     * <p>
+     * Some values in the map may be <code>MAP_NOWHERE</code> if the
+     * corresponding text characters are Bidi controls removed from the visual
+     * output by the option <code>OPTION_REMOVE_CONTROLS</code>.
+     * <p>
+     * When the visual output is altered by using options of
+     * <code>writeReordered()</code> such as <code>INSERT_LRM_FOR_NUMERIC</code>,
+     * <code>KEEP_BASE_COMBINING</code>, <code>OUTPUT_REVERSE</code>,
+     * <code>REMOVE_BIDI_CONTROLS</code>, the visual positions returned may not
+     * be correct. It is advised to use, when possible, reordering options
+     * such as {@link #OPTION_INSERT_MARKS} and {@link #OPTION_REMOVE_CONTROLS}.
+     * <p>
+     * Note that in right-to-left runs, this mapping places
+     * second surrogates before first ones (which is generally a bad idea)
+     * and combining characters before base characters.
+     * Use of <code>{@link #writeReordered}</code>, optionally with the
+     * <code>{@link #KEEP_BASE_COMBINING}</code> option can be considered instead
+     * of using the mapping, in order to avoid these issues.
+     *
+     * @return an array of <code>getProcessedLength()</code>
+     *        indexes which will reflect the reordering of the characters.<br><br>
+     *        The index map will result in
+     *        <code>indexMap[logicalIndex]==visualIndex</code>, where
+     *        <code>indexMap</code> represents the returned array.
+     *
+     * @throws IllegalStateException if this call is not preceded by a successful
+     *         call to <code>setPara</code> or <code>setLine</code>
+     *
+     * @see #getVisualMap
+     * @see #getVisualIndex
+     * @see #getProcessedLength
+     * @see #MAP_NOWHERE
+     * @see #OPTION_REMOVE_CONTROLS
+     * @see #writeReordered
+     * @stable ICU 3.8
+     */
+    public int[] getLogicalMap()
+    {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Get a visual-to-logical index map (array) for the characters in the
+     * <code>Bidi</code> (paragraph or line) object.
+     * <p>
+     * Some values in the map may be <code>MAP_NOWHERE</code> if the
+     * corresponding text characters are Bidi marks inserted in the visual
+     * output by the option <code>OPTION_INSERT_MARKS</code>.
+     * <p>
+     * When the visual output is altered by using options of
+     * <code>writeReordered()</code> such as <code>INSERT_LRM_FOR_NUMERIC</code>,
+     * <code>KEEP_BASE_COMBINING</code>, <code>OUTPUT_REVERSE</code>,
+     * <code>REMOVE_BIDI_CONTROLS</code>, the logical positions returned may not
+     * be correct. It is advised to use, when possible, reordering options
+     * such as {@link #OPTION_INSERT_MARKS} and {@link #OPTION_REMOVE_CONTROLS}.
+     *
+     * @return an array of <code>getResultLength()</code>
+     *        indexes which will reflect the reordering of the characters.<br><br>
+     *        The index map will result in
+     *        <code>indexMap[visualIndex]==logicalIndex</code>, where
+     *        <code>indexMap</code> represents the returned array.
+     *
+     * @throws IllegalStateException if this call is not preceded by a successful
+     *         call to <code>setPara</code> or <code>setLine</code>
+     *
+     * @see #getLogicalMap
+     * @see #getLogicalIndex
+     * @see #getResultLength
+     * @see #MAP_NOWHERE
+     * @see #OPTION_INSERT_MARKS
+     * @see #writeReordered
+     * @stable ICU 3.8
+     */
+    public int[] getVisualMap()
+    {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * This is a convenience method that does not use a <code>Bidi</code> object.
+     * It is intended to be used for when an application has determined the levels
+     * of objects (character sequences) and just needs to have them reordered (L2).
+     * This is equivalent to using <code>getLogicalMap()</code> on a
+     * <code>Bidi</code> object.
+     *
+     * @param levels is an array of levels that have been determined by
+     *        the application.
+     *
+     * @return an array of <code>levels.length</code>
+     *        indexes which will reflect the reordering of the characters.<p>
+     *        The index map will result in
+     *        <code>indexMap[logicalIndex]==visualIndex</code>, where
+     *        <code>indexMap</code> represents the returned array.
+     *
+     * @stable ICU 3.8
+     */
+    public static int[] reorderLogical(byte[] levels)
+    {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * This is a convenience method that does not use a <code>Bidi</code> object.
+     * It is intended to be used for when an application has determined the levels
+     * of objects (character sequences) and just needs to have them reordered (L2).
+     * This is equivalent to using <code>getVisualMap()</code> on a
+     * <code>Bidi</code> object.
+     *
+     * @param levels is an array of levels that have been determined by
+     *        the application.
+     *
+     * @return an array of <code>levels.length</code>
+     *        indexes which will reflect the reordering of the characters.<p>
+     *        The index map will result in
+     *        <code>indexMap[visualIndex]==logicalIndex</code>, where
+     *        <code>indexMap</code> represents the returned array.
+     *
+     * @stable ICU 3.8
+     */
+    public static int[] reorderVisual(byte[] levels)
+    {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Invert an index map.
+     * The index mapping of the argument map is inverted and returned as
+     * an array of indexes that we will call the inverse map.
+     *
+     * @param srcMap is an array whose elements define the original mapping
+     * from a source array to a destination array.
+     * Some elements of the source array may have no mapping in the
+     * destination array. In that case, their value will be
+     * the special value <code>MAP_NOWHERE</code>.
+     * All elements must be >=0 or equal to <code>MAP_NOWHERE</code>.
+     * Some elements in the source map may have a value greater than the
+     * srcMap.length if the destination array has more elements than the
+     * source array.
+     * There must be no duplicate indexes (two or more elements with the
+     * same value except <code>MAP_NOWHERE</code>).
+     *
+     * @return an array representing the inverse map.
+     *         This array has a number of elements equal to 1 + the highest
+     *         value in <code>srcMap</code>.
+     *         For elements of the result array which have no matching elements
+     *         in the source array, the corresponding elements in the inverse
+     *         map will receive a value equal to <code>MAP_NOWHERE</code>.
+     *         If element with index i in <code>srcMap</code> has a value k different
+     *         from <code>MAP_NOWHERE</code>, this means that element i of
+     *         the source array maps to element k in the destination array.
+     *         The inverse map will have value i in its k-th element.
+     *         For all elements of the destination array which do not map to
+     *         an element in the source array, the corresponding element in the
+     *         inverse map will have a value equal to <code>MAP_NOWHERE</code>.
+     *
+     * @see #MAP_NOWHERE
+     * @stable ICU 3.8
+     */
+    public static int[] invertMap(int[] srcMap)
+    {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /*
+     * Fields and methods for compatibility with java.text.bidi (Sun implementation)
+     */
+
+    /**
+     * Constant indicating base direction is left-to-right.
+     * @stable ICU 3.8
+     */
+    public static final int DIRECTION_LEFT_TO_RIGHT = LTR;
+
+    /**
+     * Constant indicating base direction is right-to-left.
+     * @stable ICU 3.8
+     */
+    public static final int DIRECTION_RIGHT_TO_LEFT = RTL;
+
+    /**
+     * Constant indicating that the base direction depends on the first strong
+     * directional character in the text according to the Unicode Bidirectional
+     * Algorithm. If no strong directional character is present, the base
+     * direction is left-to-right.
+     * @stable ICU 3.8
+     */
+    public static final int DIRECTION_DEFAULT_LEFT_TO_RIGHT = LEVEL_DEFAULT_LTR;
+
+    /**
+     * Constant indicating that the base direction depends on the first strong
+     * directional character in the text according to the Unicode Bidirectional
+     * Algorithm. If no strong directional character is present, the base
+     * direction is right-to-left.
+     * @stable ICU 3.8
+     */
+    public static final int DIRECTION_DEFAULT_RIGHT_TO_LEFT = LEVEL_DEFAULT_RTL;
+
+    /**
+     * Create Bidi from the given paragraph of text and base direction.
+     *
+     * @param paragraph a paragraph of text
+     * @param flags a collection of flags that control the algorithm. The
+     *        algorithm understands the flags DIRECTION_LEFT_TO_RIGHT,
+     *        DIRECTION_RIGHT_TO_LEFT, DIRECTION_DEFAULT_LEFT_TO_RIGHT, and
+     *        DIRECTION_DEFAULT_RIGHT_TO_LEFT. Other values are reserved.
+     * @see #DIRECTION_LEFT_TO_RIGHT
+     * @see #DIRECTION_RIGHT_TO_LEFT
+     * @see #DIRECTION_DEFAULT_LEFT_TO_RIGHT
+     * @see #DIRECTION_DEFAULT_RIGHT_TO_LEFT
+     * @stable ICU 3.8
+     */
+    public Bidi(String paragraph, int flags)
+    {
+        // Note: ICU and Oracle JDK are using the
+        // same DIRECTION_* flags definitions.
+        this(new java.text.Bidi(paragraph, flags));
+    }
+
+    /**
+     * Create Bidi from the given paragraph of text.<p>
+     *
+     * The RUN_DIRECTION attribute in the text, if present, determines the base
+     * direction (left-to-right or right-to-left). If not present, the base
+     * direction is computed using the Unicode Bidirectional Algorithm,
+     * defaulting to left-to-right if there are no strong directional characters
+     * in the text. This attribute, if present, must be applied to all the text
+     * in the paragraph.<p>
+     *
+     * The BIDI_EMBEDDING attribute in the text, if present, represents
+     * embedding level information. Negative values from -1 to -62 indicate
+     * overrides at the absolute value of the level. Positive values from 1 to
+     * 62 indicate embeddings. Where values are zero or not defined, the base
+     * embedding level as determined by the base direction is assumed.<p>
+     *
+     * The NUMERIC_SHAPING attribute in the text, if present, converts European
+     * digits to other decimal digits before running the bidi algorithm. This
+     * attribute, if present, must be applied to all the text in the paragraph.<p>
+     *
+     * Note: this constructor calls setPara() internally.
+     *
+     * @param paragraph a paragraph of text with optional character and
+     *        paragraph attribute information
+     * @stable ICU 3.8
+     */
+    public Bidi(AttributedCharacterIterator paragraph)
+    {
+        // ICU does not define its own attributes and just
+        // use java.awt.font.TextAttribute. Thus, no mappings
+        // are necessary.
+        this(new java.text.Bidi(paragraph));
+    }
+
+    /**
+     * Create Bidi from the given text, embedding, and direction information.
+     * The embeddings array may be null. If present, the values represent
+     * embedding level information. Negative values from -1 to -61 indicate
+     * overrides at the absolute value of the level. Positive values from 1 to
+     * 61 indicate embeddings. Where values are zero, the base embedding level
+     * as determined by the base direction is assumed.<p>
+     *
+     * Note: this constructor calls setPara() internally.
+     *
+     * @param text an array containing the paragraph of text to process.
+     * @param textStart the index into the text array of the start of the
+     *        paragraph.
+     * @param embeddings an array containing embedding values for each character
+     *        in the paragraph. This can be null, in which case it is assumed
+     *        that there is no external embedding information.
+     * @param embStart the index into the embedding array of the start of the
+     *        paragraph.
+     * @param paragraphLength the length of the paragraph in the text and
+     *        embeddings arrays.
+     * @param flags a collection of flags that control the algorithm. The
+     *        algorithm understands the flags DIRECTION_LEFT_TO_RIGHT,
+     *        DIRECTION_RIGHT_TO_LEFT, DIRECTION_DEFAULT_LEFT_TO_RIGHT, and
+     *        DIRECTION_DEFAULT_RIGHT_TO_LEFT. Other values are reserved.
+     *
+     * @throws IllegalArgumentException if the values in embeddings are
+     *         not within the allowed range
+     *
+     * @see #DIRECTION_LEFT_TO_RIGHT
+     * @see #DIRECTION_RIGHT_TO_LEFT
+     * @see #DIRECTION_DEFAULT_LEFT_TO_RIGHT
+     * @see #DIRECTION_DEFAULT_RIGHT_TO_LEFT
+     * @stable ICU 3.8
+     */
+    public Bidi(char[] text,
+            int textStart,
+            byte[] embeddings,
+            int embStart,
+            int paragraphLength,
+            int flags)
+    {
+        // Note: ICU and Oracle JDK are using the
+        // same DIRECTION_* flags definitions.
+        this(new java.text.Bidi(text, textStart, embeddings, embStart, paragraphLength, flags));
+    }
+
+    /**
+     * Create a Bidi object representing the bidi information on a line of text
+     * within the paragraph represented by the current Bidi. This call is not
+     * required if the entire paragraph fits on one line.
+     *
+     * @param lineStart the offset from the start of the paragraph to the start
+     *        of the line.
+     * @param lineLimit the offset from the start of the paragraph to the limit
+     *        of the line.
+     *
+     * @throws IllegalStateException if this call is not preceded by a successful
+     *         call to <code>setPara</code>
+     * @throws IllegalArgumentException if lineStart and lineLimit are not in the range
+     *         <code>0&lt;=lineStart&lt;lineLimit&lt;=getProcessedLength()</code>,
+     *         or if the specified line crosses a paragraph boundary
+     * @stable ICU 3.8
+     */
+    public Bidi createLineBidi(int lineStart, int lineLimit)
+    {
+        return new Bidi(bidi.createLineBidi(lineStart, lineLimit));
+    }
+
+    /**
+     * Return true if the line is not left-to-right or right-to-left. This means
+     * it either has mixed runs of left-to-right and right-to-left text, or the
+     * base direction differs from the direction of the only run of text.
+     *
+     * @return true if the line is not left-to-right or right-to-left.
+     *
+     * @throws IllegalStateException if this call is not preceded by a successful
+     *         call to <code>setPara</code>
+     * @stable ICU 3.8
+     */
+    public boolean isMixed()
+    {
+        return bidi.isMixed();
+    }
+
+    /**
+     * Return true if the line is all left-to-right text and the base direction
+     * is left-to-right.
+     *
+     * @return true if the line is all left-to-right text and the base direction
+     *         is left-to-right.
+     *
+     * @throws IllegalStateException if this call is not preceded by a successful
+     *         call to <code>setPara</code>
+     * @stable ICU 3.8
+     */
+    public boolean isLeftToRight()
+    {
+        return bidi.isLeftToRight();
+    }
+
+    /**
+     * Return true if the line is all right-to-left text, and the base direction
+     * is right-to-left
+     *
+     * @return true if the line is all right-to-left text, and the base
+     *         direction is right-to-left
+     *
+     * @throws IllegalStateException if this call is not preceded by a successful
+     *         call to <code>setPara</code>
+     * @stable ICU 3.8
+     */
+    public boolean isRightToLeft()
+    {
+        return bidi.isRightToLeft();
+    }
+
+    /**
+     * Return true if the base direction is left-to-right
+     *
+     * @return true if the base direction is left-to-right
+     *
+     * @throws IllegalStateException if this call is not preceded by a successful
+     *         call to <code>setPara</code> or <code>setLine</code>
+     *
+     * @stable ICU 3.8
+     */
+    public boolean baseIsLeftToRight()
+    {
+        return bidi.baseIsLeftToRight();
+    }
+
+    /**
+     * Return the base level (0 if left-to-right, 1 if right-to-left).
+     *
+     * @return the base level
+     *
+     * @throws IllegalStateException if this call is not preceded by a successful
+     *         call to <code>setPara</code> or <code>setLine</code>
+     *
+     * @stable ICU 3.8
+     */
+    public int getBaseLevel()
+    {
+        return bidi.getBaseLevel();
+    }
+
+    /**
+     * Return the number of level runs.
+     *
+     * @return the number of level runs
+     *
+     * @throws IllegalStateException if this call is not preceded by a successful
+     *         call to <code>setPara</code> or <code>setLine</code>
+     *
+     * @stable ICU 3.8
+     */
+    public int getRunCount()
+    {
+        return bidi.getRunCount();
+    }
+
+    /**
+     * Return the level of the nth logical run in this line.
+     *
+     * @param run the index of the run, between 0 and <code>countRuns()-1</code>
+     *
+     * @return the level of the run
+     *
+     * @throws IllegalStateException if this call is not preceded by a successful
+     *         call to <code>setPara</code> or <code>setLine</code>
+     * @throws IllegalArgumentException if <code>run</code> is not in
+     *         the range <code>0&lt;=run&lt;countRuns()</code>
+     * @stable ICU 3.8
+     */
+    public int getRunLevel(int run)
+    {
+        return bidi.getRunLevel(run);
+    }
+
+    /**
+     * Return the index of the character at the start of the nth logical run in
+     * this line, as an offset from the start of the line.
+     *
+     * @param run the index of the run, between 0 and <code>countRuns()</code>
+     *
+     * @return the start of the run
+     *
+     * @throws IllegalStateException if this call is not preceded by a successful
+     *         call to <code>setPara</code> or <code>setLine</code>
+     * @throws IllegalArgumentException if <code>run</code> is not in
+     *         the range <code>0&lt;=run&lt;countRuns()</code>
+     * @stable ICU 3.8
+     */
+    public int getRunStart(int run)
+    {
+        return bidi.getRunStart(run);
+    }
+
+    /**
+     * Return the index of the character past the end of the nth logical run in
+     * this line, as an offset from the start of the line. For example, this
+     * will return the length of the line for the last run on the line.
+     *
+     * @param run the index of the run, between 0 and <code>countRuns()</code>
+     *
+     * @return the limit of the run
+     *
+     * @throws IllegalStateException if this call is not preceded by a successful
+     *         call to <code>setPara</code> or <code>setLine</code>
+     * @throws IllegalArgumentException if <code>run</code> is not in
+     *         the range <code>0&lt;=run&lt;countRuns()</code>
+     * @stable ICU 3.8
+     */
+    public int getRunLimit(int run)
+    {
+        return bidi.getRunLimit(run);
+    }
+
+    /**
+     * Return true if the specified text requires bidi analysis. If this returns
+     * false, the text will display left-to-right. Clients can then avoid
+     * constructing a Bidi object. Text in the Arabic Presentation Forms area of
+     * Unicode is presumed to already be shaped and ordered for display, and so
+     * will not cause this method to return true.
+     *
+     * @param text the text containing the characters to test
+     * @param start the start of the range of characters to test
+     * @param limit the limit of the range of characters to test
+     *
+     * @return true if the range of characters requires bidi analysis
+     *
+     * @stable ICU 3.8
+     */
+    public static boolean requiresBidi(char[] text,
+            int start,
+            int limit)
+    {
+        return java.text.Bidi.requiresBidi(text, start, limit);
+    }
+
+    /**
+     * Reorder the objects in the array into visual order based on their levels.
+     * This is a utility method to use when you have a collection of objects
+     * representing runs of text in logical order, each run containing text at a
+     * single level. The elements at <code>index</code> from
+     * <code>objectStart</code> up to <code>objectStart + count</code> in the
+     * objects array will be reordered into visual order assuming
+     * each run of text has the level indicated by the corresponding element in
+     * the levels array (at <code>index - objectStart + levelStart</code>).
+     *
+     * @param levels an array representing the bidi level of each object
+     * @param levelStart the start position in the levels array
+     * @param objects the array of objects to be reordered into visual order
+     * @param objectStart the start position in the objects array
+     * @param count the number of objects to reorder
+     * @stable ICU 3.8
+     */
+    public static void reorderVisually(byte[] levels,
+            int levelStart,
+            Object[] objects,
+            int objectStart,
+            int count)
+    {
+        java.text.Bidi.reorderVisually(levels, levelStart, objects, objectStart, count);
+    }
+
+    /**
+     * Take a <code>Bidi</code> object containing the reordering
+     * information for a piece of text (one or more paragraphs) set by
+     * <code>setPara()</code> or for a line of text set by <code>setLine()</code>
+     * and return a string containing the reordered text.
+     *
+     * <p>The text may have been aliased (only a reference was stored
+     * without copying the contents), thus it must not have been modified
+     * since the <code>setPara()</code> call.</p>
+     *
+     * This method preserves the integrity of characters with multiple
+     * code units and (optionally) combining characters.
+     * Characters in RTL runs can be replaced by mirror-image characters
+     * in the returned string. Note that "real" mirroring has to be done in a
+     * rendering engine by glyph selection and that for many "mirrored"
+     * characters there are no Unicode characters as mirror-image equivalents.
+     * There are also options to insert or remove Bidi control
+     * characters; see the descriptions of the return value and the
+     * <code>options</code> parameter, and of the option bit flags.
+     *
+     * @param options A bit set of options for the reordering that control
+     *                how the reordered text is written.
+     *                The options include mirroring the characters on a code
+     *                point basis and inserting LRM characters, which is used
+     *                especially for transforming visually stored text
+     *                to logically stored text (although this is still an
+     *                imperfect implementation of an "inverse Bidi" algorithm
+     *                because it uses the "forward Bidi" algorithm at its core).
+     *                The available options are:
+     *                <code>DO_MIRRORING</code>,
+     *                <code>INSERT_LRM_FOR_NUMERIC</code>,
+     *                <code>KEEP_BASE_COMBINING</code>,
+     *                <code>OUTPUT_REVERSE</code>,
+     *                <code>REMOVE_BIDI_CONTROLS</code>,
+     *                <code>STREAMING</code>
+     *
+     * @return The reordered text.
+     *         If the <code>INSERT_LRM_FOR_NUMERIC</code> option is set, then
+     *         the length of the returned string could be as large as
+     *         <code>getLength()+2*countRuns()</code>.<br>
+     *         If the <code>REMOVE_BIDI_CONTROLS</code> option is set, then the
+     *         length of the returned string may be less than
+     *         <code>getLength()</code>.<br>
+     *         If none of these options is set, then the length of the returned
+     *         string will be exactly <code>getProcessedLength()</code>.
+     *
+     * @throws IllegalStateException if this call is not preceded by a successful
+     *         call to <code>setPara</code> or <code>setLine</code>
+     *
+     * @see #DO_MIRRORING
+     * @see #INSERT_LRM_FOR_NUMERIC
+     * @see #KEEP_BASE_COMBINING
+     * @see #OUTPUT_REVERSE
+     * @see #REMOVE_BIDI_CONTROLS
+     * @see #OPTION_STREAMING
+     * @see #getProcessedLength
+     * @stable ICU 3.8
+     */
+    public String writeReordered(int options)
+    {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Reverse a Right-To-Left run of Unicode text.
+     *
+     * This method preserves the integrity of characters with multiple
+     * code units and (optionally) combining characters.
+     * Characters can be replaced by mirror-image characters
+     * in the destination buffer. Note that "real" mirroring has
+     * to be done in a rendering engine by glyph selection
+     * and that for many "mirrored" characters there are no
+     * Unicode characters as mirror-image equivalents.
+     * There are also options to insert or remove Bidi control
+     * characters.
+     *
+     * This method is the implementation for reversing RTL runs as part
+     * of <code>writeReordered()</code>. For detailed descriptions
+     * of the parameters, see there.
+     * Since no Bidi controls are inserted here, the output string length
+     * will never exceed <code>src.length()</code>.
+     *
+     * @see #writeReordered
+     *
+     * @param src The RTL run text.
+     *
+     * @param options A bit set of options for the reordering that control
+     *                how the reordered text is written.
+     *                See the <code>options</code> parameter in <code>writeReordered()</code>.
+     *
+     * @return The reordered text.
+     *         If the <code>REMOVE_BIDI_CONTROLS</code> option
+     *         is set, then the length of the returned string may be less than
+     *         <code>src.length()</code>. If this option is not set,
+     *         then the length of the returned string will be exactly
+     *         <code>src.length()</code>.
+     *
+     * @throws IllegalArgumentException if <code>src</code> is null.
+     * @stable ICU 3.8
+     */
+    public static String writeReverse(String src, int options)
+    {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/BidiClassifier.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/BidiClassifier.java
index 5063e7c..39ffdf1 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/BidiClassifier.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/BidiClassifier.java
@@ -1,14 +1,14 @@
-/*
- *******************************************************************************
- * Copyright (C) 2011, International Business Machines Corporation and         *
- * others. All Rights Reserved.                                                *
- *******************************************************************************
- */
-package com.ibm.icu.text;
-
-/*
- * Empty stub
- */
-public class BidiClassifier {
-    private BidiClassifier() {}
-}
+/*
+ *******************************************************************************
+ * Copyright (C) 2011, International Business Machines Corporation and         *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+package com.ibm.icu.text;
+
+/*
+ * Empty stub
+ */
+public class BidiClassifier {
+    private BidiClassifier() {}
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/BidiRun.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/BidiRun.java
index 4846816..b0a7448 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/BidiRun.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/BidiRun.java
@@ -1,14 +1,14 @@
-/*
- *******************************************************************************
- * Copyright (C) 2011, International Business Machines Corporation and         *
- * others. All Rights Reserved.                                                *
- *******************************************************************************
- */
-package com.ibm.icu.text;
-
-/*
- * Empty stub
- */
-public class BidiRun {
-    private BidiRun() {}
-}
+/*
+ *******************************************************************************
+ * Copyright (C) 2011, International Business Machines Corporation and         *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+package com.ibm.icu.text;
+
+/*
+ * Empty stub
+ */
+public class BidiRun {
+    private BidiRun() {}
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/BreakIterator.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/BreakIterator.java
index 5b0922f..bf91595 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/BreakIterator.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/BreakIterator.java
@@ -1,833 +1,833 @@
-/*
- *******************************************************************************
- * Copyright (C) 1996-2011, International Business Machines Corporation and    *
- * others. All Rights Reserved.                                                *
- *******************************************************************************
- */
-
-package com.ibm.icu.text;
-
-import java.text.CharacterIterator;
-import java.text.StringCharacterIterator;
-import java.util.Locale;
-
-import com.ibm.icu.util.ULocale;
-
-/**
- * {@icuenhanced java.text.BreakIterator}.{@icu _usage_}
- *
- * <p>A class that locates boundaries in text.  This class defines a protocol for
- * objects that break up a piece of natural-language text according to a set
- * of criteria.  Instances or subclasses of BreakIterator can be provided, for
- * example, to break a piece of text into words, sentences, or logical characters
- * according to the conventions of some language or group of languages.
- *
- * We provide five built-in types of BreakIterator:
- * <ul><li>getTitleInstance() returns a BreakIterator that locates boundaries
- * between title breaks.
- * <li>getSentenceInstance() returns a BreakIterator that locates boundaries
- * between sentences.  This is useful for triple-click selection, for example.
- * <li>getWordInstance() returns a BreakIterator that locates boundaries between
- * words.  This is useful for double-click selection or "find whole words" searches.
- * This type of BreakIterator makes sure there is a boundary position at the
- * beginning and end of each legal word.  (Numbers count as words, too.)  Whitespace
- * and punctuation are kept separate from real words.
- * <li>getLineInstance() returns a BreakIterator that locates positions where it is
- * legal for a text editor to wrap lines.  This is similar to word breaking, but
- * not the same: punctuation and whitespace are generally kept with words (you don't
- * want a line to start with whitespace, for example), and some special characters
- * can force a position to be considered a line-break position or prevent a position
- * from being a line-break position.
- * <li>getCharacterInstance() returns a BreakIterator that locates boundaries between
- * logical characters.  Because of the structure of the Unicode encoding, a logical
- * character may be stored internally as more than one Unicode code point.  (A with an
- * umlaut may be stored as an a followed by a separate combining umlaut character,
- * for example, but the user still thinks of it as one character.)  This iterator allows
- * various processes (especially text editors) to treat as characters the units of text
- * that a user would think of as characters, rather than the units of text that the
- * computer sees as "characters".</ul>
- *
- * BreakIterator's interface follows an "iterator" model (hence the name), meaning it
- * has a concept of a "current position" and methods like first(), last(), next(),
- * and previous() that update the current position.  All BreakIterators uphold the
- * following invariants:
- * <ul><li>The beginning and end of the text are always treated as boundary positions.
- * <li>The current position of the iterator is always a boundary position (random-
- * access methods move the iterator to the nearest boundary position before or
- * after the specified position, not _to_ the specified position).
- * <li>DONE is used as a flag to indicate when iteration has stopped.  DONE is only
- * returned when the current position is the end of the text and the user calls next(),
- * or when the current position is the beginning of the text and the user calls
- * previous().
- * <li>Break positions are numbered by the positions of the characters that follow
- * them.  Thus, under normal circumstances, the position before the first character
- * is 0, the position after the first character is 1, and the position after the
- * last character is 1 plus the length of the string.
- * <li>The client can change the position of an iterator, or the text it analyzes,
- * at will, but cannot change the behavior.  If the user wants different behavior, he
- * must instantiate a new iterator.</ul>
- *
- * BreakIterator accesses the text it analyzes through a CharacterIterator, which makes
- * it possible to use BreakIterator to analyze text in any text-storage vehicle that
- * provides a CharacterIterator interface.
- *
- * <b>Note:</b>  Some types of BreakIterator can take a long time to create, and
- * instances of BreakIterator are not currently cached by the system.  For
- * optimal performance, keep instances of BreakIterator around as long as makes
- * sense.  For example, when word-wrapping a document, don't create and destroy a
- * new BreakIterator for each line.  Create one break iterator for the whole document
- * (or whatever stretch of text you're wrapping) and use it to do the whole job of
- * wrapping the text.
- *
-  * <P>
- * <strong>Examples</strong>:<P>
- * Creating and using text boundaries
- * <blockquote>
- * <pre>
- * public static void main(String args[]) {
- *      if (args.length == 1) {
- *          String stringToExamine = args[0];
- *          //print each word in order
- *          BreakIterator boundary = BreakIterator.getWordInstance();
- *          boundary.setText(stringToExamine);
- *          printEachForward(boundary, stringToExamine);
- *          //print each sentence in reverse order
- *          boundary = BreakIterator.getSentenceInstance(Locale.US);
- *          boundary.setText(stringToExamine);
- *          printEachBackward(boundary, stringToExamine);
- *          printFirst(boundary, stringToExamine);
- *          printLast(boundary, stringToExamine);
- *      }
- * }
- * </pre>
- * </blockquote>
- *
- * Print each element in order
- * <blockquote>
- * <pre>
- * public static void printEachForward(BreakIterator boundary, String source) {
- *     int start = boundary.first();
- *     for (int end = boundary.next();
- *          end != BreakIterator.DONE;
- *          start = end, end = boundary.next()) {
- *          System.out.println(source.substring(start,end));
- *     }
- * }
- * </pre>
- * </blockquote>
- *
- * Print each element in reverse order
- * <blockquote>
- * <pre>
- * public static void printEachBackward(BreakIterator boundary, String source) {
- *     int end = boundary.last();
- *     for (int start = boundary.previous();
- *          start != BreakIterator.DONE;
- *          end = start, start = boundary.previous()) {
- *         System.out.println(source.substring(start,end));
- *     }
- * }
- * </pre>
- * </blockquote>
- *
- * Print first element
- * <blockquote>
- * <pre>
- * public static void printFirst(BreakIterator boundary, String source) {
- *     int start = boundary.first();
- *     int end = boundary.next();
- *     System.out.println(source.substring(start,end));
- * }
- * </pre>
- * </blockquote>
- *
- * Print last element
- * <blockquote>
- * <pre>
- * public static void printLast(BreakIterator boundary, String source) {
- *     int end = boundary.last();
- *     int start = boundary.previous();
- *     System.out.println(source.substring(start,end));
- * }
- * </pre>
- * </blockquote>
- *
- * Print the element at a specified position
- * <blockquote>
- * <pre>
- * public static void printAt(BreakIterator boundary, int pos, String source) {
- *     int end = boundary.following(pos);
- *     int start = boundary.previous();
- *     System.out.println(source.substring(start,end));
- * }
- * </pre>
- * </blockquote>
- *
- * Find the next word
- * <blockquote>
- * <pre>
- * public static int nextWordStartAfter(int pos, String text) {
- *     BreakIterator wb = BreakIterator.getWordInstance();
- *     wb.setText(text);
- *     int last = wb.following(pos);
- *     int current = wb.next();
- *     while (current != BreakIterator.DONE) {
- *         for (int p = last; p < current; p++) {
- *             if (Character.isLetter(text.charAt(p)))
- *                 return last;
- *         }
- *         last = current;
- *         current = wb.next();
- *     }
- *     return BreakIterator.DONE;
- * }
- * </pre>
- * (The iterator returned by BreakIterator.getWordInstance() is unique in that
- * the break positions it returns don't represent both the start and end of the
- * thing being iterated over.  That is, a sentence-break iterator returns breaks
- * that each represent the end of one sentence and the beginning of the next.
- * With the word-break iterator, the characters between two boundaries might be a
- * word, or they might be the punctuation or whitespace between two words.  The
- * above code uses a simple heuristic to determine which boundary is the beginning
- * of a word: If the characters between this boundary and the next boundary
- * include at least one letter (this can be an alphabetical letter, a CJK ideograph,
- * a Hangul syllable, a Kana character, etc.), then the text between this boundary
- * and the next is a word; otherwise, it's the material between words.)
- * </blockquote>
- *
- * @see CharacterIterator
- * @stable ICU 2.0
- *
- */
-
-public abstract class BreakIterator implements Cloneable
-{
-
-    /**
-     * Default constructor.  There is no state that is carried by this abstract
-     * base class.
-     * @stable ICU 2.0
-     */
-    protected BreakIterator()
-    {
-    }
-
-    /**
-     * Clone method.  Creates another BreakIterator with the same behavior and
-     * current state as this one.
-     * @return The clone.
-     * @stable ICU 2.0
-     */
-    public Object clone()
-    {
-        try {
-            return super.clone();
-        }
-        catch (CloneNotSupportedException e) {
-            ///CLOVER:OFF
-            throw new IllegalStateException();
-            ///CLOVER:ON
-        }
-    }
-
-    /**
-     * DONE is returned by previous() and next() after all valid
-     * boundaries have been returned.
-     * @stable ICU 2.0
-     */
-    public static final int DONE = -1;
-
-    /**
-     * Return the first boundary position.  This is always the beginning
-     * index of the text this iterator iterates over.  For example, if
-     * the iterator iterates over a whole string, this function will
-     * always return 0.  This function also updates the iteration position
-     * to point to the beginning of the text.
-     * @return The character offset of the beginning of the stretch of text
-     * being broken.
-     * @stable ICU 2.0
-     */
-    public abstract int first();
-
-    /**
-     * Return the last boundary position.  This is always the "past-the-end"
-     * index of the text this iterator iterates over.  For example, if the
-     * iterator iterates over a whole string (call it "text"), this function
-     * will always return text.length().  This function also updated the
-     * iteration position to point to the end of the text.
-     * @return The character offset of the end of the stretch of text
-     * being broken.
-     * @stable ICU 2.0
-     */
-    public abstract int last();
-
-    /**
-     * Advances the specified number of steps forward in the text (a negative
-     * number, therefore, advances backwards).  If this causes the iterator
-     * to advance off either end of the text, this function returns DONE;
-     * otherwise, this function returns the position of the appropriate
-     * boundary.  Calling this function is equivalent to calling next() or
-     * previous() n times.
-     * @param n The number of boundaries to advance over (if positive, moves
-     * forward; if negative, moves backwards).
-     * @return The position of the boundary n boundaries from the current
-     * iteration position, or DONE if moving n boundaries causes the iterator
-     * to advance off either end of the text.
-     * @stable ICU 2.0
-     */
-    public abstract int next(int n);
-
-    /**
-     * Advances the iterator forward one boundary.  The current iteration
-     * position is updated to point to the next boundary position after the
-     * current position, and this is also the value that is returned.  If
-     * the current position is equal to the value returned by last(), or to
-     * DONE, this function returns DONE and sets the current position to
-     * DONE.
-     * @return The position of the first boundary position following the
-     * iteration position.
-     * @stable ICU 2.0
-     */
-    public abstract int next();
-
-    /**
-     * Advances the iterator backward one boundary.  The current iteration
-     * position is updated to point to the last boundary position before
-     * the current position, and this is also the value that is returned.  If
-     * the current position is equal to the value returned by first(), or to
-     * DONE, this function returns DONE and sets the current position to
-     * DONE.
-     * @return The position of the last boundary position preceding the
-     * iteration position.
-     * @stable ICU 2.0
-     */
-    public abstract int previous();
-
-    /**
-     * Sets the iterator's current iteration position to be the first
-     * boundary position following the specified position.  (Whether the
-     * specified position is itself a boundary position or not doesn't
-     * matter-- this function always moves the iteration position to the
-     * first boundary after the specified position.)  If the specified
-     * position is the past-the-end position, returns DONE.
-     * @param offset The character position to start searching from.
-     * @return The position of the first boundary position following
-     * "offset" (whether or not "offset" itself is a boundary position),
-     * or DONE if "offset" is the past-the-end offset.
-     * @stable ICU 2.0
-     */
-    public abstract int following(int offset);
-
-    /**
-     * Sets the iterator's current iteration position to be the last
-     * boundary position preceding the specified position.  (Whether the
-     * specified position is itself a boundary position or not doesn't
-     * matter-- this function always moves the iteration position to the
-     * last boundary before the specified position.)  If the specified
-     * position is the starting position, returns DONE.
-     * @param offset The character position to start searching from.
-     * @return The position of the last boundary position preceding
-     * "offset" (whether of not "offset" itself is a boundary position),
-     * or DONE if "offset" is the starting offset of the iterator.
-     * @stable ICU 2.0
-     */
-    public int preceding(int offset) {
-        // NOTE:  This implementation is here solely because we can't add new
-        // abstract methods to an existing class.  There is almost ALWAYS a
-        // better, faster way to do this.
-        int pos = following(offset);
-        while (pos >= offset && pos != DONE)
-            pos = previous();
-        return pos;
-    }
-
-    /**
-     * Return true if the specfied position is a boundary position.  If the
-     * function returns true, the current iteration position is set to the
-     * specified position; if the function returns false, the current
-     * iteration position is set as though following() had been called.
-     * @param offset the offset to check.
-     * @return True if "offset" is a boundary position.
-     * @stable ICU 2.0
-     */
-    public boolean isBoundary(int offset) {
-        // Again, this is the default implementation, which is provided solely because
-        // we couldn't add a new abstract method to an existing class.  The real
-        // implementations will usually need to do a little more work.
-        if (offset == 0) {
-            return true;
-        }
-        else
-            return following(offset - 1) == offset;
-    }
-
-    /**
-     * Return the iterator's current position.
-     * @return The iterator's current position.
-     * @stable ICU 2.0
-     */
-    public abstract int current();
-
-    /**
-     * Returns a CharacterIterator over the text being analyzed.
-     * For at least some subclasses of BreakIterator, this is a reference
-     * to the <b>actual iterator being used</b> by the BreakIterator,
-     * and therefore, this function's return value should be treated as
-     * <tt>const</tt>.  No guarantees are made about the current position
-     * of this iterator when it is returned.  If you need to move that
-     * position to examine the text, clone this function's return value first.
-     * @return A CharacterIterator over the text being analyzed.
-     * @stable ICU 2.0
-     */
-    public abstract CharacterIterator getText();
-
-    /**
-     * Sets the iterator to analyze a new piece of text.  The new
-     * piece of text is passed in as a String, and the current
-     * iteration position is reset to the beginning of the string.
-     * (The old text is dropped.)
-     * @param newText A String containing the text to analyze with
-     * this BreakIterator.
-     * @stable ICU 2.0
-     */
-    public void setText(String newText)
-    {
-        setText(new StringCharacterIterator(newText));
-    }
-
-    /**
-     * Sets the iterator to analyze a new piece of text.  The
-     * BreakIterator is passed a CharacterIterator through which
-     * it will access the text itself.  The current iteration
-     * position is reset to the CharacterIterator's start index.
-     * (The old iterator is dropped.)
-     * @param newText A CharacterIterator referring to the text
-     * to analyze with this BreakIterator (the iterator's current
-     * position is ignored, but its other state is significant).
-     * @stable ICU 2.0
-     */
-    public abstract void setText(CharacterIterator newText);
-
-    /**
-     * {@icu}
-     * @stable ICU 2.4
-     */
-    public static final int KIND_CHARACTER = 0;
-    /**
-     * {@icu}
-     * @stable ICU 2.4
-     */
-    public static final int KIND_WORD = 1;
-    /** 
-     * {@icu}
-     * @stable ICU 2.4
-     */
-    public static final int KIND_LINE = 2;
-    /** 
-     * {@icu}
-     * @stable ICU 2.4
-     */
-    public static final int KIND_SENTENCE = 3;
-    /** 
-     * {@icu}
-     * @stable ICU 2.4
-     */
-    public static final int KIND_TITLE = 4;
-
-    /**
-     * Returns a new instance of BreakIterator that locates word boundaries.
-     * This function assumes that the text being analyzed is in the default
-     * locale's language.
-     * @return An instance of BreakIterator that locates word boundaries.
-     * @stable ICU 2.0
-     */
-    public static BreakIterator getWordInstance()
-    {
-        return getWordInstance(Locale.getDefault());
-    }
-
-    /**
-     * Returns a new instance of BreakIterator that locates word boundaries.
-     * @param where A locale specifying the language of the text to be
-     * analyzed.
-     * @return An instance of BreakIterator that locates word boundaries.
-     * @stable ICU 2.0
-     */
-    public static BreakIterator getWordInstance(Locale where)
-    {
-        return getBreakInstance(where, KIND_WORD);
-    }
-
-    /**
-     * {@icu} Returns a new instance of BreakIterator that locates word boundaries.
-     * @param where A locale specifying the language of the text to be
-     * analyzed.
-     * @return An instance of BreakIterator that locates word boundaries.
-     * @stable ICU 3.2
-     */
-    public static BreakIterator getWordInstance(ULocale where)
-    {
-        return getBreakInstance(where.toLocale(), KIND_WORD);
-    }
-
-    /**
-     * Returns a new instance of BreakIterator that locates legal line-
-     * wrapping positions.  This function assumes the text being broken
-     * is in the default locale's language.
-     * @return A new instance of BreakIterator that locates legal
-     * line-wrapping positions.
-     * @stable ICU 2.0
-     */
-    public static BreakIterator getLineInstance()
-    {
-        return getLineInstance(Locale.getDefault());
-    }
-
-    /**
-     * Returns a new instance of BreakIterator that locates legal line-
-     * wrapping positions.
-     * @param where A Locale specifying the language of the text being broken.
-     * @return A new instance of BreakIterator that locates legal
-     * line-wrapping positions.
-     * @stable ICU 2.0
-     */
-    public static BreakIterator getLineInstance(Locale where)
-    {
-        return getBreakInstance(where, KIND_LINE);
-    }
-
-    /**
-     * {@icu} Returns a new instance of BreakIterator that locates legal line-
-     * wrapping positions.
-     * @param where A Locale specifying the language of the text being broken.
-     * @return A new instance of BreakIterator that locates legal
-     * line-wrapping positions.
-     * @stable ICU 3.2
-     */
-    public static BreakIterator getLineInstance(ULocale where)
-    {
-        return getBreakInstance(where.toLocale(), KIND_LINE);
-    }
-
-    /**
-     * Returns a new instance of BreakIterator that locates logical-character
-     * boundaries.  This function assumes that the text being analyzed is
-     * in the default locale's language.
-     * @return A new instance of BreakIterator that locates logical-character
-     * boundaries.
-     * @stable ICU 2.0
-     */
-    public static BreakIterator getCharacterInstance()
-    {
-        return getCharacterInstance(Locale.getDefault());
-    }
-
-    /**
-     * Returns a new instance of BreakIterator that locates logical-character
-     * boundaries.
-     * @param where A Locale specifying the language of the text being analyzed.
-     * @return A new instance of BreakIterator that locates logical-character
-     * boundaries.
-     * @stable ICU 2.0
-     */
-    public static BreakIterator getCharacterInstance(Locale where)
-    {
-        return getBreakInstance(where, KIND_CHARACTER);
-    }
-
-    /**
-     * {@icu} Returns a new instance of BreakIterator that locates logical-character
-     * boundaries.
-     * @param where A Locale specifying the language of the text being analyzed.
-     * @return A new instance of BreakIterator that locates logical-character
-     * boundaries.
-     * @stable ICU 3.2
-     */
-    public static BreakIterator getCharacterInstance(ULocale where)
-    {
-        return getBreakInstance(where.toLocale(), KIND_CHARACTER);
-    }
-
-    /**
-     * Returns a new instance of BreakIterator that locates sentence boundaries.
-     * This function assumes the text being analyzed is in the default locale's
-     * language.
-     * @return A new instance of BreakIterator that locates sentence boundaries.
-     * @stable ICU 2.0
-     */
-    public static BreakIterator getSentenceInstance()
-    {
-        return getSentenceInstance(Locale.getDefault());
-    }
-
-    /**
-     * Returns a new instance of BreakIterator that locates sentence boundaries.
-     * @param where A Locale specifying the language of the text being analyzed.
-     * @return A new instance of BreakIterator that locates sentence boundaries.
-     * @stable ICU 2.0
-     */
-    public static BreakIterator getSentenceInstance(Locale where)
-    {
-        return getBreakInstance(where, KIND_SENTENCE);
-    }
-
-    /**
-     * {@icu} Returns a new instance of BreakIterator that locates sentence boundaries.
-     * @param where A Locale specifying the language of the text being analyzed.
-     * @return A new instance of BreakIterator that locates sentence boundaries.
-     * @stable ICU 3.2
-     */
-    public static BreakIterator getSentenceInstance(ULocale where)
-    {
-        return getBreakInstance(where.toLocale(), KIND_SENTENCE);
-    }
-
-    /**
-     * {@icu} Returns a new instance of BreakIterator that locates title boundaries.
-     * This function assumes the text being analyzed is in the default locale's
-     * language. The iterator returned locates title boundaries as described for
-     * Unicode 3.2 only. For Unicode 4.0 and above title boundary iteration,
-     * please use a word boundary iterator. {@link #getWordInstance}
-     * @return A new instance of BreakIterator that locates title boundaries.
-     * @stable ICU 2.0
-     */
-    public static BreakIterator getTitleInstance()
-    {
-        return getTitleInstance(Locale.getDefault());
-    }
-
-    /**
-     * {@icu} Returns a new instance of BreakIterator that locates title boundaries.
-     * The iterator returned locates title boundaries as described for
-     * Unicode 3.2 only. For Unicode 4.0 and above title boundary iteration,
-     * please use Word Boundary iterator.{@link #getWordInstance}
-     * @param where A Locale specifying the language of the text being analyzed.
-     * @return A new instance of BreakIterator that locates title boundaries.
-     * @stable ICU 2.0
-     */
-    public static BreakIterator getTitleInstance(Locale where)
-    {
-        return getBreakInstance(where, KIND_TITLE);
-    }
-
-    /**
-     * {@icu} Returns a new instance of BreakIterator that locates title boundaries.
-     * The iterator returned locates title boundaries as described for
-     * Unicode 3.2 only. For Unicode 4.0 and above title boundary iteration,
-     * please use Word Boundary iterator.{@link #getWordInstance}
-     * @param where A Locale specifying the language of the text being analyzed.
-     * @return A new instance of BreakIterator that locates title boundaries.
-     * @stable ICU 3.2
-s     */
-    public static BreakIterator getTitleInstance(ULocale where)
-    {
-        return getBreakInstance(where.toLocale(), KIND_TITLE);
-    }
-
-    /**
-     * {@icu} Registers a new break iterator of the indicated kind, to use in the given
-     * locale.  Clones of the iterator will be returned if a request for a break iterator
-     * of the given kind matches or falls back to this locale.
-     * @param iter the BreakIterator instance to adopt.
-     * @param locale the Locale for which this instance is to be registered
-     * @param kind the type of iterator for which this instance is to be registered
-     * @return a registry key that can be used to unregister this instance
-     * @stable ICU 2.4
-     */
-    public static Object registerInstance(BreakIterator iter, Locale locale, int kind) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Registers a new break iterator of the indicated kind, to use in the given
-     * locale.  Clones of the iterator will be returned if a request for a break iterator
-     * of the given kind matches or falls back to this locale.
-     * @param iter the BreakIterator instance to adopt.
-     * @param locale the Locale for which this instance is to be registered
-     * @param kind the type of iterator for which this instance is to be registered
-     * @return a registry key that can be used to unregister this instance
-     * @stable ICU 3.2
-     */
-    public static Object registerInstance(BreakIterator iter, ULocale locale, int kind) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Unregisters a previously-registered BreakIterator using the key returned
-     * from the register call.  Key becomes invalid after this call and should not be used
-     * again.
-     * @param key the registry key returned by a previous call to registerInstance
-     * @return true if the iterator for the key was successfully unregistered
-     * @stable ICU 2.4
-     */
-    public static boolean unregister(Object key) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    // end of registration
-
-    /**
-     * Returns a particular kind of BreakIterator for a locale.
-     * Avoids writing a switch statement with getXYZInstance(where) calls.
-     * @internal
-     * @deprecated This API is ICU internal only.
-     */
-    public static BreakIterator getBreakInstance(ULocale where, int kind) {
-        return getBreakInstance(where.toLocale(), KIND_SENTENCE);
-    }
-
-    private static BreakIterator getBreakInstance(Locale where, int kind) {
-        java.text.BreakIterator br = null;
-        switch(kind) {
-        case KIND_CHARACTER: br = java.text.BreakIterator.getCharacterInstance(where); break;
-        case KIND_WORD: br = java.text.BreakIterator.getWordInstance(where); break;
-        case KIND_LINE: br = java.text.BreakIterator.getLineInstance(where); break;
-        case KIND_SENTENCE: br = java.text.BreakIterator.getSentenceInstance(where); break;             
-        case KIND_TITLE: throw new UnsupportedOperationException("Title break is not supported by com.ibm.icu.base");
-        }
-        return new BreakIteratorHandle(br);
-    }
-
-    /**
-     * Returns a list of locales for which BreakIterators can be used.
-     * @return An array of Locales.  All of the locales in the array can
-     * be used when creating a BreakIterator.
-     * @stable ICU 2.6
-     */
-    public static synchronized Locale[] getAvailableLocales() {
-        return java.text.BreakIterator.getAvailableLocales();
-    }
-
-    /**
-     * {@icu} Returns a list of locales for which BreakIterators can be used.
-     * @return An array of Locales.  All of the locales in the array can
-     * be used when creating a BreakIterator.
-     * @draft ICU 3.2 (retain)
-     * @provisional This API might change or be removed in a future release.
-     */
-    public static synchronized ULocale[] getAvailableULocales() {
-        Locale[] locales = java.text.BreakIterator.getAvailableLocales();
-        ULocale[] ulocales = new ULocale[locales.length];
-        for (int i = 0; i < locales.length; ++i) {
-            ulocales[i] = ULocale.forLocale(locales[i]);
-        }
-        return ulocales;
-    }
-
-    /**
-     * {@icu} Returns the locale that was used to create this object, or null.
-     * This may may differ from the locale requested at the time of
-     * this object's creation.  For example, if an object is created
-     * for locale <tt>en_US_CALIFORNIA</tt>, the actual data may be
-     * drawn from <tt>en</tt> (the <i>actual</i> locale), and
-     * <tt>en_US</tt> may be the most specific locale that exists (the
-     * <i>valid</i> locale).
-     *
-     * <p>Note: The <i>actual</i> locale is returned correctly, but the <i>valid</i>
-     * locale is not, in most cases.
-     * @param type type of information requested, either {@link
-     * com.ibm.icu.util.ULocale#VALID_LOCALE} or {@link
-     * com.ibm.icu.util.ULocale#ACTUAL_LOCALE}.
-     * @return the information specified by <i>type</i>, or null if
-     * this object was not constructed from locale data.
-     * @see com.ibm.icu.util.ULocale
-     * @see com.ibm.icu.util.ULocale#VALID_LOCALE
-     * @see com.ibm.icu.util.ULocale#ACTUAL_LOCALE
-     * @draft ICU 2.8 (retain)
-     * @provisional This API might change or be removed in a future release.
-     */
-    public final ULocale getLocale(ULocale.Type type) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    // forwarding implementation class
-    static final class BreakIteratorHandle extends BreakIterator {
-        /**
-         * @internal
-         */
-        public final java.text.BreakIterator breakIterator;
-
-        /**
-         * @internal
-         * @param delegate the BreakIterator to which to delegate
-         */
-        public BreakIteratorHandle(java.text.BreakIterator delegate) {
-            this.breakIterator = delegate;
-        }
-
-        public int first() {
-            return breakIterator.first();
-        }
-        public int last() {
-            return breakIterator.last();
-        }
-        public int next(int n) {
-            return breakIterator.next(n);
-        }
-        public int next() {
-            return breakIterator.next();
-        }
-        public int previous() {
-            return breakIterator.previous();
-        }
-        public int following(int offset) {
-            return breakIterator.following(offset);
-        }
-        public int preceding(int offset) {
-            return breakIterator.preceding(offset);
-        }
-        public boolean isBoundary(int offset) {
-            return breakIterator.isBoundary(offset);
-        }
-        public int current() {
-            return breakIterator.current();
-        }
-        public CharacterIterator getText() {
-            return breakIterator.getText();
-        }
-        public void setText(CharacterIterator newText) {
-            breakIterator.setText(newText);
-        }
-
-        /**
-         * Return a string suitable for debugging.
-         * @return a string suitable for debugging
-         * @stable ICU 3.4.3
-         */
-        public String toString() {
-            return breakIterator.toString();
-        }
-
-        /**
-         * Return a clone of this BreakIterator.
-         * @return a clone of this BreakIterator
-         * @stable ICU 3.4.3
-         */
-        public Object clone() {
-            return new BreakIteratorHandle((java.text.BreakIterator)breakIterator.clone());
-        }
-
-        /**
-         * Return true if rhs is a BreakIterator with the same break behavior as this.
-         * @return true if rhs equals this
-         * @stable ICU 3.4.3
-         */
-        public boolean equals(Object rhs) {
-            try {
-                return breakIterator.equals(((BreakIteratorHandle)rhs).breakIterator);
-            }
-            catch (Exception e) {
-                return false;
-            }
-        }
-
-        /**
-         * Return a hashCode.
-         * @return a hashCode
-         * @stable ICU 3.4.3
-         */
-        public int hashCode() {
-            return breakIterator.hashCode();
-        }
-    }
-}
+/*
+ *******************************************************************************
+ * Copyright (C) 1996-2011, International Business Machines Corporation and    *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+
+package com.ibm.icu.text;
+
+import java.text.CharacterIterator;
+import java.text.StringCharacterIterator;
+import java.util.Locale;
+
+import com.ibm.icu.util.ULocale;
+
+/**
+ * {@icuenhanced java.text.BreakIterator}.{@icu _usage_}
+ *
+ * <p>A class that locates boundaries in text.  This class defines a protocol for
+ * objects that break up a piece of natural-language text according to a set
+ * of criteria.  Instances or subclasses of BreakIterator can be provided, for
+ * example, to break a piece of text into words, sentences, or logical characters
+ * according to the conventions of some language or group of languages.
+ *
+ * We provide five built-in types of BreakIterator:
+ * <ul><li>getTitleInstance() returns a BreakIterator that locates boundaries
+ * between title breaks.
+ * <li>getSentenceInstance() returns a BreakIterator that locates boundaries
+ * between sentences.  This is useful for triple-click selection, for example.
+ * <li>getWordInstance() returns a BreakIterator that locates boundaries between
+ * words.  This is useful for double-click selection or "find whole words" searches.
+ * This type of BreakIterator makes sure there is a boundary position at the
+ * beginning and end of each legal word.  (Numbers count as words, too.)  Whitespace
+ * and punctuation are kept separate from real words.
+ * <li>getLineInstance() returns a BreakIterator that locates positions where it is
+ * legal for a text editor to wrap lines.  This is similar to word breaking, but
+ * not the same: punctuation and whitespace are generally kept with words (you don't
+ * want a line to start with whitespace, for example), and some special characters
+ * can force a position to be considered a line-break position or prevent a position
+ * from being a line-break position.
+ * <li>getCharacterInstance() returns a BreakIterator that locates boundaries between
+ * logical characters.  Because of the structure of the Unicode encoding, a logical
+ * character may be stored internally as more than one Unicode code point.  (A with an
+ * umlaut may be stored as an a followed by a separate combining umlaut character,
+ * for example, but the user still thinks of it as one character.)  This iterator allows
+ * various processes (especially text editors) to treat as characters the units of text
+ * that a user would think of as characters, rather than the units of text that the
+ * computer sees as "characters".</ul>
+ *
+ * BreakIterator's interface follows an "iterator" model (hence the name), meaning it
+ * has a concept of a "current position" and methods like first(), last(), next(),
+ * and previous() that update the current position.  All BreakIterators uphold the
+ * following invariants:
+ * <ul><li>The beginning and end of the text are always treated as boundary positions.
+ * <li>The current position of the iterator is always a boundary position (random-
+ * access methods move the iterator to the nearest boundary position before or
+ * after the specified position, not _to_ the specified position).
+ * <li>DONE is used as a flag to indicate when iteration has stopped.  DONE is only
+ * returned when the current position is the end of the text and the user calls next(),
+ * or when the current position is the beginning of the text and the user calls
+ * previous().
+ * <li>Break positions are numbered by the positions of the characters that follow
+ * them.  Thus, under normal circumstances, the position before the first character
+ * is 0, the position after the first character is 1, and the position after the
+ * last character is 1 plus the length of the string.
+ * <li>The client can change the position of an iterator, or the text it analyzes,
+ * at will, but cannot change the behavior.  If the user wants different behavior, he
+ * must instantiate a new iterator.</ul>
+ *
+ * BreakIterator accesses the text it analyzes through a CharacterIterator, which makes
+ * it possible to use BreakIterator to analyze text in any text-storage vehicle that
+ * provides a CharacterIterator interface.
+ *
+ * <b>Note:</b>  Some types of BreakIterator can take a long time to create, and
+ * instances of BreakIterator are not currently cached by the system.  For
+ * optimal performance, keep instances of BreakIterator around as long as makes
+ * sense.  For example, when word-wrapping a document, don't create and destroy a
+ * new BreakIterator for each line.  Create one break iterator for the whole document
+ * (or whatever stretch of text you're wrapping) and use it to do the whole job of
+ * wrapping the text.
+ *
+  * <P>
+ * <strong>Examples</strong>:<P>
+ * Creating and using text boundaries
+ * <blockquote>
+ * <pre>
+ * public static void main(String args[]) {
+ *      if (args.length == 1) {
+ *          String stringToExamine = args[0];
+ *          //print each word in order
+ *          BreakIterator boundary = BreakIterator.getWordInstance();
+ *          boundary.setText(stringToExamine);
+ *          printEachForward(boundary, stringToExamine);
+ *          //print each sentence in reverse order
+ *          boundary = BreakIterator.getSentenceInstance(Locale.US);
+ *          boundary.setText(stringToExamine);
+ *          printEachBackward(boundary, stringToExamine);
+ *          printFirst(boundary, stringToExamine);
+ *          printLast(boundary, stringToExamine);
+ *      }
+ * }
+ * </pre>
+ * </blockquote>
+ *
+ * Print each element in order
+ * <blockquote>
+ * <pre>
+ * public static void printEachForward(BreakIterator boundary, String source) {
+ *     int start = boundary.first();
+ *     for (int end = boundary.next();
+ *          end != BreakIterator.DONE;
+ *          start = end, end = boundary.next()) {
+ *          System.out.println(source.substring(start,end));
+ *     }
+ * }
+ * </pre>
+ * </blockquote>
+ *
+ * Print each element in reverse order
+ * <blockquote>
+ * <pre>
+ * public static void printEachBackward(BreakIterator boundary, String source) {
+ *     int end = boundary.last();
+ *     for (int start = boundary.previous();
+ *          start != BreakIterator.DONE;
+ *          end = start, start = boundary.previous()) {
+ *         System.out.println(source.substring(start,end));
+ *     }
+ * }
+ * </pre>
+ * </blockquote>
+ *
+ * Print first element
+ * <blockquote>
+ * <pre>
+ * public static void printFirst(BreakIterator boundary, String source) {
+ *     int start = boundary.first();
+ *     int end = boundary.next();
+ *     System.out.println(source.substring(start,end));
+ * }
+ * </pre>
+ * </blockquote>
+ *
+ * Print last element
+ * <blockquote>
+ * <pre>
+ * public static void printLast(BreakIterator boundary, String source) {
+ *     int end = boundary.last();
+ *     int start = boundary.previous();
+ *     System.out.println(source.substring(start,end));
+ * }
+ * </pre>
+ * </blockquote>
+ *
+ * Print the element at a specified position
+ * <blockquote>
+ * <pre>
+ * public static void printAt(BreakIterator boundary, int pos, String source) {
+ *     int end = boundary.following(pos);
+ *     int start = boundary.previous();
+ *     System.out.println(source.substring(start,end));
+ * }
+ * </pre>
+ * </blockquote>
+ *
+ * Find the next word
+ * <blockquote>
+ * <pre>
+ * public static int nextWordStartAfter(int pos, String text) {
+ *     BreakIterator wb = BreakIterator.getWordInstance();
+ *     wb.setText(text);
+ *     int last = wb.following(pos);
+ *     int current = wb.next();
+ *     while (current != BreakIterator.DONE) {
+ *         for (int p = last; p < current; p++) {
+ *             if (Character.isLetter(text.charAt(p)))
+ *                 return last;
+ *         }
+ *         last = current;
+ *         current = wb.next();
+ *     }
+ *     return BreakIterator.DONE;
+ * }
+ * </pre>
+ * (The iterator returned by BreakIterator.getWordInstance() is unique in that
+ * the break positions it returns don't represent both the start and end of the
+ * thing being iterated over.  That is, a sentence-break iterator returns breaks
+ * that each represent the end of one sentence and the beginning of the next.
+ * With the word-break iterator, the characters between two boundaries might be a
+ * word, or they might be the punctuation or whitespace between two words.  The
+ * above code uses a simple heuristic to determine which boundary is the beginning
+ * of a word: If the characters between this boundary and the next boundary
+ * include at least one letter (this can be an alphabetical letter, a CJK ideograph,
+ * a Hangul syllable, a Kana character, etc.), then the text between this boundary
+ * and the next is a word; otherwise, it's the material between words.)
+ * </blockquote>
+ *
+ * @see CharacterIterator
+ * @stable ICU 2.0
+ *
+ */
+
+public abstract class BreakIterator implements Cloneable
+{
+
+    /**
+     * Default constructor.  There is no state that is carried by this abstract
+     * base class.
+     * @stable ICU 2.0
+     */
+    protected BreakIterator()
+    {
+    }
+
+    /**
+     * Clone method.  Creates another BreakIterator with the same behavior and
+     * current state as this one.
+     * @return The clone.
+     * @stable ICU 2.0
+     */
+    public Object clone()
+    {
+        try {
+            return super.clone();
+        }
+        catch (CloneNotSupportedException e) {
+            ///CLOVER:OFF
+            throw new IllegalStateException();
+            ///CLOVER:ON
+        }
+    }
+
+    /**
+     * DONE is returned by previous() and next() after all valid
+     * boundaries have been returned.
+     * @stable ICU 2.0
+     */
+    public static final int DONE = -1;
+
+    /**
+     * Return the first boundary position.  This is always the beginning
+     * index of the text this iterator iterates over.  For example, if
+     * the iterator iterates over a whole string, this function will
+     * always return 0.  This function also updates the iteration position
+     * to point to the beginning of the text.
+     * @return The character offset of the beginning of the stretch of text
+     * being broken.
+     * @stable ICU 2.0
+     */
+    public abstract int first();
+
+    /**
+     * Return the last boundary position.  This is always the "past-the-end"
+     * index of the text this iterator iterates over.  For example, if the
+     * iterator iterates over a whole string (call it "text"), this function
+     * will always return text.length().  This function also updated the
+     * iteration position to point to the end of the text.
+     * @return The character offset of the end of the stretch of text
+     * being broken.
+     * @stable ICU 2.0
+     */
+    public abstract int last();
+
+    /**
+     * Advances the specified number of steps forward in the text (a negative
+     * number, therefore, advances backwards).  If this causes the iterator
+     * to advance off either end of the text, this function returns DONE;
+     * otherwise, this function returns the position of the appropriate
+     * boundary.  Calling this function is equivalent to calling next() or
+     * previous() n times.
+     * @param n The number of boundaries to advance over (if positive, moves
+     * forward; if negative, moves backwards).
+     * @return The position of the boundary n boundaries from the current
+     * iteration position, or DONE if moving n boundaries causes the iterator
+     * to advance off either end of the text.
+     * @stable ICU 2.0
+     */
+    public abstract int next(int n);
+
+    /**
+     * Advances the iterator forward one boundary.  The current iteration
+     * position is updated to point to the next boundary position after the
+     * current position, and this is also the value that is returned.  If
+     * the current position is equal to the value returned by last(), or to
+     * DONE, this function returns DONE and sets the current position to
+     * DONE.
+     * @return The position of the first boundary position following the
+     * iteration position.
+     * @stable ICU 2.0
+     */
+    public abstract int next();
+
+    /**
+     * Advances the iterator backward one boundary.  The current iteration
+     * position is updated to point to the last boundary position before
+     * the current position, and this is also the value that is returned.  If
+     * the current position is equal to the value returned by first(), or to
+     * DONE, this function returns DONE and sets the current position to
+     * DONE.
+     * @return The position of the last boundary position preceding the
+     * iteration position.
+     * @stable ICU 2.0
+     */
+    public abstract int previous();
+
+    /**
+     * Sets the iterator's current iteration position to be the first
+     * boundary position following the specified position.  (Whether the
+     * specified position is itself a boundary position or not doesn't
+     * matter-- this function always moves the iteration position to the
+     * first boundary after the specified position.)  If the specified
+     * position is the past-the-end position, returns DONE.
+     * @param offset The character position to start searching from.
+     * @return The position of the first boundary position following
+     * "offset" (whether or not "offset" itself is a boundary position),
+     * or DONE if "offset" is the past-the-end offset.
+     * @stable ICU 2.0
+     */
+    public abstract int following(int offset);
+
+    /**
+     * Sets the iterator's current iteration position to be the last
+     * boundary position preceding the specified position.  (Whether the
+     * specified position is itself a boundary position or not doesn't
+     * matter-- this function always moves the iteration position to the
+     * last boundary before the specified position.)  If the specified
+     * position is the starting position, returns DONE.
+     * @param offset The character position to start searching from.
+     * @return The position of the last boundary position preceding
+     * "offset" (whether of not "offset" itself is a boundary position),
+     * or DONE if "offset" is the starting offset of the iterator.
+     * @stable ICU 2.0
+     */
+    public int preceding(int offset) {
+        // NOTE:  This implementation is here solely because we can't add new
+        // abstract methods to an existing class.  There is almost ALWAYS a
+        // better, faster way to do this.
+        int pos = following(offset);
+        while (pos >= offset && pos != DONE)
+            pos = previous();
+        return pos;
+    }
+
+    /**
+     * Return true if the specfied position is a boundary position.  If the
+     * function returns true, the current iteration position is set to the
+     * specified position; if the function returns false, the current
+     * iteration position is set as though following() had been called.
+     * @param offset the offset to check.
+     * @return True if "offset" is a boundary position.
+     * @stable ICU 2.0
+     */
+    public boolean isBoundary(int offset) {
+        // Again, this is the default implementation, which is provided solely because
+        // we couldn't add a new abstract method to an existing class.  The real
+        // implementations will usually need to do a little more work.
+        if (offset == 0) {
+            return true;
+        }
+        else
+            return following(offset - 1) == offset;
+    }
+
+    /**
+     * Return the iterator's current position.
+     * @return The iterator's current position.
+     * @stable ICU 2.0
+     */
+    public abstract int current();
+
+    /**
+     * Returns a CharacterIterator over the text being analyzed.
+     * For at least some subclasses of BreakIterator, this is a reference
+     * to the <b>actual iterator being used</b> by the BreakIterator,
+     * and therefore, this function's return value should be treated as
+     * <tt>const</tt>.  No guarantees are made about the current position
+     * of this iterator when it is returned.  If you need to move that
+     * position to examine the text, clone this function's return value first.
+     * @return A CharacterIterator over the text being analyzed.
+     * @stable ICU 2.0
+     */
+    public abstract CharacterIterator getText();
+
+    /**
+     * Sets the iterator to analyze a new piece of text.  The new
+     * piece of text is passed in as a String, and the current
+     * iteration position is reset to the beginning of the string.
+     * (The old text is dropped.)
+     * @param newText A String containing the text to analyze with
+     * this BreakIterator.
+     * @stable ICU 2.0
+     */
+    public void setText(String newText)
+    {
+        setText(new StringCharacterIterator(newText));
+    }
+
+    /**
+     * Sets the iterator to analyze a new piece of text.  The
+     * BreakIterator is passed a CharacterIterator through which
+     * it will access the text itself.  The current iteration
+     * position is reset to the CharacterIterator's start index.
+     * (The old iterator is dropped.)
+     * @param newText A CharacterIterator referring to the text
+     * to analyze with this BreakIterator (the iterator's current
+     * position is ignored, but its other state is significant).
+     * @stable ICU 2.0
+     */
+    public abstract void setText(CharacterIterator newText);
+
+    /**
+     * {@icu}
+     * @stable ICU 2.4
+     */
+    public static final int KIND_CHARACTER = 0;
+    /**
+     * {@icu}
+     * @stable ICU 2.4
+     */
+    public static final int KIND_WORD = 1;
+    /** 
+     * {@icu}
+     * @stable ICU 2.4
+     */
+    public static final int KIND_LINE = 2;
+    /** 
+     * {@icu}
+     * @stable ICU 2.4
+     */
+    public static final int KIND_SENTENCE = 3;
+    /** 
+     * {@icu}
+     * @stable ICU 2.4
+     */
+    public static final int KIND_TITLE = 4;
+
+    /**
+     * Returns a new instance of BreakIterator that locates word boundaries.
+     * This function assumes that the text being analyzed is in the default
+     * locale's language.
+     * @return An instance of BreakIterator that locates word boundaries.
+     * @stable ICU 2.0
+     */
+    public static BreakIterator getWordInstance()
+    {
+        return getWordInstance(Locale.getDefault());
+    }
+
+    /**
+     * Returns a new instance of BreakIterator that locates word boundaries.
+     * @param where A locale specifying the language of the text to be
+     * analyzed.
+     * @return An instance of BreakIterator that locates word boundaries.
+     * @stable ICU 2.0
+     */
+    public static BreakIterator getWordInstance(Locale where)
+    {
+        return getBreakInstance(where, KIND_WORD);
+    }
+
+    /**
+     * {@icu} Returns a new instance of BreakIterator that locates word boundaries.
+     * @param where A locale specifying the language of the text to be
+     * analyzed.
+     * @return An instance of BreakIterator that locates word boundaries.
+     * @stable ICU 3.2
+     */
+    public static BreakIterator getWordInstance(ULocale where)
+    {
+        return getBreakInstance(where.toLocale(), KIND_WORD);
+    }
+
+    /**
+     * Returns a new instance of BreakIterator that locates legal line-
+     * wrapping positions.  This function assumes the text being broken
+     * is in the default locale's language.
+     * @return A new instance of BreakIterator that locates legal
+     * line-wrapping positions.
+     * @stable ICU 2.0
+     */
+    public static BreakIterator getLineInstance()
+    {
+        return getLineInstance(Locale.getDefault());
+    }
+
+    /**
+     * Returns a new instance of BreakIterator that locates legal line-
+     * wrapping positions.
+     * @param where A Locale specifying the language of the text being broken.
+     * @return A new instance of BreakIterator that locates legal
+     * line-wrapping positions.
+     * @stable ICU 2.0
+     */
+    public static BreakIterator getLineInstance(Locale where)
+    {
+        return getBreakInstance(where, KIND_LINE);
+    }
+
+    /**
+     * {@icu} Returns a new instance of BreakIterator that locates legal line-
+     * wrapping positions.
+     * @param where A Locale specifying the language of the text being broken.
+     * @return A new instance of BreakIterator that locates legal
+     * line-wrapping positions.
+     * @stable ICU 3.2
+     */
+    public static BreakIterator getLineInstance(ULocale where)
+    {
+        return getBreakInstance(where.toLocale(), KIND_LINE);
+    }
+
+    /**
+     * Returns a new instance of BreakIterator that locates logical-character
+     * boundaries.  This function assumes that the text being analyzed is
+     * in the default locale's language.
+     * @return A new instance of BreakIterator that locates logical-character
+     * boundaries.
+     * @stable ICU 2.0
+     */
+    public static BreakIterator getCharacterInstance()
+    {
+        return getCharacterInstance(Locale.getDefault());
+    }
+
+    /**
+     * Returns a new instance of BreakIterator that locates logical-character
+     * boundaries.
+     * @param where A Locale specifying the language of the text being analyzed.
+     * @return A new instance of BreakIterator that locates logical-character
+     * boundaries.
+     * @stable ICU 2.0
+     */
+    public static BreakIterator getCharacterInstance(Locale where)
+    {
+        return getBreakInstance(where, KIND_CHARACTER);
+    }
+
+    /**
+     * {@icu} Returns a new instance of BreakIterator that locates logical-character
+     * boundaries.
+     * @param where A Locale specifying the language of the text being analyzed.
+     * @return A new instance of BreakIterator that locates logical-character
+     * boundaries.
+     * @stable ICU 3.2
+     */
+    public static BreakIterator getCharacterInstance(ULocale where)
+    {
+        return getBreakInstance(where.toLocale(), KIND_CHARACTER);
+    }
+
+    /**
+     * Returns a new instance of BreakIterator that locates sentence boundaries.
+     * This function assumes the text being analyzed is in the default locale's
+     * language.
+     * @return A new instance of BreakIterator that locates sentence boundaries.
+     * @stable ICU 2.0
+     */
+    public static BreakIterator getSentenceInstance()
+    {
+        return getSentenceInstance(Locale.getDefault());
+    }
+
+    /**
+     * Returns a new instance of BreakIterator that locates sentence boundaries.
+     * @param where A Locale specifying the language of the text being analyzed.
+     * @return A new instance of BreakIterator that locates sentence boundaries.
+     * @stable ICU 2.0
+     */
+    public static BreakIterator getSentenceInstance(Locale where)
+    {
+        return getBreakInstance(where, KIND_SENTENCE);
+    }
+
+    /**
+     * {@icu} Returns a new instance of BreakIterator that locates sentence boundaries.
+     * @param where A Locale specifying the language of the text being analyzed.
+     * @return A new instance of BreakIterator that locates sentence boundaries.
+     * @stable ICU 3.2
+     */
+    public static BreakIterator getSentenceInstance(ULocale where)
+    {
+        return getBreakInstance(where.toLocale(), KIND_SENTENCE);
+    }
+
+    /**
+     * {@icu} Returns a new instance of BreakIterator that locates title boundaries.
+     * This function assumes the text being analyzed is in the default locale's
+     * language. The iterator returned locates title boundaries as described for
+     * Unicode 3.2 only. For Unicode 4.0 and above title boundary iteration,
+     * please use a word boundary iterator. {@link #getWordInstance}
+     * @return A new instance of BreakIterator that locates title boundaries.
+     * @stable ICU 2.0
+     */
+    public static BreakIterator getTitleInstance()
+    {
+        return getTitleInstance(Locale.getDefault());
+    }
+
+    /**
+     * {@icu} Returns a new instance of BreakIterator that locates title boundaries.
+     * The iterator returned locates title boundaries as described for
+     * Unicode 3.2 only. For Unicode 4.0 and above title boundary iteration,
+     * please use Word Boundary iterator.{@link #getWordInstance}
+     * @param where A Locale specifying the language of the text being analyzed.
+     * @return A new instance of BreakIterator that locates title boundaries.
+     * @stable ICU 2.0
+     */
+    public static BreakIterator getTitleInstance(Locale where)
+    {
+        return getBreakInstance(where, KIND_TITLE);
+    }
+
+    /**
+     * {@icu} Returns a new instance of BreakIterator that locates title boundaries.
+     * The iterator returned locates title boundaries as described for
+     * Unicode 3.2 only. For Unicode 4.0 and above title boundary iteration,
+     * please use Word Boundary iterator.{@link #getWordInstance}
+     * @param where A Locale specifying the language of the text being analyzed.
+     * @return A new instance of BreakIterator that locates title boundaries.
+     * @stable ICU 3.2
+s     */
+    public static BreakIterator getTitleInstance(ULocale where)
+    {
+        return getBreakInstance(where.toLocale(), KIND_TITLE);
+    }
+
+    /**
+     * {@icu} Registers a new break iterator of the indicated kind, to use in the given
+     * locale.  Clones of the iterator will be returned if a request for a break iterator
+     * of the given kind matches or falls back to this locale.
+     * @param iter the BreakIterator instance to adopt.
+     * @param locale the Locale for which this instance is to be registered
+     * @param kind the type of iterator for which this instance is to be registered
+     * @return a registry key that can be used to unregister this instance
+     * @stable ICU 2.4
+     */
+    public static Object registerInstance(BreakIterator iter, Locale locale, int kind) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Registers a new break iterator of the indicated kind, to use in the given
+     * locale.  Clones of the iterator will be returned if a request for a break iterator
+     * of the given kind matches or falls back to this locale.
+     * @param iter the BreakIterator instance to adopt.
+     * @param locale the Locale for which this instance is to be registered
+     * @param kind the type of iterator for which this instance is to be registered
+     * @return a registry key that can be used to unregister this instance
+     * @stable ICU 3.2
+     */
+    public static Object registerInstance(BreakIterator iter, ULocale locale, int kind) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Unregisters a previously-registered BreakIterator using the key returned
+     * from the register call.  Key becomes invalid after this call and should not be used
+     * again.
+     * @param key the registry key returned by a previous call to registerInstance
+     * @return true if the iterator for the key was successfully unregistered
+     * @stable ICU 2.4
+     */
+    public static boolean unregister(Object key) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    // end of registration
+
+    /**
+     * Returns a particular kind of BreakIterator for a locale.
+     * Avoids writing a switch statement with getXYZInstance(where) calls.
+     * @internal
+     * @deprecated This API is ICU internal only.
+     */
+    public static BreakIterator getBreakInstance(ULocale where, int kind) {
+        return getBreakInstance(where.toLocale(), KIND_SENTENCE);
+    }
+
+    private static BreakIterator getBreakInstance(Locale where, int kind) {
+        java.text.BreakIterator br = null;
+        switch(kind) {
+        case KIND_CHARACTER: br = java.text.BreakIterator.getCharacterInstance(where); break;
+        case KIND_WORD: br = java.text.BreakIterator.getWordInstance(where); break;
+        case KIND_LINE: br = java.text.BreakIterator.getLineInstance(where); break;
+        case KIND_SENTENCE: br = java.text.BreakIterator.getSentenceInstance(where); break;             
+        case KIND_TITLE: throw new UnsupportedOperationException("Title break is not supported by com.ibm.icu.base");
+        }
+        return new BreakIteratorHandle(br);
+    }
+
+    /**
+     * Returns a list of locales for which BreakIterators can be used.
+     * @return An array of Locales.  All of the locales in the array can
+     * be used when creating a BreakIterator.
+     * @stable ICU 2.6
+     */
+    public static synchronized Locale[] getAvailableLocales() {
+        return java.text.BreakIterator.getAvailableLocales();
+    }
+
+    /**
+     * {@icu} Returns a list of locales for which BreakIterators can be used.
+     * @return An array of Locales.  All of the locales in the array can
+     * be used when creating a BreakIterator.
+     * @draft ICU 3.2 (retain)
+     * @provisional This API might change or be removed in a future release.
+     */
+    public static synchronized ULocale[] getAvailableULocales() {
+        Locale[] locales = java.text.BreakIterator.getAvailableLocales();
+        ULocale[] ulocales = new ULocale[locales.length];
+        for (int i = 0; i < locales.length; ++i) {
+            ulocales[i] = ULocale.forLocale(locales[i]);
+        }
+        return ulocales;
+    }
+
+    /**
+     * {@icu} Returns the locale that was used to create this object, or null.
+     * This may may differ from the locale requested at the time of
+     * this object's creation.  For example, if an object is created
+     * for locale <tt>en_US_CALIFORNIA</tt>, the actual data may be
+     * drawn from <tt>en</tt> (the <i>actual</i> locale), and
+     * <tt>en_US</tt> may be the most specific locale that exists (the
+     * <i>valid</i> locale).
+     *
+     * <p>Note: The <i>actual</i> locale is returned correctly, but the <i>valid</i>
+     * locale is not, in most cases.
+     * @param type type of information requested, either {@link
+     * com.ibm.icu.util.ULocale#VALID_LOCALE} or {@link
+     * com.ibm.icu.util.ULocale#ACTUAL_LOCALE}.
+     * @return the information specified by <i>type</i>, or null if
+     * this object was not constructed from locale data.
+     * @see com.ibm.icu.util.ULocale
+     * @see com.ibm.icu.util.ULocale#VALID_LOCALE
+     * @see com.ibm.icu.util.ULocale#ACTUAL_LOCALE
+     * @draft ICU 2.8 (retain)
+     * @provisional This API might change or be removed in a future release.
+     */
+    public final ULocale getLocale(ULocale.Type type) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    // forwarding implementation class
+    static final class BreakIteratorHandle extends BreakIterator {
+        /**
+         * @internal
+         */
+        public final java.text.BreakIterator breakIterator;
+
+        /**
+         * @internal
+         * @param delegate the BreakIterator to which to delegate
+         */
+        public BreakIteratorHandle(java.text.BreakIterator delegate) {
+            this.breakIterator = delegate;
+        }
+
+        public int first() {
+            return breakIterator.first();
+        }
+        public int last() {
+            return breakIterator.last();
+        }
+        public int next(int n) {
+            return breakIterator.next(n);
+        }
+        public int next() {
+            return breakIterator.next();
+        }
+        public int previous() {
+            return breakIterator.previous();
+        }
+        public int following(int offset) {
+            return breakIterator.following(offset);
+        }
+        public int preceding(int offset) {
+            return breakIterator.preceding(offset);
+        }
+        public boolean isBoundary(int offset) {
+            return breakIterator.isBoundary(offset);
+        }
+        public int current() {
+            return breakIterator.current();
+        }
+        public CharacterIterator getText() {
+            return breakIterator.getText();
+        }
+        public void setText(CharacterIterator newText) {
+            breakIterator.setText(newText);
+        }
+
+        /**
+         * Return a string suitable for debugging.
+         * @return a string suitable for debugging
+         * @stable ICU 3.4.3
+         */
+        public String toString() {
+            return breakIterator.toString();
+        }
+
+        /**
+         * Return a clone of this BreakIterator.
+         * @return a clone of this BreakIterator
+         * @stable ICU 3.4.3
+         */
+        public Object clone() {
+            return new BreakIteratorHandle((java.text.BreakIterator)breakIterator.clone());
+        }
+
+        /**
+         * Return true if rhs is a BreakIterator with the same break behavior as this.
+         * @return true if rhs equals this
+         * @stable ICU 3.4.3
+         */
+        public boolean equals(Object rhs) {
+            try {
+                return breakIterator.equals(((BreakIteratorHandle)rhs).breakIterator);
+            }
+            catch (Exception e) {
+                return false;
+            }
+        }
+
+        /**
+         * Return a hashCode.
+         * @return a hashCode
+         * @stable ICU 3.4.3
+         */
+        public int hashCode() {
+            return breakIterator.hashCode();
+        }
+    }
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/CollationKey.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/CollationKey.java
index 5cdef2f..7de3a95 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/CollationKey.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/CollationKey.java
@@ -1,415 +1,415 @@
-/**
-*******************************************************************************
-* Copyright (C) 1996-2011, International Business Machines Corporation and    *
-* others. All Rights Reserved.                                                *
-*******************************************************************************
-*/
-package com.ibm.icu.text;
-
-/**
- * <p>A <code>CollationKey</code> represents a <code>String</code>
- * under the rules of a specific <code>Collator</code>
- * object. Comparing two <code>CollationKey</code>s returns the
- * relative order of the <code>String</code>s they represent.</p>
- *
- * <p>Since the rule set of <code>Collator</code>s can differ, the
- * sort orders of the same string under two different
- * <code>Collator</code>s might differ.  Hence comparing
- * <code>CollationKey</code>s generated from different
- * <code>Collator</code>s can give incorrect results.</p>
- 
- * <p>Both the method
- * <code>CollationKey.compareTo(CollationKey)</code> and the method
- * <code>Collator.compare(String, String)</code> compare two strings
- * and returns their relative order.  The performance characterictics
- * of these two approaches can differ.</p>
- *
- * <p>During the construction of a <code>CollationKey</code>, the
- * entire source string is examined and processed into a series of
- * bits terminated by a null, that are stored in the <code>CollationKey</code>. 
- * When <code>CollationKey.compareTo(CollationKey)</code> executes, it
- * performs bitwise comparison on the bit sequences.  This can incurs
- * startup cost when creating the <code>CollationKey</code>, but once
- * the key is created, binary comparisons are fast.  This approach is
- * recommended when the same strings are to be compared over and over
- * again.</p>
- *
- * <p>On the other hand, implementations of
- * <code>Collator.compare(String, String)</code> can examine and
- * process the strings only until the first characters differing in
- * order.  This approach is recommended if the strings are to be
- * compared only once.</p>
- * 
- * <p>More information about the composition of the bit sequence can
- * be found in the 
- * <a href="http://www.icu-project.org/userguide/Collate_ServiceArchitecture.html">
- * user guide</a>.</p>
- *
- * <p>The following example shows how <code>CollationKey</code>s can be used
- * to sort a list of <code>String</code>s.</p>
- * <blockquote>
- * <pre>
- * // Create an array of CollationKeys for the Strings to be sorted.
- * Collator myCollator = Collator.getInstance();
- * CollationKey[] keys = new CollationKey[3];
- * keys[0] = myCollator.getCollationKey("Tom");
- * keys[1] = myCollator.getCollationKey("Dick");
- * keys[2] = myCollator.getCollationKey("Harry");
- * sort( keys );
- * <br>
- * //...
- * <br>
- * // Inside body of sort routine, compare keys this way
- * if( keys[i].compareTo( keys[j] ) > 0 )
- *    // swap keys[i] and keys[j]
- * <br>
- * //...
- * <br>
- * // Finally, when we've returned from sort.
- * System.out.println( keys[0].getSourceString() );
- * System.out.println( keys[1].getSourceString() );
- * System.out.println( keys[2].getSourceString() );
- * </pre>
- * </blockquote>
- * </p>
- * <p>
- * This class is not subclassable
- * </p>
- * @see Collator
- * @see RuleBasedCollator
- * @author Syn Wee Quek
- * @stable ICU 2.8 
- */
-public final class CollationKey implements Comparable<CollationKey>
-{
-    /**
-     * @internal
-     */
-    final java.text.CollationKey key;
-
-    /**
-     * @internal
-     */
-    CollationKey(java.text.CollationKey delegate) {
-        this.key = delegate;
-    }
-
-    // public inner classes -------------------------------------------------
-    
-    /** 
-     * Options that used in the API CollationKey.getBound() for getting a 
-     * CollationKey based on the bound mode requested.
-     * @stable ICU 2.6
-     */
-    public static final class BoundMode 
-    {
-        /*
-         * do not change the values assigned to the members of this enum. 
-         * Underlying code depends on them having these numbers  
-         */
-         
-        /** 
-         * Lower bound
-         * @stable ICU 2.6
-         */
-        public static final int LOWER = 0;
-
-        /** 
-         * Upper bound that will match strings of exact size
-         * @stable ICU 2.6
-         */
-        public static final int UPPER = 1;
-
-        /** 
-         * Upper bound that will match all the strings that have the same 
-         * initial substring as the given string
-         * @stable ICU 2.6
-         */
-        public static final int UPPER_LONG = 2;
-
-        /**
-         * Number of bound mode
-         * @stable ICU 2.6
-         */
-        public static final int COUNT = 3;
-        
-        /**
-         * Private Constructor
-         */
-        ///CLOVER:OFF
-        private BoundMode(){}
-        ///CLOVER:ON
-    }
-    
-    // public constructor ---------------------------------------------------
-    
-    /**
-     * CollationKey constructor.
-     * This constructor is given public access, unlike the JDK version, to
-     * allow access to users extending the Collator class. See 
-     * {@link Collator#getCollationKey(String)}. 
-     * @param source string this CollationKey is to represent
-     * @param key array of bytes that represent the collation order of argument
-     *            source terminated by a null
-     * @see Collator
-     * @stable ICU 2.8
-     */
-    public CollationKey(String source, byte key[])
-    {
-        throw new UnsupportedOperationException("Constructor not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * CollationKey constructor that forces key to release its internal byte 
-     * array for adoption. key will have a null byte array after this 
-     * construction.
-     * @param source string this CollationKey is to represent
-     * @param key RawCollationKey object that represents the collation order of 
-     *            argument source. 
-     * @see Collator
-     * @see RawCollationKey
-     * @stable ICU 2.8 
-     */
-    public CollationKey(String source, RawCollationKey key)
-    {
-    	throw new UnsupportedOperationException("Constructor not supported by com.ibm.icu.base");
-    }
-
-    // public getters -------------------------------------------------------
-    
-    /**
-     * Return the source string that this CollationKey represents.
-     * @return source string that this CollationKey represents
-     * @stable ICU 2.8
-     */
-    public String getSourceString() 
-    {
-        return key.getSourceString();
-    }
-
-    /**
-     * <p>Duplicates and returns the value of this CollationKey as a sequence 
-     * of big-endian bytes terminated by a null.</p> 
-     *
-     * <p>If two CollationKeys can be legitimately compared, then one can
-     * compare the byte arrays of each to obtain the same result, e.g.
-     * <pre>
-     * byte key1[] = collationkey1.toByteArray();
-     * byte key2[] = collationkey2.toByteArray();
-     * int key, targetkey;
-     * int i = 0;
-     * do {
-     *       key = key1[i] & 0xFF;
-     *     targetkey = key2[i] & 0xFF;
-     *     if (key &lt; targetkey) {
-     *         System.out.println("String 1 is less than string 2");
-     *         return;
-     *     }
-     *     if (targetkey &lt; key) {
-     *         System.out.println("String 1 is more than string 2");
-     *     }
-     *     i ++;
-     * } while (key != 0 && targetKey != 0);
-     *
-     * System.out.println("Strings are equal.");
-     * </pre>
-     * </p>  
-     * @return CollationKey value in a sequence of big-endian byte bytes 
-     *         terminated by a null.
-     * @stable ICU 2.8
-     */
-    public byte[] toByteArray() 
-    {
-        return key.toByteArray();
-    }
-
-    // public other methods -------------------------------------------------    
-     
-    /**
-     * <p>Compare this CollationKey to another CollationKey.  The
-     * collation rules of the Collator that created this key are
-     * applied.</p>
-     *
-     * <p><strong>Note:</strong> Comparison between CollationKeys
-     * created by different Collators might return incorrect
-     * results.  See class documentation.</p>
-     *
-     * @param target target CollationKey
-     * @return an integer value.  If the value is less than zero this CollationKey
-     *         is less than than target, if the value is zero they are equal, and
-     *         if the value is greater than zero this CollationKey is greater 
-     *         than target.
-     * @exception NullPointerException is thrown if argument is null.
-     * @see Collator#compare(String, String)
-     * @stable ICU 2.8 
-     */
-    public int compareTo(CollationKey target)
-    {
-    	return key.compareTo(target.key);
-    }
-
-    /**
-     * <p>Compare this CollationKey and the specified Object for
-     * equality.  The collation rules of the Collator that created
-     * this key are applied.</p>
-     *
-     * <p>See note in compareTo(CollationKey) for warnings about
-     * possible incorrect results.</p>
-     *
-     * @param target the object to compare to.
-     * @return true if the two keys compare as equal, false otherwise.
-     * @see #compareTo(CollationKey)
-     * @exception ClassCastException is thrown when the argument is not 
-     *            a CollationKey.  NullPointerException is thrown when the argument 
-     *            is null.
-     * @stable ICU 2.8 
-     */
-    public boolean equals(Object target) 
-    {
-        if (!(target instanceof CollationKey)) {
-            return false;
-        }
-        
-        return equals((CollationKey)target);
-    }
-    
-    /**
-     * <p>
-     * Compare this CollationKey and the argument target CollationKey for 
-     * equality.
-     * The collation 
-     * rules of the Collator object which created these objects are applied.
-     * </p>
-     * <p>
-     * See note in compareTo(CollationKey) for warnings of incorrect results
-     * </p>
-     * @param target the CollationKey to compare to.
-     * @return true if two objects are equal, false otherwise.
-     * @exception NullPointerException is thrown when the argument is null.
-     * @stable ICU 2.8
-     */
-    public boolean equals(CollationKey target) 
-    {
-    	return key.equals(target.key);
-    }
-
-    /**
-     * <p>Returns a hash code for this CollationKey. The hash value is calculated 
-     * on the key itself, not the String from which the key was created. Thus 
-     * if x and y are CollationKeys, then x.hashCode(x) == y.hashCode() 
-     * if x.equals(y) is true. This allows language-sensitive comparison in a 
-     * hash table.
-     * </p>
-     * @return the hash value.
-     * @stable ICU 2.8
-     */
-    public int hashCode() 
-    {
-    	return key.hashCode();
-    }
-    
-    /**
-     * <p>
-     * Produce a bound for the sort order of a given collation key and a 
-     * strength level. This API does not attempt to find a bound for the 
-     * CollationKey String representation, hence null will be returned in its 
-     * place.
-     * </p>
-     * <p>
-     * Resulting bounds can be used to produce a range of strings that are
-     * between upper and lower bounds. For example, if bounds are produced
-     * for a sortkey of string "smith", strings between upper and lower 
-     * bounds with primary strength would include "Smith", "SMITH", "sMiTh".
-     * </p>
-     * <p>
-     * There are two upper bounds that can be produced. If BoundMode.UPPER
-     * is produced, strings matched would be as above. However, if a bound
-     * is produced using BoundMode.UPPER_LONG is used, the above example will
-     * also match "Smithsonian" and similar.
-     * </p>
-     * <p>
-     * For more on usage, see example in test procedure 
-     * <a href="http://source.icu-project.org/repos/icu/icu4j/trunk/src/com/ibm/icu/dev/test/collator/CollationAPITest.java">
-     * src/com/ibm/icu/dev/test/collator/CollationAPITest/TestBounds.
-     * </a>
-     * </p>
-     * <p>
-     * Collation keys produced may be compared using the <TT>compare</TT> API.
-     * </p>
-     * @param boundType Mode of bound required. It can be BoundMode.LOWER, which 
-     *              produces a lower inclusive bound, BoundMode.UPPER, that 
-     *              produces upper bound that matches strings of the same 
-     *              length or BoundMode.UPPER_LONG that matches strings that 
-     *              have the same starting substring as the source string.
-     * @param noOfLevels Strength levels required in the resulting bound 
-     *                 (for most uses, the recommended value is PRIMARY). This
-     *                 strength should be less than the maximum strength of 
-     *                 this CollationKey.
-     *                 See users guide for explanation on the strength levels a 
-     *                 collation key can have. 
-     * @return the result bounded CollationKey with a valid sort order but 
-     *         a null String representation.
-     * @exception IllegalArgumentException thrown when the strength level 
-     *            requested is higher than or equal to the strength in this
-     *            CollationKey. 
-     *            In the case of an Exception, information 
-     *            about the maximum strength to use will be returned in the 
-     *            Exception. The user can then call getBound() again with the 
-     *            appropriate strength.
-     * @see CollationKey
-     * @see CollationKey.BoundMode
-     * @see Collator#PRIMARY
-     * @see Collator#SECONDARY
-     * @see Collator#TERTIARY
-     * @see Collator#QUATERNARY
-     * @see Collator#IDENTICAL
-     * @stable ICU 2.6
-     */
-    public CollationKey getBound(int boundType, int noOfLevels) 
-    {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-    
-    /** 
-     * <p>
-     * Merges this CollationKey with another. Only the sorting order of the 
-     * CollationKeys will be merged. This API does not attempt to merge the 
-     * String representations of the CollationKeys, hence null will be returned
-     * as the String representation.
-     * </p>
-     * <p>
-     * The strength levels are merged with their corresponding counterparts 
-     * (PRIMARIES with PRIMARIES, SECONDARIES with SECONDARIES etc.). 
-     * </p>
-     * <p>
-     * The merged String representation of the result CollationKey will be a
-     * concatenation of the String representations of the 2 source 
-     * CollationKeys.
-     * </p>
-     * <p>
-     * Between the values from the same level a separator is inserted.
-     * example (uncompressed):
-     * <pre> 
-     * 191B1D 01 050505 01 910505 00 and 1F2123 01 050505 01 910505 00
-     * will be merged as 
-     * 191B1D 02 1F212301 050505 02 050505 01 910505 02 910505 00
-     * </pre>
-     * </p>
-     * <p>
-     * This allows for concatenating of first and last names for sorting, among 
-     * other things.
-     * </p>
-     * </p>
-     * @param source CollationKey to merge with 
-     * @return a CollationKey that contains the valid merged sorting order 
-     *         with a null String representation, 
-     *         i.e. <tt>new CollationKey(null, merge_sort_order)</tt>
-     * @exception IllegalArgumentException thrown if source CollationKey
-     *            argument is null or of 0 length.
-     * @stable ICU 2.6
-     */
-    public CollationKey merge(CollationKey source)
-    {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-}
+/**
+*******************************************************************************
+* Copyright (C) 1996-2011, International Business Machines Corporation and    *
+* others. All Rights Reserved.                                                *
+*******************************************************************************
+*/
+package com.ibm.icu.text;
+
+/**
+ * <p>A <code>CollationKey</code> represents a <code>String</code>
+ * under the rules of a specific <code>Collator</code>
+ * object. Comparing two <code>CollationKey</code>s returns the
+ * relative order of the <code>String</code>s they represent.</p>
+ *
+ * <p>Since the rule set of <code>Collator</code>s can differ, the
+ * sort orders of the same string under two different
+ * <code>Collator</code>s might differ.  Hence comparing
+ * <code>CollationKey</code>s generated from different
+ * <code>Collator</code>s can give incorrect results.</p>
+ 
+ * <p>Both the method
+ * <code>CollationKey.compareTo(CollationKey)</code> and the method
+ * <code>Collator.compare(String, String)</code> compare two strings
+ * and returns their relative order.  The performance characterictics
+ * of these two approaches can differ.</p>
+ *
+ * <p>During the construction of a <code>CollationKey</code>, the
+ * entire source string is examined and processed into a series of
+ * bits terminated by a null, that are stored in the <code>CollationKey</code>. 
+ * When <code>CollationKey.compareTo(CollationKey)</code> executes, it
+ * performs bitwise comparison on the bit sequences.  This can incurs
+ * startup cost when creating the <code>CollationKey</code>, but once
+ * the key is created, binary comparisons are fast.  This approach is
+ * recommended when the same strings are to be compared over and over
+ * again.</p>
+ *
+ * <p>On the other hand, implementations of
+ * <code>Collator.compare(String, String)</code> can examine and
+ * process the strings only until the first characters differing in
+ * order.  This approach is recommended if the strings are to be
+ * compared only once.</p>
+ * 
+ * <p>More information about the composition of the bit sequence can
+ * be found in the 
+ * <a href="http://www.icu-project.org/userguide/Collate_ServiceArchitecture.html">
+ * user guide</a>.</p>
+ *
+ * <p>The following example shows how <code>CollationKey</code>s can be used
+ * to sort a list of <code>String</code>s.</p>
+ * <blockquote>
+ * <pre>
+ * // Create an array of CollationKeys for the Strings to be sorted.
+ * Collator myCollator = Collator.getInstance();
+ * CollationKey[] keys = new CollationKey[3];
+ * keys[0] = myCollator.getCollationKey("Tom");
+ * keys[1] = myCollator.getCollationKey("Dick");
+ * keys[2] = myCollator.getCollationKey("Harry");
+ * sort( keys );
+ * <br>
+ * //...
+ * <br>
+ * // Inside body of sort routine, compare keys this way
+ * if( keys[i].compareTo( keys[j] ) > 0 )
+ *    // swap keys[i] and keys[j]
+ * <br>
+ * //...
+ * <br>
+ * // Finally, when we've returned from sort.
+ * System.out.println( keys[0].getSourceString() );
+ * System.out.println( keys[1].getSourceString() );
+ * System.out.println( keys[2].getSourceString() );
+ * </pre>
+ * </blockquote>
+ * </p>
+ * <p>
+ * This class is not subclassable
+ * </p>
+ * @see Collator
+ * @see RuleBasedCollator
+ * @author Syn Wee Quek
+ * @stable ICU 2.8 
+ */
+public final class CollationKey implements Comparable<CollationKey>
+{
+    /**
+     * @internal
+     */
+    final java.text.CollationKey key;
+
+    /**
+     * @internal
+     */
+    CollationKey(java.text.CollationKey delegate) {
+        this.key = delegate;
+    }
+
+    // public inner classes -------------------------------------------------
+    
+    /** 
+     * Options that used in the API CollationKey.getBound() for getting a 
+     * CollationKey based on the bound mode requested.
+     * @stable ICU 2.6
+     */
+    public static final class BoundMode 
+    {
+        /*
+         * do not change the values assigned to the members of this enum. 
+         * Underlying code depends on them having these numbers  
+         */
+         
+        /** 
+         * Lower bound
+         * @stable ICU 2.6
+         */
+        public static final int LOWER = 0;
+
+        /** 
+         * Upper bound that will match strings of exact size
+         * @stable ICU 2.6
+         */
+        public static final int UPPER = 1;
+
+        /** 
+         * Upper bound that will match all the strings that have the same 
+         * initial substring as the given string
+         * @stable ICU 2.6
+         */
+        public static final int UPPER_LONG = 2;
+
+        /**
+         * Number of bound mode
+         * @stable ICU 2.6
+         */
+        public static final int COUNT = 3;
+        
+        /**
+         * Private Constructor
+         */
+        ///CLOVER:OFF
+        private BoundMode(){}
+        ///CLOVER:ON
+    }
+    
+    // public constructor ---------------------------------------------------
+    
+    /**
+     * CollationKey constructor.
+     * This constructor is given public access, unlike the JDK version, to
+     * allow access to users extending the Collator class. See 
+     * {@link Collator#getCollationKey(String)}. 
+     * @param source string this CollationKey is to represent
+     * @param key array of bytes that represent the collation order of argument
+     *            source terminated by a null
+     * @see Collator
+     * @stable ICU 2.8
+     */
+    public CollationKey(String source, byte key[])
+    {
+        throw new UnsupportedOperationException("Constructor not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * CollationKey constructor that forces key to release its internal byte 
+     * array for adoption. key will have a null byte array after this 
+     * construction.
+     * @param source string this CollationKey is to represent
+     * @param key RawCollationKey object that represents the collation order of 
+     *            argument source. 
+     * @see Collator
+     * @see RawCollationKey
+     * @stable ICU 2.8 
+     */
+    public CollationKey(String source, RawCollationKey key)
+    {
+    	throw new UnsupportedOperationException("Constructor not supported by com.ibm.icu.base");
+    }
+
+    // public getters -------------------------------------------------------
+    
+    /**
+     * Return the source string that this CollationKey represents.
+     * @return source string that this CollationKey represents
+     * @stable ICU 2.8
+     */
+    public String getSourceString() 
+    {
+        return key.getSourceString();
+    }
+
+    /**
+     * <p>Duplicates and returns the value of this CollationKey as a sequence 
+     * of big-endian bytes terminated by a null.</p> 
+     *
+     * <p>If two CollationKeys can be legitimately compared, then one can
+     * compare the byte arrays of each to obtain the same result, e.g.
+     * <pre>
+     * byte key1[] = collationkey1.toByteArray();
+     * byte key2[] = collationkey2.toByteArray();
+     * int key, targetkey;
+     * int i = 0;
+     * do {
+     *       key = key1[i] & 0xFF;
+     *     targetkey = key2[i] & 0xFF;
+     *     if (key &lt; targetkey) {
+     *         System.out.println("String 1 is less than string 2");
+     *         return;
+     *     }
+     *     if (targetkey &lt; key) {
+     *         System.out.println("String 1 is more than string 2");
+     *     }
+     *     i ++;
+     * } while (key != 0 && targetKey != 0);
+     *
+     * System.out.println("Strings are equal.");
+     * </pre>
+     * </p>  
+     * @return CollationKey value in a sequence of big-endian byte bytes 
+     *         terminated by a null.
+     * @stable ICU 2.8
+     */
+    public byte[] toByteArray() 
+    {
+        return key.toByteArray();
+    }
+
+    // public other methods -------------------------------------------------    
+     
+    /**
+     * <p>Compare this CollationKey to another CollationKey.  The
+     * collation rules of the Collator that created this key are
+     * applied.</p>
+     *
+     * <p><strong>Note:</strong> Comparison between CollationKeys
+     * created by different Collators might return incorrect
+     * results.  See class documentation.</p>
+     *
+     * @param target target CollationKey
+     * @return an integer value.  If the value is less than zero this CollationKey
+     *         is less than than target, if the value is zero they are equal, and
+     *         if the value is greater than zero this CollationKey is greater 
+     *         than target.
+     * @exception NullPointerException is thrown if argument is null.
+     * @see Collator#compare(String, String)
+     * @stable ICU 2.8 
+     */
+    public int compareTo(CollationKey target)
+    {
+    	return key.compareTo(target.key);
+    }
+
+    /**
+     * <p>Compare this CollationKey and the specified Object for
+     * equality.  The collation rules of the Collator that created
+     * this key are applied.</p>
+     *
+     * <p>See note in compareTo(CollationKey) for warnings about
+     * possible incorrect results.</p>
+     *
+     * @param target the object to compare to.
+     * @return true if the two keys compare as equal, false otherwise.
+     * @see #compareTo(CollationKey)
+     * @exception ClassCastException is thrown when the argument is not 
+     *            a CollationKey.  NullPointerException is thrown when the argument 
+     *            is null.
+     * @stable ICU 2.8 
+     */
+    public boolean equals(Object target) 
+    {
+        if (!(target instanceof CollationKey)) {
+            return false;
+        }
+        
+        return equals((CollationKey)target);
+    }
+    
+    /**
+     * <p>
+     * Compare this CollationKey and the argument target CollationKey for 
+     * equality.
+     * The collation 
+     * rules of the Collator object which created these objects are applied.
+     * </p>
+     * <p>
+     * See note in compareTo(CollationKey) for warnings of incorrect results
+     * </p>
+     * @param target the CollationKey to compare to.
+     * @return true if two objects are equal, false otherwise.
+     * @exception NullPointerException is thrown when the argument is null.
+     * @stable ICU 2.8
+     */
+    public boolean equals(CollationKey target) 
+    {
+    	return key.equals(target.key);
+    }
+
+    /**
+     * <p>Returns a hash code for this CollationKey. The hash value is calculated 
+     * on the key itself, not the String from which the key was created. Thus 
+     * if x and y are CollationKeys, then x.hashCode(x) == y.hashCode() 
+     * if x.equals(y) is true. This allows language-sensitive comparison in a 
+     * hash table.
+     * </p>
+     * @return the hash value.
+     * @stable ICU 2.8
+     */
+    public int hashCode() 
+    {
+    	return key.hashCode();
+    }
+    
+    /**
+     * <p>
+     * Produce a bound for the sort order of a given collation key and a 
+     * strength level. This API does not attempt to find a bound for the 
+     * CollationKey String representation, hence null will be returned in its 
+     * place.
+     * </p>
+     * <p>
+     * Resulting bounds can be used to produce a range of strings that are
+     * between upper and lower bounds. For example, if bounds are produced
+     * for a sortkey of string "smith", strings between upper and lower 
+     * bounds with primary strength would include "Smith", "SMITH", "sMiTh".
+     * </p>
+     * <p>
+     * There are two upper bounds that can be produced. If BoundMode.UPPER
+     * is produced, strings matched would be as above. However, if a bound
+     * is produced using BoundMode.UPPER_LONG is used, the above example will
+     * also match "Smithsonian" and similar.
+     * </p>
+     * <p>
+     * For more on usage, see example in test procedure 
+     * <a href="http://source.icu-project.org/repos/icu/icu4j/trunk/src/com/ibm/icu/dev/test/collator/CollationAPITest.java">
+     * src/com/ibm/icu/dev/test/collator/CollationAPITest/TestBounds.
+     * </a>
+     * </p>
+     * <p>
+     * Collation keys produced may be compared using the <TT>compare</TT> API.
+     * </p>
+     * @param boundType Mode of bound required. It can be BoundMode.LOWER, which 
+     *              produces a lower inclusive bound, BoundMode.UPPER, that 
+     *              produces upper bound that matches strings of the same 
+     *              length or BoundMode.UPPER_LONG that matches strings that 
+     *              have the same starting substring as the source string.
+     * @param noOfLevels Strength levels required in the resulting bound 
+     *                 (for most uses, the recommended value is PRIMARY). This
+     *                 strength should be less than the maximum strength of 
+     *                 this CollationKey.
+     *                 See users guide for explanation on the strength levels a 
+     *                 collation key can have. 
+     * @return the result bounded CollationKey with a valid sort order but 
+     *         a null String representation.
+     * @exception IllegalArgumentException thrown when the strength level 
+     *            requested is higher than or equal to the strength in this
+     *            CollationKey. 
+     *            In the case of an Exception, information 
+     *            about the maximum strength to use will be returned in the 
+     *            Exception. The user can then call getBound() again with the 
+     *            appropriate strength.
+     * @see CollationKey
+     * @see CollationKey.BoundMode
+     * @see Collator#PRIMARY
+     * @see Collator#SECONDARY
+     * @see Collator#TERTIARY
+     * @see Collator#QUATERNARY
+     * @see Collator#IDENTICAL
+     * @stable ICU 2.6
+     */
+    public CollationKey getBound(int boundType, int noOfLevels) 
+    {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+    
+    /** 
+     * <p>
+     * Merges this CollationKey with another. Only the sorting order of the 
+     * CollationKeys will be merged. This API does not attempt to merge the 
+     * String representations of the CollationKeys, hence null will be returned
+     * as the String representation.
+     * </p>
+     * <p>
+     * The strength levels are merged with their corresponding counterparts 
+     * (PRIMARIES with PRIMARIES, SECONDARIES with SECONDARIES etc.). 
+     * </p>
+     * <p>
+     * The merged String representation of the result CollationKey will be a
+     * concatenation of the String representations of the 2 source 
+     * CollationKeys.
+     * </p>
+     * <p>
+     * Between the values from the same level a separator is inserted.
+     * example (uncompressed):
+     * <pre> 
+     * 191B1D 01 050505 01 910505 00 and 1F2123 01 050505 01 910505 00
+     * will be merged as 
+     * 191B1D 02 1F212301 050505 02 050505 01 910505 02 910505 00
+     * </pre>
+     * </p>
+     * <p>
+     * This allows for concatenating of first and last names for sorting, among 
+     * other things.
+     * </p>
+     * </p>
+     * @param source CollationKey to merge with 
+     * @return a CollationKey that contains the valid merged sorting order 
+     *         with a null String representation, 
+     *         i.e. <tt>new CollationKey(null, merge_sort_order)</tt>
+     * @exception IllegalArgumentException thrown if source CollationKey
+     *            argument is null or of 0 length.
+     * @stable ICU 2.6
+     */
+    public CollationKey merge(CollationKey source)
+    {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/Collator.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/Collator.java
index d9eaaeb..2623e46 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/Collator.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/Collator.java
@@ -1,932 +1,932 @@
-/**
-*******************************************************************************
-* Copyright (C) 1996-2011, International Business Machines Corporation and    *
-* others. All Rights Reserved.                                                *
-*******************************************************************************
-*/
-package com.ibm.icu.text;
-
-import java.util.Comparator;
-import java.util.Locale;
-import java.util.Set;
-
-import com.ibm.icu.util.ULocale;
-import com.ibm.icu.util.VersionInfo;
-
-/**
-* {@icuenhanced java.text.Collator}.{@icu _usage_}
-*
-* <p>Collator performs locale-sensitive string comparison. A concrete
-* subclass, RuleBasedCollator, allows customization of the collation
-* ordering by the use of rule sets.</p>
-*
-* <p>Following the <a href=http://www.unicode.org>Unicode
-* Consortium</a>'s specifications for the
-* <a href="http://www.unicode.org/unicode/reports/tr10/">Unicode Collation
-* Algorithm (UCA)</a>, there are 5 different levels of strength used
-* in comparisons:
-*
-* <ul>
-* <li>PRIMARY strength: Typically, this is used to denote differences between
-*     base characters (for example, "a" &lt; "b").
-*     It is the strongest difference. For example, dictionaries are divided
-*     into different sections by base character.
-* <li>SECONDARY strength: Accents in the characters are considered secondary
-*     differences (for example, "as" &lt; "&agrave;s" &lt; "at"). Other
-*     differences
-*     between letters can also be considered secondary differences, depending
-*     on the language. A secondary difference is ignored when there is a
-*     primary difference anywhere in the strings.
-* <li>TERTIARY strength: Upper and lower case differences in characters are
-*     distinguished at tertiary strength (for example, "ao" &lt; "Ao" &lt;
-*     "a&ograve;"). In addition, a variant of a letter differs from the base
-*     form on the tertiary strength (such as "A" and "&#9398;"). Another
-*     example is the
-*     difference between large and small Kana. A tertiary difference is ignored
-*     when there is a primary or secondary difference anywhere in the strings.
-* <li>QUATERNARY strength: When punctuation is ignored
-*     <a href="http://www.icu-project.org/userguide/Collate_Concepts.html#Ignoring_Punctuation">
-*     (see Ignoring Punctuations in the user guide)</a> at PRIMARY to TERTIARY
-*     strength, an additional strength level can
-*     be used to distinguish words with and without punctuation (for example,
-*     "ab" &lt; "a-b" &lt; "aB").
-*     This difference is ignored when there is a PRIMARY, SECONDARY or TERTIARY
-*     difference. The QUATERNARY strength should only be used if ignoring
-*     punctuation is required.
-* <li>IDENTICAL strength:
-*     When all other strengths are equal, the IDENTICAL strength is used as a
-*     tiebreaker. The Unicode code point values of the NFD form of each string
-*     are compared, just in case there is no difference.
-*     For example, Hebrew cantellation marks are only distinguished at this
-*     strength. This strength should be used sparingly, as only code point
-*     value differences between two strings is an extremely rare occurrence.
-*     Using this strength substantially decreases the performance for both
-*     comparison and collation key generation APIs. This strength also
-*     increases the size of the collation key.
-* </ul>
-*
-* Unlike the JDK, ICU4J's Collator deals only with 2 decomposition modes,
-* the canonical decomposition mode and one that does not use any decomposition.
-* The compatibility decomposition mode, java.text.Collator.FULL_DECOMPOSITION
-* is not supported here. If the canonical
-* decomposition mode is set, the Collator handles un-normalized text properly,
-* producing the same results as if the text were normalized in NFD. If
-* canonical decomposition is turned off, it is the user's responsibility to
-* ensure that all text is already in the appropriate form before performing
-* a comparison or before getting a CollationKey.</p>
-*
-* <p>For more information about the collation service see the
-* <a href="http://www.icu-project.org/userguide/Collate_Intro.html">users
-* guide</a>.</p>
-*
-* <p>Examples of use
-* <pre>
-* // Get the Collator for US English and set its strength to PRIMARY
-* Collator usCollator = Collator.getInstance(Locale.US);
-* usCollator.setStrength(Collator.PRIMARY);
-* if (usCollator.compare("abc", "ABC") == 0) {
-*     System.out.println("Strings are equivalent");
-* }
-*
-* The following example shows how to compare two strings using the
-* Collator for the default locale.
-*
-* // Compare two strings in the default locale
-* Collator myCollator = Collator.getInstance();
-* myCollator.setDecomposition(NO_DECOMPOSITION);
-* if (myCollator.compare("&agrave;&#92;u0325", "a&#92;u0325&#768;") != 0) {
-*     System.out.println("&agrave;&#92;u0325 is not equals to a&#92;u0325&#768; without decomposition");
-*     myCollator.setDecomposition(CANONICAL_DECOMPOSITION);
-*     if (myCollator.compare("&agrave;&#92;u0325", "a&#92;u0325&#768;") != 0) {
-*         System.out.println("Error: &agrave;&#92;u0325 should be equals to a&#92;u0325&#768; with decomposition");
-*     }
-*     else {
-*         System.out.println("&agrave;&#92;u0325 is equals to a&#92;u0325&#768; with decomposition");
-*     }
-* }
-* else {
-*     System.out.println("Error: &agrave;&#92;u0325 should be not equals to a&#92;u0325&#768; without decomposition");
-* }
-* </pre>
-* </p>
-* @see RuleBasedCollator
-* @see CollationKey
-* @author Syn Wee Quek
-* @stable ICU 2.8
-*/
-public class Collator implements Comparator<Object>, Cloneable
-{
-    /**
-     * @internal
-     */
-    private final java.text.Collator collator;
-
-    /**
-     * @internal
-     */
-    private Collator(java.text.Collator delegate) {
-        this.collator = delegate;
-    }
-
-    /**
-     * Create a collator with a null delegate.
-     * For use by possible subclassers.  This is present since
-     * the original Collator is abstract, and so, in theory
-     * subclassable.  All member APIs must be overridden.
-     */
-    protected Collator() {
-        this.collator = null;
-    }
-
-    // public data members ---------------------------------------------------
-
-    /**
-     * Strongest collator strength value. Typically used to denote differences
-     * between base characters. See class documentation for more explanation.
-     * @see #setStrength
-     * @see #getStrength
-     * @stable ICU 2.8
-     */
-    public final static int PRIMARY = java.text.Collator.PRIMARY;
-
-    /**
-     * Second level collator strength value.
-     * Accents in the characters are considered secondary differences.
-     * Other differences between letters can also be considered secondary
-     * differences, depending on the language.
-     * See class documentation for more explanation.
-     * @see #setStrength
-     * @see #getStrength
-     * @stable ICU 2.8
-     */
-    public final static int SECONDARY = java.text.Collator.SECONDARY;
-
-    /**
-     * Third level collator strength value.
-     * Upper and lower case differences in characters are distinguished at this
-     * strength level. In addition, a variant of a letter differs from the base
-     * form on the tertiary level.
-     * See class documentation for more explanation.
-     * @see #setStrength
-     * @see #getStrength
-     * @stable ICU 2.8
-     */
-    public final static int TERTIARY = java.text.Collator.TERTIARY;
-
-    /**
-     * {@icu} Fourth level collator strength value.
-     * When punctuation is ignored
-     * <a href="http://www.icu-project.org/userguide/Collate_Concepts.html#Ignoring_Punctuation">
-     * (see Ignoring Punctuations in the user guide)</a> at PRIMARY to TERTIARY
-     * strength, an additional strength level can
-     * be used to distinguish words with and without punctuation.
-     * See class documentation for more explanation.
-     * @see #setStrength
-     * @see #getStrength
-     * @stable ICU 2.8
-     */
-    public final static int QUATERNARY = java.text.Collator.IDENTICAL;
-
-    /**
-     * Smallest Collator strength value. When all other strengths are equal,
-     * the IDENTICAL strength is used as a tiebreaker. The Unicode code point
-     * values of the NFD form of each string are compared, just in case there
-     * is no difference.
-     * See class documentation for more explanation.
-     * </p>
-     * <p>
-     * Note this value is different from JDK's
-     * </p>
-     * @stable ICU 2.8
-     */
-    public final static int IDENTICAL = java.text.Collator.FULL_DECOMPOSITION;
-
-    /**
-     * {@icunote} This is for backwards compatibility with Java APIs only.  It
-     * should not be used, IDENTICAL should be used instead.  ICU's
-     * collation does not support Java's FULL_DECOMPOSITION mode.
-     * @stable ICU 3.4
-     */
-    public final static int FULL_DECOMPOSITION = java.text.Collator.FULL_DECOMPOSITION;
-
-    /**
-     * Decomposition mode value. With NO_DECOMPOSITION set, Strings
-     * will not be decomposed for collation. This is the default
-     * decomposition setting unless otherwise specified by the locale
-     * used to create the Collator.</p>
-     *
-     * <p><strong>Note</strong> this value is different from the JDK's.</p>
-     * @see #CANONICAL_DECOMPOSITION
-     * @see #getDecomposition
-     * @see #setDecomposition
-     * @stable ICU 2.8
-     */
-    public final static int NO_DECOMPOSITION = java.text.Collator.NO_DECOMPOSITION;
-
-    /**
-     * Decomposition mode value. With CANONICAL_DECOMPOSITION set,
-     * characters that are canonical variants according to the Unicode standard
-     * will be decomposed for collation.</p>
-     *
-     * <p>CANONICAL_DECOMPOSITION corresponds to Normalization Form D as
-     * described in <a href="http://www.unicode.org/unicode/reports/tr15/">
-     * Unicode Technical Report #15</a>.
-     * </p>
-     * @see #NO_DECOMPOSITION
-     * @see #getDecomposition
-     * @see #setDecomposition
-     * @stable ICU 2.8
-     */
-    public final static int CANONICAL_DECOMPOSITION = java.text.Collator.CANONICAL_DECOMPOSITION;
-
-    // public methods --------------------------------------------------------
-
-    // public setters --------------------------------------------------------
-
-    /**
-     * Sets this Collator's strength property. The strength property
-     * determines the minimum level of difference considered significant
-     * during comparison.</p>
-     *
-     * <p>The default strength for the Collator is TERTIARY, unless specified
-     * otherwise by the locale used to create the Collator.</p>
-     *
-     * <p>See the Collator class description for an example of use.</p>
-     * @param newStrength the new strength value.
-     * @see #getStrength
-     * @see #PRIMARY
-     * @see #SECONDARY
-     * @see #TERTIARY
-     * @see #QUATERNARY
-     * @see #IDENTICAL
-     * @throws IllegalArgumentException if the new strength value is not one
-     *                of PRIMARY, SECONDARY, TERTIARY, QUATERNARY or IDENTICAL.
-     * @stable ICU 2.8
-     */
-    public void setStrength(int newStrength)
-    {
-        collator.setStrength(newStrength);
-    }
-
-    /**
-     * Sets the decomposition mode of this Collator.  Setting this
-     * decomposition property with CANONICAL_DECOMPOSITION allows the
-     * Collator to handle un-normalized text properly, producing the
-     * same results as if the text were normalized. If
-     * NO_DECOMPOSITION is set, it is the user's responsibility to
-     * insure that all text is already in the appropriate form before
-     * a comparison or before getting a CollationKey. Adjusting
-     * decomposition mode allows the user to select between faster and
-     * more complete collation behavior.</p>
-     *
-     * <p>Since a great many of the world's languages do not require
-     * text normalization, most locales set NO_DECOMPOSITION as the
-     * default decomposition mode.</p>
-     *
-     * The default decompositon mode for the Collator is
-     * NO_DECOMPOSITON, unless specified otherwise by the locale used
-     * to create the Collator.</p>
-     *
-     * <p>See getDecomposition for a description of decomposition
-     * mode.</p>
-     *
-     * @param decomposition the new decomposition mode
-     * @see #getDecomposition
-     * @see #NO_DECOMPOSITION
-     * @see #CANONICAL_DECOMPOSITION
-     * @throws IllegalArgumentException If the given value is not a valid
-     *            decomposition mode.
-     * @stable ICU 2.8
-     */
-    public void setDecomposition(int decomposition)
-    {
-        collator.setDecomposition(decomposition);
-    }
-
-    // public getters --------------------------------------------------------
-
-    /**
-     * Returns the Collator for the current default locale.
-     * The default locale is determined by java.util.Locale.getDefault().
-     * @return the Collator for the default locale (for example, en_US) if it
-     *         is created successfully. Otherwise if there is no Collator
-     *         associated with the current locale, the default UCA collator
-     *         will be returned.
-     * @see java.util.Locale#getDefault()
-     * @see #getInstance(Locale)
-     * @stable ICU 2.8
-     */
-    public static final Collator getInstance()
-    {
-        return new Collator(java.text.Collator.getInstance());
-    }
-
-    /**
-     * Clones the collator.
-     * @stable ICU 2.6
-     * @return a clone of this collator.
-     */
-    public Object clone() throws CloneNotSupportedException {
-        return new Collator((java.text.Collator)collator.clone());
-    }
-
-    // begin registry stuff
-
-    /**
-     * A factory used with registerFactory to register multiple collators and provide
-     * display names for them.  If standard locale display names are sufficient,
-     * Collator instances may be registered instead.
-     * <p><b>Note:</b> as of ICU4J 3.2, the default API for CollatorFactory uses
-     * ULocale instead of Locale.  Instead of overriding createCollator(Locale),
-     * new implementations should override createCollator(ULocale).  Note that
-     * one of these two methods <b>MUST</b> be overridden or else an infinite
-     * loop will occur.
-     * @stable ICU 2.6
-     */
-    public static abstract class CollatorFactory {
-        /**
-         * Return true if this factory will be visible.  Default is true.
-         * If not visible, the locales supported by this factory will not
-         * be listed by getAvailableLocales.
-         *
-         * @return true if this factory is visible
-         * @stable ICU 2.6
-         */
-        public boolean visible() {
-            return true;
-        }
-
-        /**
-         * Return an instance of the appropriate collator.  If the locale
-         * is not supported, return null.
-         * <b>Note:</b> as of ICU4J 3.2, implementations should override
-         * this method instead of createCollator(Locale).
-         * @param loc the locale for which this collator is to be created.
-         * @return the newly created collator.
-         * @stable ICU 3.2
-         */
-        public Collator createCollator(ULocale loc) {
-            return createCollator(loc.toLocale());
-        }
-
-        /**
-         * Return an instance of the appropriate collator.  If the locale
-         * is not supported, return null.
-         * <p><b>Note:</b> as of ICU4J 3.2, implementations should override
-         * createCollator(ULocale) instead of this method, and inherit this
-         * method's implementation.  This method is no longer abstract
-         * and instead delegates to createCollator(ULocale).
-         * @param loc the locale for which this collator is to be created.
-         * @return the newly created collator.
-         * @stable ICU 2.6
-         */
-         public Collator createCollator(Locale loc) {
-            return createCollator(ULocale.forLocale(loc));
-        }
-
-        /**
-         * Return the name of the collator for the objectLocale, localized for the displayLocale.
-         * If objectLocale is not visible or not defined by the factory, return null.
-         * @param objectLocale the locale identifying the collator
-         * @param displayLocale the locale for which the display name of the collator should be localized
-         * @return the display name
-         * @stable ICU 2.6
-         */
-        public String getDisplayName(Locale objectLocale, Locale displayLocale) {
-            return getDisplayName(ULocale.forLocale(objectLocale), ULocale.forLocale(displayLocale));
-        }
-
-        /**
-         * Return the name of the collator for the objectLocale, localized for the displayLocale.
-         * If objectLocale is not visible or not defined by the factory, return null.
-         * @param objectLocale the locale identifying the collator
-         * @param displayLocale the locale for which the display name of the collator should be localized
-         * @return the display name
-         * @stable ICU 3.2
-         */
-        public String getDisplayName(ULocale objectLocale, ULocale displayLocale) {
-            if (visible()) {
-                Set<String> supported = getSupportedLocaleIDs();
-                String name = objectLocale.getBaseName();
-                if (supported.contains(name)) {
-                    return objectLocale.getDisplayName(displayLocale);
-                }
-            }
-            return null;
-        }
-
-        /**
-         * Return an unmodifiable collection of the locale names directly
-         * supported by this factory.
-         *
-         * @return the set of supported locale IDs.
-         * @stable ICU 2.6
-         */
-        public abstract Set<String> getSupportedLocaleIDs();
-
-        /**
-         * Empty default constructor.
-         * @stable ICU 2.6
-         */
-        protected CollatorFactory() {
-        }
-    }
-
-    /**
-     * {@icu} Returns the Collator for the desired locale.
-     * @param locale the desired locale.
-     * @return Collator for the desired locale if it is created successfully.
-     *         Otherwise if there is no Collator
-     *         associated with the current locale, a default UCA collator will
-     *         be returned.
-     * @see java.util.Locale
-     * @see java.util.ResourceBundle
-     * @see #getInstance(Locale)
-     * @see #getInstance()
-     * @stable ICU 3.0
-     */
-    public static final Collator getInstance(ULocale locale) {
-        return getInstance(locale.toLocale());
-    }
-
-    /**
-     * Returns the Collator for the desired locale.
-     * @param locale the desired locale.
-     * @return Collator for the desired locale if it is created successfully.
-     *         Otherwise if there is no Collator
-     *         associated with the current locale, a default UCA collator will
-     *         be returned.
-     * @see java.util.Locale
-     * @see java.util.ResourceBundle
-     * @see #getInstance(ULocale)
-     * @see #getInstance()
-     * @stable ICU 2.8
-     */
-    public static final Collator getInstance(Locale locale) {
-        return new Collator(java.text.Collator.getInstance(locale));
-    }
-
-    /**
-     * {@icu} Registers a collator as the default collator for the provided locale.  The
-     * collator should not be modified after it is registered.
-     *
-     * @param collator the collator to register
-     * @param locale the locale for which this is the default collator
-     * @return an object that can be used to unregister the registered collator.
-     *
-     * @stable ICU 3.2
-     */
-    public static final Object registerInstance(Collator collator, ULocale locale) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Registers a collator factory.
-     *
-     * @param factory the factory to register
-     * @return an object that can be used to unregister the registered factory.
-     *
-     * @stable ICU 2.6
-     */
-    public static final Object registerFactory(CollatorFactory factory) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Unregisters a collator previously registered using registerInstance.
-     * @param registryKey the object previously returned by registerInstance.
-     * @return true if the collator was successfully unregistered.
-     * @stable ICU 2.6
-     */
-    public static final boolean unregister(Object registryKey) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Returns the set of locales, as Locale objects, for which collators
-     * are installed.  Note that Locale objects do not support RFC 3066.
-     * @return the list of locales in which collators are installed.
-     * This list includes any that have been registered, in addition to
-     * those that are installed with ICU4J.
-     * @stable ICU 2.4
-     */
-    public static Locale[] getAvailableLocales() {
-        return java.text.Collator.getAvailableLocales();
-    }
-
-    /**
-     * {@icu} Returns the set of locales, as ULocale objects, for which collators
-     * are installed.  ULocale objects support RFC 3066.
-     * @return the list of locales in which collators are installed.
-     * This list includes any that have been registered, in addition to
-     * those that are installed with ICU4J.
-     * @stable ICU 3.0
-     */
-    public static final ULocale[] getAvailableULocales() {
-        Locale[] locales = java.text.Collator.getAvailableLocales();
-        ULocale[] ulocales = new ULocale[locales.length];
-        for (int i = 0; i < locales.length; ++i) {
-            ulocales[i] = ULocale.forLocale(locales[i]);
-        }
-        return ulocales;
-    }
-
-    /**
-     * {@icu} Returns an array of all possible keywords that are relevant to
-     * collation. At this point, the only recognized keyword for this
-     * service is "collation".
-     * @return an array of valid collation keywords.
-     * @see #getKeywordValues
-     * @stable ICU 3.0
-     */
-    public static final String[] getKeywords() {
-        // No keywords support in com.ibm.icu.base
-        return new String[0];
-    }
-
-    /**
-     * {@icu} Given a keyword, returns an array of all values for
-     * that keyword that are currently in use.
-     * @param keyword one of the keywords returned by getKeywords.
-     * @see #getKeywords
-     * @stable ICU 3.0
-     */
-    public static final String[] getKeywordValues(String keyword) {
-        // No keywords support in com.ibm.icu.base
-        return new String[0];
-    }
-
-    /**
-     * {@icu} Given a key and a locale, returns an array of string values in a preferred
-     * order that would make a difference. These are all and only those values where
-     * the open (creation) of the service with the locale formed from the input locale
-     * plus input keyword and that value has different behavior than creation with the
-     * input locale alone.
-     * @param key           one of the keys supported by this service.  For now, only
-     *                      "collation" is supported.
-     * @param locale        the locale
-     * @param commonlyUsed  if set to true it will return only commonly used values
-     *                      with the given locale in preferred order.  Otherwise,
-     *                      it will return all the available values for the locale.
-     * @return an array of string values for the given key and the locale.
-     * @stable ICU 4.2
-     */
-    public static final String[] getKeywordValuesForLocale(String key, ULocale locale, 
-                                                           boolean commonlyUsed) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Returns the functionally equivalent locale for the given
-     * requested locale, with respect to given keyword, for the
-     * collation service.  If two locales return the same result, then
-     * collators instantiated for these locales will behave
-     * equivalently.  The converse is not always true; two collators
-     * may in fact be equivalent, but return different results, due to
-     * internal details.  The return result has no other meaning than
-     * that stated above, and implies nothing as to the relationship
-     * between the two locales.  This is intended for use by
-     * applications who wish to cache collators, or otherwise reuse
-     * collators when possible.  The functional equivalent may change
-     * over time.  For more information, please see the <a
-     * href="http://www.icu-project.org/userguide/locale.html#services">
-     * Locales and Services</a> section of the ICU User Guide.
-     * @param keyword a particular keyword as enumerated by
-     * getKeywords.
-     * @param locID The requested locale
-     * @param isAvailable If non-null, isAvailable[0] will receive and
-     * output boolean that indicates whether the requested locale was
-     * 'available' to the collation service. If non-null, isAvailable
-     * must have length >= 1.
-     * @return the locale
-     * @stable ICU 3.0
-     */
-    public static final ULocale getFunctionalEquivalent(String keyword,
-                                                        ULocale locID,
-                                                        boolean isAvailable[]) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Returns the functionally equivalent locale for the given
-     * requested locale, with respect to given keyword, for the
-     * collation service.
-     * @param keyword a particular keyword as enumerated by
-     * getKeywords.
-     * @param locID The requested locale
-     * @return the locale
-     * @see #getFunctionalEquivalent(String,ULocale,boolean[])
-     * @stable ICU 3.0
-     */
-    public static final ULocale getFunctionalEquivalent(String keyword,
-                                                        ULocale locID) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Returns the name of the collator for the objectLocale, localized for the
-     * displayLocale.
-     * @param objectLocale the locale of the collator
-     * @param displayLocale the locale for the collator's display name
-     * @return the display name
-     * @stable ICU 2.6
-     */
-    static public String getDisplayName(Locale objectLocale, Locale displayLocale) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Returns the name of the collator for the objectLocale, localized for the
-     * displayLocale.
-     * @param objectLocale the locale of the collator
-     * @param displayLocale the locale for the collator's display name
-     * @return the display name
-     * @stable ICU 3.2
-     */
-    static public String getDisplayName(ULocale objectLocale, ULocale displayLocale) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Returns the name of the collator for the objectLocale, localized for the
-     * current locale.
-     * @param objectLocale the locale of the collator
-     * @return the display name
-     * @stable ICU 2.6
-     */
-    static public String getDisplayName(Locale objectLocale) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Returns the name of the collator for the objectLocale, localized for the
-     * current locale.
-     * @param objectLocale the locale of the collator
-     * @return the display name
-     * @stable ICU 3.2
-     */
-    static public String getDisplayName(ULocale objectLocale) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Returns this Collator's strength property. The strength property
-     * determines the minimum level of difference considered significant.
-     * </p>
-     * {@icunote} This can return QUATERNARY strength, which is not supported by the
-     * JDK version.
-     * <p>
-     * See the Collator class description for more details.
-     * </p>
-     * @return this Collator's current strength property.
-     * @see #setStrength
-     * @see #PRIMARY
-     * @see #SECONDARY
-     * @see #TERTIARY
-     * @see #QUATERNARY
-     * @see #IDENTICAL
-     * @stable ICU 2.8
-     */
-    public int getStrength()
-    {
-        return collator.getStrength();
-    }
-
-    /**
-     * Returns the decomposition mode of this Collator. The decomposition mode
-     * determines how Unicode composed characters are handled.
-     * </p>
-     * <p>
-     * See the Collator class description for more details.
-     * </p>
-     * @return the decomposition mode
-     * @see #setDecomposition
-     * @see #NO_DECOMPOSITION
-     * @see #CANONICAL_DECOMPOSITION
-     * @stable ICU 2.8
-     */
-    public int getDecomposition()
-    {
-        return collator.getDecomposition();
-    }
-
-    // public other methods -------------------------------------------------
-
-    /**
-     * Compares the equality of two text Strings using
-     * this Collator's rules, strength and decomposition mode.  Convenience method.
-     * @param source the source string to be compared.
-     * @param target the target string to be compared.
-     * @return true if the strings are equal according to the collation
-     *         rules, otherwise false.
-     * @see #compare
-     * @throws NullPointerException thrown if either arguments is null.
-     * @stable ICU 2.8
-     */
-    public boolean equals(String source, String target)
-    {
-        return (compare(source, target) == 0);
-    }
-
-    /**
-     * {@icu} Returns a UnicodeSet that contains all the characters and sequences tailored
-     * in this collator.
-     * @return a pointer to a UnicodeSet object containing all the
-     *         code points and sequences that may sort differently than
-     *         in the UCA.
-     * @stable ICU 2.4
-     */
-    public UnicodeSet getTailoredSet()
-    {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Compares the source text String to the target text String according to
-     * this Collator's rules, strength and decomposition mode.
-     * Returns an integer less than,
-     * equal to or greater than zero depending on whether the source String is
-     * less than, equal to or greater than the target String. See the Collator
-     * class description for an example of use.
-     * </p>
-     * @param source the source String.
-     * @param target the target String.
-     * @return Returns an integer value. Value is less than zero if source is
-     *         less than target, value is zero if source and target are equal,
-     *         value is greater than zero if source is greater than target.
-     * @see CollationKey
-     * @see #getCollationKey
-     * @throws NullPointerException thrown if either argument is null.
-     * @stable ICU 2.8
-     */
-    public int compare(String source, String target) {
-        return collator.compare(source, target);
-    }
-
-    /**
-     * Compares the source Object to the target Object.
-     * </p>
-     * @param source the source Object.
-     * @param target the target Object.
-     * @return Returns an integer value. Value is less than zero if source is
-     *         less than target, value is zero if source and target are equal,
-     *         value is greater than zero if source is greater than target.
-     * @throws ClassCastException thrown if either arguments cannot be cast to String.
-     * @stable ICU 4.2
-     */
-    public int compare(Object source, Object target) {
-        return compare((String)source, (String)target);
-    }
-
-    /**
-     * <p>
-     * Transforms the String into a CollationKey suitable for efficient
-     * repeated comparison.  The resulting key depends on the collator's
-     * rules, strength and decomposition mode.
-     * </p>
-     * <p>See the CollationKey class documentation for more information.</p>
-     * @param source the string to be transformed into a CollationKey.
-     * @return the CollationKey for the given String based on this Collator's
-     *         collation rules. If the source String is null, a null
-     *         CollationKey is returned.
-     * @see CollationKey
-     * @see #compare(String, String)
-     * @see #getRawCollationKey
-     * @stable ICU 2.8
-     */
-    public CollationKey getCollationKey(String source) {
-        return new CollationKey(collator.getCollationKey(source));
-    }
-
-    /**
-     * {@icu} Returns the simpler form of a CollationKey for the String source following
-     * the rules of this Collator and stores the result into the user provided argument
-     * key.  If key has a internal byte array of length that's too small for the result,
-     * the internal byte array will be grown to the exact required size.
-     * @param source the text String to be transformed into a RawCollationKey
-     * @return If key is null, a new instance of RawCollationKey will be
-     *         created and returned, otherwise the user provided key will be
-     *         returned.
-     * @see #compare(String, String)
-     * @see #getCollationKey
-     * @see RawCollationKey
-     * @stable ICU 2.8
-     */
-    public RawCollationKey getRawCollationKey(String source, RawCollationKey key) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Variable top is a two byte primary value which causes all the codepoints
-     * with primary values that are less or equal than the variable top to be
-     * shifted when alternate handling is set to SHIFTED.
-     * </p>
-     * <p>
-     * Sets the variable top to a collation element value of a string supplied.
-     * </p>
-     * @param varTop one or more (if contraction) characters to which the
-     *               variable top should be set
-     * @return a int value containing the value of the variable top in upper 16
-     *         bits. Lower 16 bits are undefined.
-     * @throws IllegalArgumentException is thrown if varTop argument is not
-     *            a valid variable top element. A variable top element is
-     *            invalid when it is a contraction that does not exist in the
-     *            Collation order or when the PRIMARY strength collation
-     *            element for the variable top has more than two bytes
-     * @see #getVariableTop
-     * @see RuleBasedCollator#setAlternateHandlingShifted
-     * @stable ICU 2.6
-     */
-    public int setVariableTop(String varTop) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Returns the variable top value of a Collator.
-     * Lower 16 bits are undefined and should be ignored.
-     * @return the variable top value of a Collator.
-     * @see #setVariableTop
-     * @stable ICU 2.6
-     */
-    public int getVariableTop() {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Sets the variable top to a collation element value supplied.
-     * Variable top is set to the upper 16 bits.
-     * Lower 16 bits are ignored.
-     * @param varTop Collation element value, as returned by setVariableTop or
-     *               getVariableTop
-     * @see #getVariableTop
-     * @see #setVariableTop
-     * @stable ICU 2.6
-     */
-    public void setVariableTop(int varTop) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Returns the version of this collator object.
-     * @return the version object associated with this collator
-     * @stable ICU 2.8
-     */
-    public VersionInfo getVersion() {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Returns the UCA version of this collator object.
-     * @return the version object associated with this collator
-     * @stable ICU 2.8
-     */
-    public VersionInfo getUCAVersion() {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Returns the locale that was used to create this object, or null.
-     * This may may differ from the locale requested at the time of
-     * this object's creation.  For example, if an object is created
-     * for locale <tt>en_US_CALIFORNIA</tt>, the actual data may be
-     * drawn from <tt>en</tt> (the <i>actual</i> locale), and
-     * <tt>en_US</tt> may be the most specific locale that exists (the
-     * <i>valid</i> locale).
-     *
-     * <p>Note: This method will be implemented in ICU 3.0; ICU 2.8
-     * contains a partial preview implementation.  The * <i>actual</i>
-     * locale is returned correctly, but the <i>valid</i> locale is
-     * not, in most cases.
-     * @param type type of information requested, either {@link
-     * com.ibm.icu.util.ULocale#VALID_LOCALE} or {@link
-     * com.ibm.icu.util.ULocale#ACTUAL_LOCALE}.
-     * @return the information specified by <i>type</i>, or null if
-     * this object was not constructed from locale data.
-     * @see com.ibm.icu.util.ULocale
-     * @see com.ibm.icu.util.ULocale#VALID_LOCALE
-     * @see com.ibm.icu.util.ULocale#ACTUAL_LOCALE
-     * @draft ICU 2.8 (retain)
-     * @provisional This API might change or be removed in a future release.
-     */
-    public final ULocale getLocale(ULocale.Type type) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    // com.ibm.icu.base specific overrides
-    public String toString() {
-        return collator.toString();
-    }
-
-    public boolean equals(Object rhs) {
-        try {
-            return collator.equals(((Collator)rhs).collator);
-        }
-        catch (Exception e) {
-            return false;
-        }
-    }
-
-    public int hashCode() {
-        return collator.hashCode();
-    }
-}
+/**
+*******************************************************************************
+* Copyright (C) 1996-2011, International Business Machines Corporation and    *
+* others. All Rights Reserved.                                                *
+*******************************************************************************
+*/
+package com.ibm.icu.text;
+
+import java.util.Comparator;
+import java.util.Locale;
+import java.util.Set;
+
+import com.ibm.icu.util.ULocale;
+import com.ibm.icu.util.VersionInfo;
+
+/**
+* {@icuenhanced java.text.Collator}.{@icu _usage_}
+*
+* <p>Collator performs locale-sensitive string comparison. A concrete
+* subclass, RuleBasedCollator, allows customization of the collation
+* ordering by the use of rule sets.</p>
+*
+* <p>Following the <a href=http://www.unicode.org>Unicode
+* Consortium</a>'s specifications for the
+* <a href="http://www.unicode.org/unicode/reports/tr10/">Unicode Collation
+* Algorithm (UCA)</a>, there are 5 different levels of strength used
+* in comparisons:
+*
+* <ul>
+* <li>PRIMARY strength: Typically, this is used to denote differences between
+*     base characters (for example, "a" &lt; "b").
+*     It is the strongest difference. For example, dictionaries are divided
+*     into different sections by base character.
+* <li>SECONDARY strength: Accents in the characters are considered secondary
+*     differences (for example, "as" &lt; "&agrave;s" &lt; "at"). Other
+*     differences
+*     between letters can also be considered secondary differences, depending
+*     on the language. A secondary difference is ignored when there is a
+*     primary difference anywhere in the strings.
+* <li>TERTIARY strength: Upper and lower case differences in characters are
+*     distinguished at tertiary strength (for example, "ao" &lt; "Ao" &lt;
+*     "a&ograve;"). In addition, a variant of a letter differs from the base
+*     form on the tertiary strength (such as "A" and "&#9398;"). Another
+*     example is the
+*     difference between large and small Kana. A tertiary difference is ignored
+*     when there is a primary or secondary difference anywhere in the strings.
+* <li>QUATERNARY strength: When punctuation is ignored
+*     <a href="http://www.icu-project.org/userguide/Collate_Concepts.html#Ignoring_Punctuation">
+*     (see Ignoring Punctuations in the user guide)</a> at PRIMARY to TERTIARY
+*     strength, an additional strength level can
+*     be used to distinguish words with and without punctuation (for example,
+*     "ab" &lt; "a-b" &lt; "aB").
+*     This difference is ignored when there is a PRIMARY, SECONDARY or TERTIARY
+*     difference. The QUATERNARY strength should only be used if ignoring
+*     punctuation is required.
+* <li>IDENTICAL strength:
+*     When all other strengths are equal, the IDENTICAL strength is used as a
+*     tiebreaker. The Unicode code point values of the NFD form of each string
+*     are compared, just in case there is no difference.
+*     For example, Hebrew cantellation marks are only distinguished at this
+*     strength. This strength should be used sparingly, as only code point
+*     value differences between two strings is an extremely rare occurrence.
+*     Using this strength substantially decreases the performance for both
+*     comparison and collation key generation APIs. This strength also
+*     increases the size of the collation key.
+* </ul>
+*
+* Unlike the JDK, ICU4J's Collator deals only with 2 decomposition modes,
+* the canonical decomposition mode and one that does not use any decomposition.
+* The compatibility decomposition mode, java.text.Collator.FULL_DECOMPOSITION
+* is not supported here. If the canonical
+* decomposition mode is set, the Collator handles un-normalized text properly,
+* producing the same results as if the text were normalized in NFD. If
+* canonical decomposition is turned off, it is the user's responsibility to
+* ensure that all text is already in the appropriate form before performing
+* a comparison or before getting a CollationKey.</p>
+*
+* <p>For more information about the collation service see the
+* <a href="http://www.icu-project.org/userguide/Collate_Intro.html">users
+* guide</a>.</p>
+*
+* <p>Examples of use
+* <pre>
+* // Get the Collator for US English and set its strength to PRIMARY
+* Collator usCollator = Collator.getInstance(Locale.US);
+* usCollator.setStrength(Collator.PRIMARY);
+* if (usCollator.compare("abc", "ABC") == 0) {
+*     System.out.println("Strings are equivalent");
+* }
+*
+* The following example shows how to compare two strings using the
+* Collator for the default locale.
+*
+* // Compare two strings in the default locale
+* Collator myCollator = Collator.getInstance();
+* myCollator.setDecomposition(NO_DECOMPOSITION);
+* if (myCollator.compare("&agrave;&#92;u0325", "a&#92;u0325&#768;") != 0) {
+*     System.out.println("&agrave;&#92;u0325 is not equals to a&#92;u0325&#768; without decomposition");
+*     myCollator.setDecomposition(CANONICAL_DECOMPOSITION);
+*     if (myCollator.compare("&agrave;&#92;u0325", "a&#92;u0325&#768;") != 0) {
+*         System.out.println("Error: &agrave;&#92;u0325 should be equals to a&#92;u0325&#768; with decomposition");
+*     }
+*     else {
+*         System.out.println("&agrave;&#92;u0325 is equals to a&#92;u0325&#768; with decomposition");
+*     }
+* }
+* else {
+*     System.out.println("Error: &agrave;&#92;u0325 should be not equals to a&#92;u0325&#768; without decomposition");
+* }
+* </pre>
+* </p>
+* @see RuleBasedCollator
+* @see CollationKey
+* @author Syn Wee Quek
+* @stable ICU 2.8
+*/
+public class Collator implements Comparator<Object>, Cloneable
+{
+    /**
+     * @internal
+     */
+    private final java.text.Collator collator;
+
+    /**
+     * @internal
+     */
+    private Collator(java.text.Collator delegate) {
+        this.collator = delegate;
+    }
+
+    /**
+     * Create a collator with a null delegate.
+     * For use by possible subclassers.  This is present since
+     * the original Collator is abstract, and so, in theory
+     * subclassable.  All member APIs must be overridden.
+     */
+    protected Collator() {
+        this.collator = null;
+    }
+
+    // public data members ---------------------------------------------------
+
+    /**
+     * Strongest collator strength value. Typically used to denote differences
+     * between base characters. See class documentation for more explanation.
+     * @see #setStrength
+     * @see #getStrength
+     * @stable ICU 2.8
+     */
+    public final static int PRIMARY = java.text.Collator.PRIMARY;
+
+    /**
+     * Second level collator strength value.
+     * Accents in the characters are considered secondary differences.
+     * Other differences between letters can also be considered secondary
+     * differences, depending on the language.
+     * See class documentation for more explanation.
+     * @see #setStrength
+     * @see #getStrength
+     * @stable ICU 2.8
+     */
+    public final static int SECONDARY = java.text.Collator.SECONDARY;
+
+    /**
+     * Third level collator strength value.
+     * Upper and lower case differences in characters are distinguished at this
+     * strength level. In addition, a variant of a letter differs from the base
+     * form on the tertiary level.
+     * See class documentation for more explanation.
+     * @see #setStrength
+     * @see #getStrength
+     * @stable ICU 2.8
+     */
+    public final static int TERTIARY = java.text.Collator.TERTIARY;
+
+    /**
+     * {@icu} Fourth level collator strength value.
+     * When punctuation is ignored
+     * <a href="http://www.icu-project.org/userguide/Collate_Concepts.html#Ignoring_Punctuation">
+     * (see Ignoring Punctuations in the user guide)</a> at PRIMARY to TERTIARY
+     * strength, an additional strength level can
+     * be used to distinguish words with and without punctuation.
+     * See class documentation for more explanation.
+     * @see #setStrength
+     * @see #getStrength
+     * @stable ICU 2.8
+     */
+    public final static int QUATERNARY = java.text.Collator.IDENTICAL;
+
+    /**
+     * Smallest Collator strength value. When all other strengths are equal,
+     * the IDENTICAL strength is used as a tiebreaker. The Unicode code point
+     * values of the NFD form of each string are compared, just in case there
+     * is no difference.
+     * See class documentation for more explanation.
+     * </p>
+     * <p>
+     * Note this value is different from JDK's
+     * </p>
+     * @stable ICU 2.8
+     */
+    public final static int IDENTICAL = java.text.Collator.FULL_DECOMPOSITION;
+
+    /**
+     * {@icunote} This is for backwards compatibility with Java APIs only.  It
+     * should not be used, IDENTICAL should be used instead.  ICU's
+     * collation does not support Java's FULL_DECOMPOSITION mode.
+     * @stable ICU 3.4
+     */
+    public final static int FULL_DECOMPOSITION = java.text.Collator.FULL_DECOMPOSITION;
+
+    /**
+     * Decomposition mode value. With NO_DECOMPOSITION set, Strings
+     * will not be decomposed for collation. This is the default
+     * decomposition setting unless otherwise specified by the locale
+     * used to create the Collator.</p>
+     *
+     * <p><strong>Note</strong> this value is different from the JDK's.</p>
+     * @see #CANONICAL_DECOMPOSITION
+     * @see #getDecomposition
+     * @see #setDecomposition
+     * @stable ICU 2.8
+     */
+    public final static int NO_DECOMPOSITION = java.text.Collator.NO_DECOMPOSITION;
+
+    /**
+     * Decomposition mode value. With CANONICAL_DECOMPOSITION set,
+     * characters that are canonical variants according to the Unicode standard
+     * will be decomposed for collation.</p>
+     *
+     * <p>CANONICAL_DECOMPOSITION corresponds to Normalization Form D as
+     * described in <a href="http://www.unicode.org/unicode/reports/tr15/">
+     * Unicode Technical Report #15</a>.
+     * </p>
+     * @see #NO_DECOMPOSITION
+     * @see #getDecomposition
+     * @see #setDecomposition
+     * @stable ICU 2.8
+     */
+    public final static int CANONICAL_DECOMPOSITION = java.text.Collator.CANONICAL_DECOMPOSITION;
+
+    // public methods --------------------------------------------------------
+
+    // public setters --------------------------------------------------------
+
+    /**
+     * Sets this Collator's strength property. The strength property
+     * determines the minimum level of difference considered significant
+     * during comparison.</p>
+     *
+     * <p>The default strength for the Collator is TERTIARY, unless specified
+     * otherwise by the locale used to create the Collator.</p>
+     *
+     * <p>See the Collator class description for an example of use.</p>
+     * @param newStrength the new strength value.
+     * @see #getStrength
+     * @see #PRIMARY
+     * @see #SECONDARY
+     * @see #TERTIARY
+     * @see #QUATERNARY
+     * @see #IDENTICAL
+     * @throws IllegalArgumentException if the new strength value is not one
+     *                of PRIMARY, SECONDARY, TERTIARY, QUATERNARY or IDENTICAL.
+     * @stable ICU 2.8
+     */
+    public void setStrength(int newStrength)
+    {
+        collator.setStrength(newStrength);
+    }
+
+    /**
+     * Sets the decomposition mode of this Collator.  Setting this
+     * decomposition property with CANONICAL_DECOMPOSITION allows the
+     * Collator to handle un-normalized text properly, producing the
+     * same results as if the text were normalized. If
+     * NO_DECOMPOSITION is set, it is the user's responsibility to
+     * insure that all text is already in the appropriate form before
+     * a comparison or before getting a CollationKey. Adjusting
+     * decomposition mode allows the user to select between faster and
+     * more complete collation behavior.</p>
+     *
+     * <p>Since a great many of the world's languages do not require
+     * text normalization, most locales set NO_DECOMPOSITION as the
+     * default decomposition mode.</p>
+     *
+     * The default decompositon mode for the Collator is
+     * NO_DECOMPOSITON, unless specified otherwise by the locale used
+     * to create the Collator.</p>
+     *
+     * <p>See getDecomposition for a description of decomposition
+     * mode.</p>
+     *
+     * @param decomposition the new decomposition mode
+     * @see #getDecomposition
+     * @see #NO_DECOMPOSITION
+     * @see #CANONICAL_DECOMPOSITION
+     * @throws IllegalArgumentException If the given value is not a valid
+     *            decomposition mode.
+     * @stable ICU 2.8
+     */
+    public void setDecomposition(int decomposition)
+    {
+        collator.setDecomposition(decomposition);
+    }
+
+    // public getters --------------------------------------------------------
+
+    /**
+     * Returns the Collator for the current default locale.
+     * The default locale is determined by java.util.Locale.getDefault().
+     * @return the Collator for the default locale (for example, en_US) if it
+     *         is created successfully. Otherwise if there is no Collator
+     *         associated with the current locale, the default UCA collator
+     *         will be returned.
+     * @see java.util.Locale#getDefault()
+     * @see #getInstance(Locale)
+     * @stable ICU 2.8
+     */
+    public static final Collator getInstance()
+    {
+        return new Collator(java.text.Collator.getInstance());
+    }
+
+    /**
+     * Clones the collator.
+     * @stable ICU 2.6
+     * @return a clone of this collator.
+     */
+    public Object clone() throws CloneNotSupportedException {
+        return new Collator((java.text.Collator)collator.clone());
+    }
+
+    // begin registry stuff
+
+    /**
+     * A factory used with registerFactory to register multiple collators and provide
+     * display names for them.  If standard locale display names are sufficient,
+     * Collator instances may be registered instead.
+     * <p><b>Note:</b> as of ICU4J 3.2, the default API for CollatorFactory uses
+     * ULocale instead of Locale.  Instead of overriding createCollator(Locale),
+     * new implementations should override createCollator(ULocale).  Note that
+     * one of these two methods <b>MUST</b> be overridden or else an infinite
+     * loop will occur.
+     * @stable ICU 2.6
+     */
+    public static abstract class CollatorFactory {
+        /**
+         * Return true if this factory will be visible.  Default is true.
+         * If not visible, the locales supported by this factory will not
+         * be listed by getAvailableLocales.
+         *
+         * @return true if this factory is visible
+         * @stable ICU 2.6
+         */
+        public boolean visible() {
+            return true;
+        }
+
+        /**
+         * Return an instance of the appropriate collator.  If the locale
+         * is not supported, return null.
+         * <b>Note:</b> as of ICU4J 3.2, implementations should override
+         * this method instead of createCollator(Locale).
+         * @param loc the locale for which this collator is to be created.
+         * @return the newly created collator.
+         * @stable ICU 3.2
+         */
+        public Collator createCollator(ULocale loc) {
+            return createCollator(loc.toLocale());
+        }
+
+        /**
+         * Return an instance of the appropriate collator.  If the locale
+         * is not supported, return null.
+         * <p><b>Note:</b> as of ICU4J 3.2, implementations should override
+         * createCollator(ULocale) instead of this method, and inherit this
+         * method's implementation.  This method is no longer abstract
+         * and instead delegates to createCollator(ULocale).
+         * @param loc the locale for which this collator is to be created.
+         * @return the newly created collator.
+         * @stable ICU 2.6
+         */
+         public Collator createCollator(Locale loc) {
+            return createCollator(ULocale.forLocale(loc));
+        }
+
+        /**
+         * Return the name of the collator for the objectLocale, localized for the displayLocale.
+         * If objectLocale is not visible or not defined by the factory, return null.
+         * @param objectLocale the locale identifying the collator
+         * @param displayLocale the locale for which the display name of the collator should be localized
+         * @return the display name
+         * @stable ICU 2.6
+         */
+        public String getDisplayName(Locale objectLocale, Locale displayLocale) {
+            return getDisplayName(ULocale.forLocale(objectLocale), ULocale.forLocale(displayLocale));
+        }
+
+        /**
+         * Return the name of the collator for the objectLocale, localized for the displayLocale.
+         * If objectLocale is not visible or not defined by the factory, return null.
+         * @param objectLocale the locale identifying the collator
+         * @param displayLocale the locale for which the display name of the collator should be localized
+         * @return the display name
+         * @stable ICU 3.2
+         */
+        public String getDisplayName(ULocale objectLocale, ULocale displayLocale) {
+            if (visible()) {
+                Set<String> supported = getSupportedLocaleIDs();
+                String name = objectLocale.getBaseName();
+                if (supported.contains(name)) {
+                    return objectLocale.getDisplayName(displayLocale);
+                }
+            }
+            return null;
+        }
+
+        /**
+         * Return an unmodifiable collection of the locale names directly
+         * supported by this factory.
+         *
+         * @return the set of supported locale IDs.
+         * @stable ICU 2.6
+         */
+        public abstract Set<String> getSupportedLocaleIDs();
+
+        /**
+         * Empty default constructor.
+         * @stable ICU 2.6
+         */
+        protected CollatorFactory() {
+        }
+    }
+
+    /**
+     * {@icu} Returns the Collator for the desired locale.
+     * @param locale the desired locale.
+     * @return Collator for the desired locale if it is created successfully.
+     *         Otherwise if there is no Collator
+     *         associated with the current locale, a default UCA collator will
+     *         be returned.
+     * @see java.util.Locale
+     * @see java.util.ResourceBundle
+     * @see #getInstance(Locale)
+     * @see #getInstance()
+     * @stable ICU 3.0
+     */
+    public static final Collator getInstance(ULocale locale) {
+        return getInstance(locale.toLocale());
+    }
+
+    /**
+     * Returns the Collator for the desired locale.
+     * @param locale the desired locale.
+     * @return Collator for the desired locale if it is created successfully.
+     *         Otherwise if there is no Collator
+     *         associated with the current locale, a default UCA collator will
+     *         be returned.
+     * @see java.util.Locale
+     * @see java.util.ResourceBundle
+     * @see #getInstance(ULocale)
+     * @see #getInstance()
+     * @stable ICU 2.8
+     */
+    public static final Collator getInstance(Locale locale) {
+        return new Collator(java.text.Collator.getInstance(locale));
+    }
+
+    /**
+     * {@icu} Registers a collator as the default collator for the provided locale.  The
+     * collator should not be modified after it is registered.
+     *
+     * @param collator the collator to register
+     * @param locale the locale for which this is the default collator
+     * @return an object that can be used to unregister the registered collator.
+     *
+     * @stable ICU 3.2
+     */
+    public static final Object registerInstance(Collator collator, ULocale locale) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Registers a collator factory.
+     *
+     * @param factory the factory to register
+     * @return an object that can be used to unregister the registered factory.
+     *
+     * @stable ICU 2.6
+     */
+    public static final Object registerFactory(CollatorFactory factory) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Unregisters a collator previously registered using registerInstance.
+     * @param registryKey the object previously returned by registerInstance.
+     * @return true if the collator was successfully unregistered.
+     * @stable ICU 2.6
+     */
+    public static final boolean unregister(Object registryKey) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Returns the set of locales, as Locale objects, for which collators
+     * are installed.  Note that Locale objects do not support RFC 3066.
+     * @return the list of locales in which collators are installed.
+     * This list includes any that have been registered, in addition to
+     * those that are installed with ICU4J.
+     * @stable ICU 2.4
+     */
+    public static Locale[] getAvailableLocales() {
+        return java.text.Collator.getAvailableLocales();
+    }
+
+    /**
+     * {@icu} Returns the set of locales, as ULocale objects, for which collators
+     * are installed.  ULocale objects support RFC 3066.
+     * @return the list of locales in which collators are installed.
+     * This list includes any that have been registered, in addition to
+     * those that are installed with ICU4J.
+     * @stable ICU 3.0
+     */
+    public static final ULocale[] getAvailableULocales() {
+        Locale[] locales = java.text.Collator.getAvailableLocales();
+        ULocale[] ulocales = new ULocale[locales.length];
+        for (int i = 0; i < locales.length; ++i) {
+            ulocales[i] = ULocale.forLocale(locales[i]);
+        }
+        return ulocales;
+    }
+
+    /**
+     * {@icu} Returns an array of all possible keywords that are relevant to
+     * collation. At this point, the only recognized keyword for this
+     * service is "collation".
+     * @return an array of valid collation keywords.
+     * @see #getKeywordValues
+     * @stable ICU 3.0
+     */
+    public static final String[] getKeywords() {
+        // No keywords support in com.ibm.icu.base
+        return new String[0];
+    }
+
+    /**
+     * {@icu} Given a keyword, returns an array of all values for
+     * that keyword that are currently in use.
+     * @param keyword one of the keywords returned by getKeywords.
+     * @see #getKeywords
+     * @stable ICU 3.0
+     */
+    public static final String[] getKeywordValues(String keyword) {
+        // No keywords support in com.ibm.icu.base
+        return new String[0];
+    }
+
+    /**
+     * {@icu} Given a key and a locale, returns an array of string values in a preferred
+     * order that would make a difference. These are all and only those values where
+     * the open (creation) of the service with the locale formed from the input locale
+     * plus input keyword and that value has different behavior than creation with the
+     * input locale alone.
+     * @param key           one of the keys supported by this service.  For now, only
+     *                      "collation" is supported.
+     * @param locale        the locale
+     * @param commonlyUsed  if set to true it will return only commonly used values
+     *                      with the given locale in preferred order.  Otherwise,
+     *                      it will return all the available values for the locale.
+     * @return an array of string values for the given key and the locale.
+     * @stable ICU 4.2
+     */
+    public static final String[] getKeywordValuesForLocale(String key, ULocale locale, 
+                                                           boolean commonlyUsed) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Returns the functionally equivalent locale for the given
+     * requested locale, with respect to given keyword, for the
+     * collation service.  If two locales return the same result, then
+     * collators instantiated for these locales will behave
+     * equivalently.  The converse is not always true; two collators
+     * may in fact be equivalent, but return different results, due to
+     * internal details.  The return result has no other meaning than
+     * that stated above, and implies nothing as to the relationship
+     * between the two locales.  This is intended for use by
+     * applications who wish to cache collators, or otherwise reuse
+     * collators when possible.  The functional equivalent may change
+     * over time.  For more information, please see the <a
+     * href="http://www.icu-project.org/userguide/locale.html#services">
+     * Locales and Services</a> section of the ICU User Guide.
+     * @param keyword a particular keyword as enumerated by
+     * getKeywords.
+     * @param locID The requested locale
+     * @param isAvailable If non-null, isAvailable[0] will receive and
+     * output boolean that indicates whether the requested locale was
+     * 'available' to the collation service. If non-null, isAvailable
+     * must have length >= 1.
+     * @return the locale
+     * @stable ICU 3.0
+     */
+    public static final ULocale getFunctionalEquivalent(String keyword,
+                                                        ULocale locID,
+                                                        boolean isAvailable[]) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Returns the functionally equivalent locale for the given
+     * requested locale, with respect to given keyword, for the
+     * collation service.
+     * @param keyword a particular keyword as enumerated by
+     * getKeywords.
+     * @param locID The requested locale
+     * @return the locale
+     * @see #getFunctionalEquivalent(String,ULocale,boolean[])
+     * @stable ICU 3.0
+     */
+    public static final ULocale getFunctionalEquivalent(String keyword,
+                                                        ULocale locID) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Returns the name of the collator for the objectLocale, localized for the
+     * displayLocale.
+     * @param objectLocale the locale of the collator
+     * @param displayLocale the locale for the collator's display name
+     * @return the display name
+     * @stable ICU 2.6
+     */
+    static public String getDisplayName(Locale objectLocale, Locale displayLocale) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Returns the name of the collator for the objectLocale, localized for the
+     * displayLocale.
+     * @param objectLocale the locale of the collator
+     * @param displayLocale the locale for the collator's display name
+     * @return the display name
+     * @stable ICU 3.2
+     */
+    static public String getDisplayName(ULocale objectLocale, ULocale displayLocale) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Returns the name of the collator for the objectLocale, localized for the
+     * current locale.
+     * @param objectLocale the locale of the collator
+     * @return the display name
+     * @stable ICU 2.6
+     */
+    static public String getDisplayName(Locale objectLocale) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Returns the name of the collator for the objectLocale, localized for the
+     * current locale.
+     * @param objectLocale the locale of the collator
+     * @return the display name
+     * @stable ICU 3.2
+     */
+    static public String getDisplayName(ULocale objectLocale) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Returns this Collator's strength property. The strength property
+     * determines the minimum level of difference considered significant.
+     * </p>
+     * {@icunote} This can return QUATERNARY strength, which is not supported by the
+     * JDK version.
+     * <p>
+     * See the Collator class description for more details.
+     * </p>
+     * @return this Collator's current strength property.
+     * @see #setStrength
+     * @see #PRIMARY
+     * @see #SECONDARY
+     * @see #TERTIARY
+     * @see #QUATERNARY
+     * @see #IDENTICAL
+     * @stable ICU 2.8
+     */
+    public int getStrength()
+    {
+        return collator.getStrength();
+    }
+
+    /**
+     * Returns the decomposition mode of this Collator. The decomposition mode
+     * determines how Unicode composed characters are handled.
+     * </p>
+     * <p>
+     * See the Collator class description for more details.
+     * </p>
+     * @return the decomposition mode
+     * @see #setDecomposition
+     * @see #NO_DECOMPOSITION
+     * @see #CANONICAL_DECOMPOSITION
+     * @stable ICU 2.8
+     */
+    public int getDecomposition()
+    {
+        return collator.getDecomposition();
+    }
+
+    // public other methods -------------------------------------------------
+
+    /**
+     * Compares the equality of two text Strings using
+     * this Collator's rules, strength and decomposition mode.  Convenience method.
+     * @param source the source string to be compared.
+     * @param target the target string to be compared.
+     * @return true if the strings are equal according to the collation
+     *         rules, otherwise false.
+     * @see #compare
+     * @throws NullPointerException thrown if either arguments is null.
+     * @stable ICU 2.8
+     */
+    public boolean equals(String source, String target)
+    {
+        return (compare(source, target) == 0);
+    }
+
+    /**
+     * {@icu} Returns a UnicodeSet that contains all the characters and sequences tailored
+     * in this collator.
+     * @return a pointer to a UnicodeSet object containing all the
+     *         code points and sequences that may sort differently than
+     *         in the UCA.
+     * @stable ICU 2.4
+     */
+    public UnicodeSet getTailoredSet()
+    {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Compares the source text String to the target text String according to
+     * this Collator's rules, strength and decomposition mode.
+     * Returns an integer less than,
+     * equal to or greater than zero depending on whether the source String is
+     * less than, equal to or greater than the target String. See the Collator
+     * class description for an example of use.
+     * </p>
+     * @param source the source String.
+     * @param target the target String.
+     * @return Returns an integer value. Value is less than zero if source is
+     *         less than target, value is zero if source and target are equal,
+     *         value is greater than zero if source is greater than target.
+     * @see CollationKey
+     * @see #getCollationKey
+     * @throws NullPointerException thrown if either argument is null.
+     * @stable ICU 2.8
+     */
+    public int compare(String source, String target) {
+        return collator.compare(source, target);
+    }
+
+    /**
+     * Compares the source Object to the target Object.
+     * </p>
+     * @param source the source Object.
+     * @param target the target Object.
+     * @return Returns an integer value. Value is less than zero if source is
+     *         less than target, value is zero if source and target are equal,
+     *         value is greater than zero if source is greater than target.
+     * @throws ClassCastException thrown if either arguments cannot be cast to String.
+     * @stable ICU 4.2
+     */
+    public int compare(Object source, Object target) {
+        return compare((String)source, (String)target);
+    }
+
+    /**
+     * <p>
+     * Transforms the String into a CollationKey suitable for efficient
+     * repeated comparison.  The resulting key depends on the collator's
+     * rules, strength and decomposition mode.
+     * </p>
+     * <p>See the CollationKey class documentation for more information.</p>
+     * @param source the string to be transformed into a CollationKey.
+     * @return the CollationKey for the given String based on this Collator's
+     *         collation rules. If the source String is null, a null
+     *         CollationKey is returned.
+     * @see CollationKey
+     * @see #compare(String, String)
+     * @see #getRawCollationKey
+     * @stable ICU 2.8
+     */
+    public CollationKey getCollationKey(String source) {
+        return new CollationKey(collator.getCollationKey(source));
+    }
+
+    /**
+     * {@icu} Returns the simpler form of a CollationKey for the String source following
+     * the rules of this Collator and stores the result into the user provided argument
+     * key.  If key has a internal byte array of length that's too small for the result,
+     * the internal byte array will be grown to the exact required size.
+     * @param source the text String to be transformed into a RawCollationKey
+     * @return If key is null, a new instance of RawCollationKey will be
+     *         created and returned, otherwise the user provided key will be
+     *         returned.
+     * @see #compare(String, String)
+     * @see #getCollationKey
+     * @see RawCollationKey
+     * @stable ICU 2.8
+     */
+    public RawCollationKey getRawCollationKey(String source, RawCollationKey key) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Variable top is a two byte primary value which causes all the codepoints
+     * with primary values that are less or equal than the variable top to be
+     * shifted when alternate handling is set to SHIFTED.
+     * </p>
+     * <p>
+     * Sets the variable top to a collation element value of a string supplied.
+     * </p>
+     * @param varTop one or more (if contraction) characters to which the
+     *               variable top should be set
+     * @return a int value containing the value of the variable top in upper 16
+     *         bits. Lower 16 bits are undefined.
+     * @throws IllegalArgumentException is thrown if varTop argument is not
+     *            a valid variable top element. A variable top element is
+     *            invalid when it is a contraction that does not exist in the
+     *            Collation order or when the PRIMARY strength collation
+     *            element for the variable top has more than two bytes
+     * @see #getVariableTop
+     * @see RuleBasedCollator#setAlternateHandlingShifted
+     * @stable ICU 2.6
+     */
+    public int setVariableTop(String varTop) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Returns the variable top value of a Collator.
+     * Lower 16 bits are undefined and should be ignored.
+     * @return the variable top value of a Collator.
+     * @see #setVariableTop
+     * @stable ICU 2.6
+     */
+    public int getVariableTop() {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Sets the variable top to a collation element value supplied.
+     * Variable top is set to the upper 16 bits.
+     * Lower 16 bits are ignored.
+     * @param varTop Collation element value, as returned by setVariableTop or
+     *               getVariableTop
+     * @see #getVariableTop
+     * @see #setVariableTop
+     * @stable ICU 2.6
+     */
+    public void setVariableTop(int varTop) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Returns the version of this collator object.
+     * @return the version object associated with this collator
+     * @stable ICU 2.8
+     */
+    public VersionInfo getVersion() {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Returns the UCA version of this collator object.
+     * @return the version object associated with this collator
+     * @stable ICU 2.8
+     */
+    public VersionInfo getUCAVersion() {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Returns the locale that was used to create this object, or null.
+     * This may may differ from the locale requested at the time of
+     * this object's creation.  For example, if an object is created
+     * for locale <tt>en_US_CALIFORNIA</tt>, the actual data may be
+     * drawn from <tt>en</tt> (the <i>actual</i> locale), and
+     * <tt>en_US</tt> may be the most specific locale that exists (the
+     * <i>valid</i> locale).
+     *
+     * <p>Note: This method will be implemented in ICU 3.0; ICU 2.8
+     * contains a partial preview implementation.  The * <i>actual</i>
+     * locale is returned correctly, but the <i>valid</i> locale is
+     * not, in most cases.
+     * @param type type of information requested, either {@link
+     * com.ibm.icu.util.ULocale#VALID_LOCALE} or {@link
+     * com.ibm.icu.util.ULocale#ACTUAL_LOCALE}.
+     * @return the information specified by <i>type</i>, or null if
+     * this object was not constructed from locale data.
+     * @see com.ibm.icu.util.ULocale
+     * @see com.ibm.icu.util.ULocale#VALID_LOCALE
+     * @see com.ibm.icu.util.ULocale#ACTUAL_LOCALE
+     * @draft ICU 2.8 (retain)
+     * @provisional This API might change or be removed in a future release.
+     */
+    public final ULocale getLocale(ULocale.Type type) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    // com.ibm.icu.base specific overrides
+    public String toString() {
+        return collator.toString();
+    }
+
+    public boolean equals(Object rhs) {
+        try {
+            return collator.equals(((Collator)rhs).collator);
+        }
+        catch (Exception e) {
+            return false;
+        }
+    }
+
+    public int hashCode() {
+        return collator.hashCode();
+    }
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/CurrencyPluralInfo.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/CurrencyPluralInfo.java
index 39f1fd1..40289fd 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/CurrencyPluralInfo.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/CurrencyPluralInfo.java
@@ -1,14 +1,14 @@
-/*
- *******************************************************************************
- * Copyright (C) 2011, International Business Machines Corporation and         *
- * others. All Rights Reserved.                                                *
- *******************************************************************************
- */
-package com.ibm.icu.text;
-
-/*
- * Empty stub
- */
-public class CurrencyPluralInfo {
-    private CurrencyPluralInfo() {}
-}
+/*
+ *******************************************************************************
+ * Copyright (C) 2011, International Business Machines Corporation and         *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+package com.ibm.icu.text;
+
+/*
+ * Empty stub
+ */
+public class CurrencyPluralInfo {
+    private CurrencyPluralInfo() {}
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/DateFormat.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/DateFormat.java
index 686d1dd..14d0c9a 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/DateFormat.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/DateFormat.java
@@ -1,1949 +1,1950 @@
-/*
- *   Copyright (C) 1996-2011, International Business Machines
- *   Corporation and others.  All Rights Reserved.
- */
-
-package com.ibm.icu.text;
-
-import java.io.InvalidObjectException;
-import java.text.FieldPosition;
-import java.text.Format;
-import java.text.ParseException;
-import java.text.ParsePosition;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.Map;
-
-import com.ibm.icu.util.Calendar;
-import com.ibm.icu.util.TimeZone;
-import com.ibm.icu.util.ULocale;
-
-/**
- * {@icuenhanced java.text.DateFormat}.{@icu _usage_}
- *
- * <p>DateFormat is an abstract class for date/time formatting subclasses which
- * formats and parses dates or time in a language-independent manner.
- * The date/time formatting subclass, such as SimpleDateFormat, allows for
- * formatting (i.e., date -> text), parsing (text -> date), and
- * normalization.  The date is represented as a <code>Date</code> object or
- * as the milliseconds since January 1, 1970, 00:00:00 GMT.
- *
- * <p>DateFormat provides many class methods for obtaining default date/time
- * formatters based on the default or a given locale and a number of formatting
- * styles. The formatting styles include FULL, LONG, MEDIUM, and SHORT. More
- * detail and examples of using these styles are provided in the method
- * descriptions.
- *
- * <p>DateFormat helps you to format and parse dates for any locale.
- * Your code can be completely independent of the locale conventions for
- * months, days of the week, or even the calendar format: lunar vs. solar.
- *
- * <p>To format a date for the current Locale, use one of the
- * static factory methods:
- * <pre>
- *  myString = DateFormat.getDateInstance().format(myDate);
- * </pre>
- * <p>If you are formatting multiple numbers, it is
- * more efficient to get the format and use it multiple times so that
- * the system doesn't have to fetch the information about the local
- * language and country conventions multiple times.
- * <pre>
- *  DateFormat df = DateFormat.getDateInstance();
- *  for (int i = 0; i < a.length; ++i) {
- *    output.println(df.format(myDate[i]) + "; ");
- *  }
- * </pre>
- * <p>To format a number for a different Locale, specify it in the
- * call to getDateInstance().
- * <pre>
- *  DateFormat df = DateFormat.getDateInstance(DateFormat.LONG, Locale.FRANCE);
- * </pre>
- * <p>You can use a DateFormat to parse also.
- * <pre>
- *  myDate = df.parse(myString);
- * </pre>
- * <p>Use getDateInstance to get the normal date format for that country.
- * There are other static factory methods available.
- * Use getTimeInstance to get the time format for that country.
- * Use getDateTimeInstance to get a date and time format. You can pass in
- * different options to these factory methods to control the length of the
- * result; from SHORT to MEDIUM to LONG to FULL. The exact result depends
- * on the locale, but generally:
- * <ul><li>SHORT is completely numeric, such as 12.13.52 or 3:30pm
- * <li>MEDIUM is longer, such as Jan 12, 1952
- * <li>LONG is longer, such as January 12, 1952 or 3:30:32pm
- * <li>FULL is pretty completely specified, such as
- * Tuesday, April 12, 1952 AD or 3:30:42pm PST.
- * </ul>
- *
- * <p>You can also set the time zone on the format if you wish.
- * If you want even more control over the format or parsing,
- * (or want to give your users more control),
- * you can try casting the DateFormat you get from the factory methods
- * to a SimpleDateFormat. This will work for the majority
- * of countries; just remember to put it in a try block in case you
- * encounter an unusual one.
- *
- * <p>You can also use forms of the parse and format methods with
- * ParsePosition and FieldPosition to
- * allow you to
- * <ul><li>progressively parse through pieces of a string.
- * <li>align any particular field, or find out where it is for selection
- * on the screen.
- * </ul>
- *
- * <h4>Synchronization</h4>
- *
- * Date formats are not synchronized. It is recommended to create separate
- * format instances for each thread. If multiple threads access a format
- * concurrently, it must be synchronized externally.
- *
- * @see          UFormat
- * @see          NumberFormat
- * @see          SimpleDateFormat
- * @see          com.ibm.icu.util.Calendar
- * @see          com.ibm.icu.util.GregorianCalendar
- * @see          com.ibm.icu.util.TimeZone
- * @author       Mark Davis, Chen-Lieh Huang, Alan Liu
- * @stable ICU 2.0
- */
-public class DateFormat extends Format {
-
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * @internal
-     */
-    public final java.text.DateFormat dateFormat;
-        
-    /**
-     * @internal
-     * @param delegate the DateFormat to which to delegate
-     */
-    public DateFormat(java.text.DateFormat delegate) {
-        this.dateFormat = delegate;
-    }
-    
-    /**
-     * For subclass use.  Subclasses will generally not
-     * work correctly unless they manipulate the delegate.
-     */
-    protected DateFormat() {
-        this.dateFormat = java.text.DateFormat.getInstance();
-    }
-
-    /**
-     * FieldPosition selector for 'G' field alignment,
-     * corresponding to the {@link Calendar#ERA} field.
-     * @stable ICU 2.0
-     */
-    public final static int ERA_FIELD = 0;
-
-    /**
-     * FieldPosition selector for 'y' field alignment,
-     * corresponding to the {@link Calendar#YEAR} field.
-     * @stable ICU 2.0
-     */
-    public final static int YEAR_FIELD = 1;
-
-    /**
-     * FieldPosition selector for 'M' field alignment,
-     * corresponding to the {@link Calendar#MONTH} field.
-     * @stable ICU 2.0
-     */
-    public final static int MONTH_FIELD = 2;
-
-    /**
-     * FieldPosition selector for 'd' field alignment,
-     * corresponding to the {@link Calendar#DATE} field.
-     * @stable ICU 2.0
-     */
-    public final static int DATE_FIELD = 3;
-
-    /**
-     * FieldPosition selector for 'k' field alignment,
-     * corresponding to the {@link Calendar#HOUR_OF_DAY} field.
-     * HOUR_OF_DAY1_FIELD is used for the one-based 24-hour clock.
-     * For example, 23:59 + 01:00 results in 24:59.
-     * @stable ICU 2.0
-     */
-    public final static int HOUR_OF_DAY1_FIELD = 4;
-
-    /**
-     * FieldPosition selector for 'H' field alignment,
-     * corresponding to the {@link Calendar#HOUR_OF_DAY} field.
-     * HOUR_OF_DAY0_FIELD is used for the zero-based 24-hour clock.
-     * For example, 23:59 + 01:00 results in 00:59.
-     * @stable ICU 2.0
-     */
-    public final static int HOUR_OF_DAY0_FIELD = 5;
-
-    /**
-     * FieldPosition selector for 'm' field alignment,
-     * corresponding to the {@link Calendar#MINUTE} field.
-     * @stable ICU 2.0
-     */
-    public final static int MINUTE_FIELD = 6;
-
-    /**
-     * FieldPosition selector for 's' field alignment,
-     * corresponding to the {@link Calendar#SECOND} field.
-     * @stable ICU 2.0
-     */
-    public final static int SECOND_FIELD = 7;
-
-    /**
-     * {@icu} FieldPosition selector for 'S' field alignment,
-     * corresponding to the {@link Calendar#MILLISECOND} field.
-     * @stable ICU 3.0
-     */
-    public final static int FRACTIONAL_SECOND_FIELD = 8;
-
-    /**
-     * Alias for FRACTIONAL_SECOND_FIELD.
-     * @deprecated ICU 3.0 use FRACTIONAL_SECOND_FIELD.
-     */
-    public final static int MILLISECOND_FIELD = FRACTIONAL_SECOND_FIELD;
-
-    /**
-     * FieldPosition selector for 'E' field alignment,
-     * corresponding to the {@link Calendar#DAY_OF_WEEK} field.
-     * @stable ICU 2.0
-     */
-    public final static int DAY_OF_WEEK_FIELD = 9;
-
-    /**
-     * FieldPosition selector for 'D' field alignment,
-     * corresponding to the {@link Calendar#DAY_OF_YEAR} field.
-     * @stable ICU 2.0
-     */
-    public final static int DAY_OF_YEAR_FIELD = 10;
-
-    /**
-     * FieldPosition selector for 'F' field alignment,
-     * corresponding to the {@link Calendar#DAY_OF_WEEK_IN_MONTH} field.
-     * @stable ICU 2.0
-     */
-    public final static int DAY_OF_WEEK_IN_MONTH_FIELD = 11;
-
-    /**
-     * FieldPosition selector for 'w' field alignment,
-     * corresponding to the {@link Calendar#WEEK_OF_YEAR} field.
-     * @stable ICU 2.0
-     */
-    public final static int WEEK_OF_YEAR_FIELD = 12;
-
-    /**
-     * FieldPosition selector for 'W' field alignment,
-     * corresponding to the {@link Calendar#WEEK_OF_MONTH} field.
-     * @stable ICU 2.0
-     */
-    public final static int WEEK_OF_MONTH_FIELD = 13;
-
-    /**
-     * FieldPosition selector for 'a' field alignment,
-     * corresponding to the {@link Calendar#AM_PM} field.
-     * @stable ICU 2.0
-     */
-    public final static int AM_PM_FIELD = 14;
-
-    /**
-     * FieldPosition selector for 'h' field alignment,
-     * corresponding to the {@link Calendar#HOUR} field.
-     * HOUR1_FIELD is used for the one-based 12-hour clock.
-     * For example, 11:30 PM + 1 hour results in 12:30 AM.
-     * @stable ICU 2.0
-     */
-    public final static int HOUR1_FIELD = 15;
-
-    /**
-     * FieldPosition selector for 'K' field alignment,
-     * corresponding to the {@link Calendar#HOUR} field.
-     * HOUR0_FIELD is used for the zero-based 12-hour clock.
-     * For example, 11:30 PM + 1 hour results in 00:30 AM.
-     * @stable ICU 2.0
-     */
-    public final static int HOUR0_FIELD = 16;
-
-    /**
-     * FieldPosition selector for 'z' field alignment,
-     * corresponding to the {@link Calendar#ZONE_OFFSET} and
-     * {@link Calendar#DST_OFFSET} fields.
-     * @stable ICU 2.0
-     */
-    public final static int TIMEZONE_FIELD = 17;
-
-    /**
-     * {@icu} FieldPosition selector for 'Y' field alignment,
-     * corresponding to the {@link Calendar#YEAR_WOY} field.
-     * @stable ICU 3.0
-     */
-    public final static int YEAR_WOY_FIELD = 18;
-
-    /**
-     * {@icu} FieldPosition selector for 'e' field alignment,
-     * corresponding to the {@link Calendar#DOW_LOCAL} field.
-     * @stable ICU 3.0
-     */
-    public final static int DOW_LOCAL_FIELD = 19;
-
-    /**
-     * {@icu} FieldPosition selector for 'u' field alignment,
-     * corresponding to the {@link Calendar#EXTENDED_YEAR} field.
-     * @stable ICU 3.0
-     */
-    public final static int EXTENDED_YEAR_FIELD = 20;
-
-    /**
-     * {@icu} FieldPosition selector for 'g' field alignment,
-     * corresponding to the {@link Calendar#JULIAN_DAY} field.
-     * @stable ICU 3.0
-     */
-    public final static int JULIAN_DAY_FIELD = 21;
-
-    /**
-     * {@icu} FieldPosition selector for 'A' field alignment,
-     * corresponding to the {@link Calendar#MILLISECONDS_IN_DAY} field.
-     * @stable ICU 3.0
-     */
-    public final static int MILLISECONDS_IN_DAY_FIELD = 22;
-
-    /**
-     * {@icu} FieldPosition selector for 'Z' field alignment,
-     * corresponding to the {@link Calendar#ZONE_OFFSET} and
-     * {@link Calendar#DST_OFFSET} fields.
-     * @stable ICU 3.0
-     */
-    public final static int TIMEZONE_RFC_FIELD = 23;
-
-    /**
-     * {@icu} FieldPosition selector for 'v' field alignment,
-     * corresponding to the {@link Calendar#ZONE_OFFSET} and
-     * {@link Calendar#DST_OFFSET} fields.  This displays the generic zone
-     * name, if available.
-     * @stable ICU 3.4
-     */
-    public final static int TIMEZONE_GENERIC_FIELD = 24;
-
-    /**
-     * {@icu} FieldPosition selector for 'c' field alignment,
-     * corresponding to the {@link Calendar#DAY_OF_WEEK} field.
-     * This displays the stand alone day name, if available.
-     * @stable ICU 3.4
-     */
-    public final static int STANDALONE_DAY_FIELD = 25;
-
-    /**
-     * {@icu} FieldPosition selector for 'L' field alignment,
-     * corresponding to the {@link Calendar#MONTH} field.
-     * This displays the stand alone month name, if available.
-     * @stable ICU 3.4
-     */
-    public final static int STANDALONE_MONTH_FIELD = 26;
-
-    /**
-     * {@icu} FieldPosition selector for 'Q' field alignment,
-     * corresponding to the {@link Calendar#MONTH} field.
-     * This displays the quarter.
-     * @stable ICU 3.6
-     */
-    public final static int QUARTER_FIELD = 27;
-
-    /**
-     * {@icu} FieldPosition selector for 'q' field alignment,
-     * corresponding to the {@link Calendar#MONTH} field.
-     * This displays the stand alone quarter, if available.
-     * @stable ICU 3.6
-     */
-    public final static int STANDALONE_QUARTER_FIELD = 28;
-
-    /**
-     * {@icu} FieldPosition selector for 'V' field alignment,
-     * corresponding to the {@link Calendar#ZONE_OFFSET} and
-     * {@link Calendar#DST_OFFSET} fields.  This displays the fallback timezone
-     * name when VVVV is specified, and the short standard or daylight
-     * timezone name ignoring commonlyUsed when a single V is specified.
-     * @stable ICU 3.8
-     */
-    public final static int TIMEZONE_SPECIAL_FIELD = 29;
-
-    /**
-     * {@icu} Number of FieldPosition selectors for DateFormat.
-     * Valid selectors range from 0 to FIELD_COUNT-1.
-     * @stable ICU 3.0
-     */
-    public final static int FIELD_COUNT = 30; // must == DateFormatSymbols.patternChars.length()
-
-    /**
-     * Formats a time object into a time string. Examples of time objects
-     * are a time value expressed in milliseconds and a Date object.
-     * @param obj must be a Number or a Date or a Calendar.
-     * @param toAppendTo the string buffer for the returning time string.
-     * @return the formatted time string.
-     * @param fieldPosition keeps track of the position of the field
-     * within the returned string.
-     * On input: an alignment field,
-     * if desired. On output: the offsets of the alignment field. For
-     * example, given a time text "1996.07.10 AD at 15:08:56 PDT",
-     * if the given fieldPosition is DateFormat.YEAR_FIELD, the
-     * begin index and end index of fieldPosition will be set to
-     * 0 and 4, respectively.
-     * Notice that if the same time field appears
-     * more than once in a pattern, the fieldPosition will be set for the first
-     * occurrence of that time field. For instance, formatting a Date to
-     * the time string "1 PM PDT (Pacific Daylight Time)" using the pattern
-     * "h a z (zzzz)" and the alignment field DateFormat.TIMEZONE_FIELD,
-     * the begin index and end index of fieldPosition will be set to
-     * 5 and 8, respectively, for the first occurrence of the timezone
-     * pattern character 'z'.
-     * @see java.text.Format
-     * @stable ICU 2.0
-     */
-    public final StringBuffer format(Object obj, StringBuffer toAppendTo,
-                                     FieldPosition fieldPosition)
-    {
-        if (obj instanceof Calendar) {
-            return format((Calendar)obj, toAppendTo, fieldPosition);
-        } else if (obj instanceof Date) {
-            return format((Date)obj, toAppendTo, fieldPosition);
-        } else if (obj instanceof Number) {
-            return format(new Date(((Number)obj).longValue()), toAppendTo, fieldPosition );
-        }
-
-        throw new IllegalArgumentException("Cannot format given Object (" +
-                                               obj.getClass().getName() + ") as a Date");
-    }
-
-    /**
-     * Formats a date into a date/time string.
-     * @param cal a Calendar set to the date and time to be formatted
-     * into a date/time string.  When the calendar type is different from
-     * the internal calendar held by this DateFormat instance, the date
-     * and the time zone will be inherited from the input calendar, but
-     * other calendar field values will be calculated by the internal calendar.
-     * @param toAppendTo the string buffer for the returning date/time string.
-     * @param fieldPosition keeps track of the position of the field
-     * within the returned string.
-     * On input: an alignment field,
-     * if desired. On output: the offsets of the alignment field. For
-     * example, given a time text "1996.07.10 AD at 15:08:56 PDT",
-     * if the given fieldPosition is DateFormat.YEAR_FIELD, the
-     * begin index and end index of fieldPosition will be set to
-     * 0 and 4, respectively.
-     * Notice that if the same time field appears
-     * more than once in a pattern, the fieldPosition will be set for the first
-     * occurrence of that time field. For instance, formatting a Date to
-     * the time string "1 PM PDT (Pacific Daylight Time)" using the pattern
-     * "h a z (zzzz)" and the alignment field DateFormat.TIMEZONE_FIELD,
-     * the begin index and end index of fieldPosition will be set to
-     * 5 and 8, respectively, for the first occurrence of the timezone
-     * pattern character 'z'.
-     * @return the formatted date/time string.
-     * @stable ICU 2.0
-     */
-    public StringBuffer format(Calendar cal, StringBuffer toAppendTo,
-                                        FieldPosition fieldPosition) {
-        return format(cal.getTime(), toAppendTo, fieldPosition);
-    }
-
-    /**
-     * Formats a Date into a date/time string.
-     * @param date a Date to be formatted into a date/time string.
-     * @param toAppendTo the string buffer for the returning date/time string.
-     * @param fieldPosition keeps track of the position of the field
-     * within the returned string.
-     * On input: an alignment field,
-     * if desired. On output: the offsets of the alignment field. For
-     * example, given a time text "1996.07.10 AD at 15:08:56 PDT",
-     * if the given fieldPosition is DateFormat.YEAR_FIELD, the
-     * begin index and end index of fieldPosition will be set to
-     * 0 and 4, respectively.
-     * Notice that if the same time field appears
-     * more than once in a pattern, the fieldPosition will be set for the first
-     * occurrence of that time field. For instance, formatting a Date to
-     * the time string "1 PM PDT (Pacific Daylight Time)" using the pattern
-     * "h a z (zzzz)" and the alignment field DateFormat.TIMEZONE_FIELD,
-     * the begin index and end index of fieldPosition will be set to
-     * 5 and 8, respectively, for the first occurrence of the timezone
-     * pattern character 'z'.
-     * @return the formatted date/time string.
-     * @stable ICU 2.0
-     */
-    public StringBuffer format(Date date, StringBuffer toAppendTo,
-                                     FieldPosition fieldPosition) {
-        FieldPosition jdkPos = toJDKFieldPosition(fieldPosition);
-        StringBuffer buf = dateFormat.format(date, toAppendTo, jdkPos);
-        if (jdkPos != null) {
-            fieldPosition.setBeginIndex(jdkPos.getBeginIndex());
-            fieldPosition.setEndIndex(jdkPos.getEndIndex());
-        }
-        return buf;
-    }
-
-    /**
-     * Formats a Date into a date/time string.
-     * @param date the time value to be formatted into a time string.
-     * @return the formatted time string.
-     * @stable ICU 2.0
-     */
-    public final String format(Date date)
-    {
-        return dateFormat.format(date);
-    }
-
-    /**
-     * Parses a date/time string.
-     *
-     * @param text  The date/time string to be parsed
-     *
-     * @return      A Date, or null if the input could not be parsed
-     *
-     * @exception  ParseException  If the given string cannot be parsed as a date.
-     *
-     * @see #parse(String, ParsePosition)
-     * @stable ICU 2.0
-     */
-    public Date parse(String text) throws ParseException
-    {
-        return dateFormat.parse(text);
-    }
-
-    /**
-     * Parses a date/time string according to the given parse position.
-     * For example, a time text "07/10/96 4:5 PM, PDT" will be parsed
-     * into a Calendar that is equivalent to Date(837039928046).  The
-     * caller should clear the calendar before calling this method,
-     * unless existing field information is to be kept.
-     *
-     * <p> By default, parsing is lenient: If the input is not in the form used
-     * by this object's format method but can still be parsed as a date, then
-     * the parse succeeds.  Clients may insist on strict adherence to the
-     * format by calling setLenient(false).
-     *
-     * @see #setLenient(boolean)
-     *
-     * @param text  The date/time string to be parsed
-     *
-     * @param cal   The calendar into which parsed data will be stored.
-     *              In general, this should be cleared before calling this
-     *              method.  If this parse fails, the calendar may still
-     *              have been modified.  When the calendar type is different
-     *              from the internal calendar held by this DateFormat
-     *              instance, calendar field values will be parsed based
-     *              on the internal calendar initialized with the time and
-     *              the time zone taken from this calendar, then the
-     *              parse result (time in milliseconds and time zone) will
-     *              be set back to this calendar.
-     *
-     * @param pos   On input, the position at which to start parsing; on
-     *              output, the position at which parsing terminated, or the
-     *              start position if the parse failed.
-     * @stable ICU 2.0
-     */
-    public void parse(String text, Calendar cal, ParsePosition pos) {
-        Date result = dateFormat.parse(text, pos);
-        cal.setTime(result);
-    }
-
-    /**
-     * Parses a date/time string according to the given parse position.  For
-     * example, a time text "07/10/96 4:5 PM, PDT" will be parsed into a Date
-     * that is equivalent to Date(837039928046).
-     *
-     * <p> By default, parsing is lenient: If the input is not in the form used
-     * by this object's format method but can still be parsed as a date, then
-     * the parse succeeds.  Clients may insist on strict adherence to the
-     * format by calling setLenient(false).
-     *
-     * @see #setLenient(boolean)
-     *
-     * @param text  The date/time string to be parsed
-     *
-     * @param pos   On input, the position at which to start parsing; on
-     *              output, the position at which parsing terminated, or the
-     *              start position if the parse failed.
-     *
-     * @return      A Date, or null if the input could not be parsed
-     * @stable ICU 2.0
-     */
-    public Date parse(String text, ParsePosition pos) {
-        return dateFormat.parse(text, pos);
-    }
-
-    /**
-     * Parses a date/time string into an Object.  This convenience method simply
-     * calls parse(String, ParsePosition).
-     *
-     * @see #parse(String, ParsePosition)
-     * @stable ICU 2.0
-     */
-    public Object parseObject (String source, ParsePosition pos)
-    {
-        return parse(source, pos);
-    }
-
-    /**
-     * {@icu} Constant for empty style pattern.
-     * @stable ICU 3.8
-     */
-    public static final int NONE = -1;
-
-    /**
-     * Constant for full style pattern.
-     * @stable ICU 2.0
-     */
-    public static final int FULL = 0;
-
-    /**
-     * Constant for long style pattern.
-     * @stable ICU 2.0
-     */
-    public static final int LONG = 1;
-
-    /**
-     * Constant for medium style pattern.
-     * @stable ICU 2.0
-     */
-    public static final int MEDIUM = 2;
-
-    /**
-     * Constant for short style pattern.
-     * @stable ICU 2.0
-     */
-    public static final int SHORT = 3;
-
-    /**
-     * Constant for default style pattern.  Its value is MEDIUM.
-     * @stable ICU 2.0
-     */
-    public static final int DEFAULT = MEDIUM;
-
-    /**
-     * {@icu} Constant for relative style mask.
-     * @stable ICU 3.8
-     */
-    public static final int RELATIVE = (1 << 7);
-
-    /**
-     * {@icu} Constant for relative full style pattern.
-     * @stable ICU 3.8
-     */
-    public static final int RELATIVE_FULL = RELATIVE | FULL;
-
-    /**
-     * {@icu} Constant for relative style pattern.
-     * @stable ICU 3.8
-     */
-    public static final int RELATIVE_LONG = RELATIVE | LONG;
-
-    /**
-     * {@icu} Constant for relative style pattern.
-     * @stable ICU 3.8
-     */
-    public static final int RELATIVE_MEDIUM = RELATIVE | MEDIUM;
-
-    /**
-     * {@icu} Constant for relative style pattern.
-     * @stable ICU 3.8
-     */
-    public static final int RELATIVE_SHORT = RELATIVE | SHORT;
-
-    /**
-     * {@icu} Constant for relative default style pattern.
-     * @stable ICU 3.8
-     */
-    public static final int RELATIVE_DEFAULT = RELATIVE | DEFAULT;
-
-    /* Below are pre-defined skeletons
-     *
-     * <P>
-     * A skeleton
-     * <ul>
-     * <li>
-     * 1. only keeps the field pattern letter and ignores all other parts
-     *    in a pattern, such as space, punctuations, and string literals.
-     * <li>
-     * 2. hides the order of fields.
-     * <li>
-     * 3. might hide a field's pattern letter length.
-     *
-     *    For those non-digit calendar fields, the pattern letter length is
-     *    important, such as MMM, MMMM, and MMMMM; E and EEEE,
-     *    and the field's pattern letter length is honored.
-     *
-     *    For the digit calendar fields,  such as M or MM, d or dd, yy or yyyy,
-     *    the field pattern length is ignored and the best match, which is
-     *    defined in date time patterns, will be returned without honor
-     *    the field pattern letter length in skeleton.
-     * </ul>
-     */
-    /**
-     * {@icu} Constant for date pattern with minute and second.
-     * @stable ICU 4.0
-     */
-    public static final String MINUTE_SECOND = "ms";
-
-    /**
-     * {@icu} Constant for date pattern with hour and minute in 24-hour presentation.
-     * @stable ICU 4.0
-     */
-    public static final String HOUR24_MINUTE = "Hm";
-
-    /**
-     * {@icu} Constant for date pattern with hour, minute, and second in
-     * 24-hour presentation.
-     * @stable ICU 4.0
-     */
-    public static final String HOUR24_MINUTE_SECOND = "Hms";
-
-    /**
-     * {@icu} Constant for date pattern with hour, minute, and second.
-     * @stable ICU 4.0
-     */
-    public static final String HOUR_MINUTE_SECOND = "hms";
-
-    /**
-     * {@icu} Constant for date pattern with standalone month.
-     * @stable ICU 4.0
-     */
-    public static final String STANDALONE_MONTH = "LLLL";
-
-    /**
-     * {@icu} Constant for date pattern with standalone abbreviated month.
-     * @stable ICU 4.0
-     */
-    public static final String ABBR_STANDALONE_MONTH = "LLL";
-
-    /**
-     * {@icu} Constant for date pattern with year and quarter.
-     * @stable ICU 4.0
-     */
-    public static final String YEAR_QUARTER = "yQQQ";
-
-    /**
-     * {@icu} Constant for date pattern with year and abbreviated quarter.
-     * @stable ICU 4.0
-     */
-    public static final String YEAR_ABBR_QUARTER = "yQ";
-
-
-    /* Below are skeletons that date interval pre-defined in resource file.
-     * Users are encouraged to use them in date interval format factory methods.
-     */
-    /**
-     * {@icu} Constant for date pattern with hour and minute.
-     * @stable ICU 4.0
-     */
-    public static final String HOUR_MINUTE = "hm";
-
-    /**
-     * {@icu} Constant for date pattern with year.
-     * @stable ICU 4.0
-     */
-    public static final String YEAR = "y";
-
-    /**
-     * {@icu} Constant for date pattern with day.
-     * @stable ICU 4.0
-     */
-    public static final String DAY = "d";
-
-    /**
-     * {@icu} Constant for date pattern with numeric month, weekday, and day.
-     * @stable ICU 4.0
-     */
-    public static final String NUM_MONTH_WEEKDAY_DAY = "MEd";
-
-    /**
-     * {@icu} Constant for date pattern with year and numeric month.
-     * @stable ICU 4.0
-     */
-    public static final String YEAR_NUM_MONTH = "yM";
-
-    /**
-     * {@icu} Constant for date pattern with numeric month and day.
-     * @stable ICU 4.0
-     */
-    public static final String NUM_MONTH_DAY = "Md";
-
-    /**
-     * {@icu} Constant for date pattern with year, numeric month, weekday, and day.
-     * @stable ICU 4.0
-     */
-    public static final String YEAR_NUM_MONTH_WEEKDAY_DAY = "yMEd";
-
-    /**
-     * {@icu} Constant for date pattern with abbreviated month, weekday, and day.
-     * @stable ICU 4.0
-     */
-    public static final String ABBR_MONTH_WEEKDAY_DAY = "MMMEd";
-
-    /**
-     * {@icu} Constant for date pattern with year and month.
-     * @stable ICU 4.0
-     */
-    public static final String YEAR_MONTH = "yMMMM";
-
-    /**
-     * {@icu} Constant for date pattern with year and abbreviated month.
-     * @stable ICU 4.0
-     */
-    public static final String YEAR_ABBR_MONTH = "yMMM";
-
-    /**
-     * {@icu} Constant for date pattern having month and day.
-     * @stable ICU 4.0
-     */
-    public static final String MONTH_DAY = "MMMMd";
-
-    /**
-     * {@icu} Constant for date pattern with abbreviated month and day.
-     * @stable ICU 4.0
-     */
-    public static final String ABBR_MONTH_DAY = "MMMd";
-
-    /**
-     * {@icu} Constant for date pattern with month, weekday, and day.
-     * @stable ICU 4.0
-     */
-    public static final String MONTH_WEEKDAY_DAY = "MMMMEEEEd";
-
-    /**
-     * {@icu} Constant for date pattern with year, abbreviated month, weekday,
-     * and day.
-     * @stable ICU 4.0
-     */
-    public static final String YEAR_ABBR_MONTH_WEEKDAY_DAY = "yMMMEd";
-
-    /**
-     * {@icu} Constant for date pattern with year, month, weekday, and day.
-     * @stable ICU 4.0
-     */
-    public static final String YEAR_MONTH_WEEKDAY_DAY = "yMMMMEEEEd";
-
-    /**
-     * {@icu} Constant for date pattern with year, month, and day.
-     * @stable ICU 4.0
-     */
-    public static final String YEAR_MONTH_DAY = "yMMMMd";
-
-    /**
-     * {@icu} Constant for date pattern with year, abbreviated month, and day.
-     * @stable ICU 4.0
-     */
-    public static final String YEAR_ABBR_MONTH_DAY = "yMMMd";
-
-    /**
-     * {@icu} Constant for date pattern with year, numeric month, and day.
-     * @stable ICU 4.0
-     */
-    public static final String YEAR_NUM_MONTH_DAY = "yMd";
-
-    /**
-     * {@icu} Constant for date pattern with numeric month.
-     * @stable ICU 4.0
-     */
-    public static final String NUM_MONTH = "M";
-
-    /**
-     * {@icu} Constant for date pattern with abbreviated month.
-     * @stable ICU 4.0
-     */
-    public static final String ABBR_MONTH = "MMM";
-
-    /**
-     * {@icu} Constant for date pattern with month.
-     * @stable ICU 4.0
-     */
-    public static final String MONTH = "MMMM";
-
-    /**
-     * {@icu} Constant for date pattern with hour, minute, and generic timezone.
-     * @stable ICU 4.0
-     */
-    public static final String HOUR_MINUTE_GENERIC_TZ = "hmv";
-
-    /**
-     * {@icu} Constant for date pattern with hour, minute, and timezone.
-     * @stable ICU 4.0
-     */
-    public static final String HOUR_MINUTE_TZ = "hmz";
-
-    /**
-     * {@icu} Constant for date pattern with hour.
-     * @stable ICU 4.0
-     */
-    public static final String HOUR = "h";
-
-    /**
-     * {@icu} Constant for date pattern with hour and generic timezone.
-     * @stable ICU 4.0
-     */
-    public static final String HOUR_GENERIC_TZ = "hv";
-
-    /**
-     * {@icu} Constant for date pattern with hour and timezone.
-     * @stable ICU 4.0
-     */
-    public static final String HOUR_TZ = "hz";
-
-    /**
-     * Gets the time formatter with the default formatting style
-     * for the default locale.
-     * @return a time formatter.
-     * @stable ICU 2.0
-     */
-    public final static DateFormat getTimeInstance()
-    {
-        return new DateFormat(java.text.DateFormat.getTimeInstance());
-    }
-
-    /**
-     * Returns the time formatter with the given formatting style
-     * for the default locale.
-     * @param style the given formatting style. For example,
-     * SHORT for "h:mm a" in the US locale.
-     * @return a time formatter.
-     * @stable ICU 2.0
-     */
-    public final static DateFormat getTimeInstance(int style)
-    {
-        return new DateFormat(java.text.DateFormat.getTimeInstance(getJDKFormatStyle(style)));
-    }
-
-    /**
-     * Returns the time formatter with the given formatting style
-     * for the given locale.
-     * @param style the given formatting style. For example,
-     * SHORT for "h:mm a" in the US locale.
-     * @param aLocale the given locale.
-     * @return a time formatter.
-     * @stable ICU 2.0
-     */
-    public final static DateFormat getTimeInstance(int style,
-                                                 Locale aLocale)
-    {
-        return new DateFormat(java.text.DateFormat.getTimeInstance(getJDKFormatStyle(style), aLocale));
-    }
-
-    /**
-     * Returns the time formatter with the given formatting style
-     * for the given locale.
-     * @param style the given formatting style. For example,
-     * SHORT for "h:mm a" in the US locale.
-     * @param locale the given ulocale.
-     * @return a time formatter.
-     * @stable ICU 3.2
-     */
-    public final static DateFormat getTimeInstance(int style,
-                                                 ULocale locale)
-    {
-        return new DateFormat(java.text.DateFormat.getTimeInstance(getJDKFormatStyle(style), locale.toLocale()));
-    }
-
-    /**
-     * Returns the date formatter with the default formatting style
-     * for the default locale.
-     * @return a date formatter.
-     * @stable ICU 2.0
-     */
-    public final static DateFormat getDateInstance()
-    {
-        return new DateFormat(java.text.DateFormat.getDateInstance());
-    }
-
-    /**
-     * Returns the date formatter with the given formatting style
-     * for the default locale.
-     * @param style the given formatting style. For example,
-     * SHORT for "M/d/yy" in the US locale.
-     * @return a date formatter.
-     * @stable ICU 2.0
-     */
-    public final static DateFormat getDateInstance(int style)
-    {
-        return new DateFormat(java.text.DateFormat.getDateInstance(getJDKFormatStyle(style)));
-    }
-
-    /**
-     * Returns the date formatter with the given formatting style
-     * for the given locale.
-     * @param style the given formatting style. For example,
-     * SHORT for "M/d/yy" in the US locale.
-     * @param aLocale the given locale.
-     * @return a date formatter.
-     * @stable ICU 2.0
-     */
-    public final static DateFormat getDateInstance(int style,
-                                                 Locale aLocale)
-    {
-        return new DateFormat(java.text.DateFormat.getDateInstance(getJDKFormatStyle(style), aLocale));
-    }
-
-    /**
-     * Returns the date formatter with the given formatting style
-     * for the given locale.
-     * @param style the given formatting style. For example,
-     * SHORT for "M/d/yy" in the US locale.
-     * @param locale the given ulocale.
-     * @return a date formatter.
-     * @stable ICU 3.2
-     */
-    public final static DateFormat getDateInstance(int style,
-                                                 ULocale locale)
-    {
-        return new DateFormat(java.text.DateFormat.getDateInstance(getJDKFormatStyle(style), locale.toLocale()));
-    }
-
-    /**
-     * Returns the date/time formatter with the default formatting style
-     * for the default locale.
-     * @return a date/time formatter.
-     * @stable ICU 2.0
-     */
-    public final static DateFormat getDateTimeInstance()
-    {
-        return new DateFormat(java.text.DateFormat.getDateTimeInstance());
-    }
-
-    /**
-     * Returns the date/time formatter with the given date and time
-     * formatting styles for the default locale.
-     * @param dateStyle the given date formatting style. For example,
-     * SHORT for "M/d/yy" in the US locale.
-     * @param timeStyle the given time formatting style. For example,
-     * SHORT for "h:mm a" in the US locale.
-     * @return a date/time formatter.
-     * @stable ICU 2.0
-     */
-    public final static DateFormat getDateTimeInstance(int dateStyle,
-                                                       int timeStyle)
-    {
-        if (dateStyle != NONE) {
-            if (timeStyle != NONE) {
-                return new DateFormat(java.text.DateFormat.getDateTimeInstance(getJDKFormatStyle(dateStyle), getJDKFormatStyle(timeStyle)));
-            } else {
-                return new DateFormat(java.text.DateFormat.getDateInstance(getJDKFormatStyle(dateStyle)));
-            }
-        }
-        if (timeStyle != NONE) {
-            return new DateFormat(java.text.DateFormat.getTimeInstance(getJDKFormatStyle(timeStyle)));
-        }
-        return null;
-    }
-
-    /**
-     * Returns the date/time formatter with the given formatting styles
-     * for the given locale.
-     * @param dateStyle the given date formatting style.
-     * @param timeStyle the given time formatting style.
-     * @param aLocale the given locale.
-     * @return a date/time formatter.
-     * @stable ICU 2.0
-     */
-    public final static DateFormat getDateTimeInstance(
-        int dateStyle, int timeStyle, Locale aLocale)
-    {
-        if (dateStyle != NONE) {
-            if (timeStyle != NONE) {
-                return new DateFormat(java.text.DateFormat.getDateTimeInstance(getJDKFormatStyle(dateStyle), getJDKFormatStyle(timeStyle), aLocale));
-            } else {
-                return new DateFormat(java.text.DateFormat.getDateInstance(getJDKFormatStyle(dateStyle), aLocale));
-            }
-        }
-        if (timeStyle != NONE) {
-            return new DateFormat(java.text.DateFormat.getTimeInstance(getJDKFormatStyle(timeStyle), aLocale));
-        }
-        return null;
-    }
-
-    /**
-     * Returns the date/time formatter with the given formatting styles
-     * for the given locale.
-     * @param dateStyle the given date formatting style.
-     * @param timeStyle the given time formatting style.
-     * @param locale the given ulocale.
-     * @return a date/time formatter.
-     * @stable ICU 3.2
-     */
-    public final static DateFormat getDateTimeInstance(
-        int dateStyle, int timeStyle, ULocale locale)
-    {
-        if (dateStyle != NONE) {
-            if (timeStyle != NONE) {
-                return new DateFormat(java.text.DateFormat.getDateTimeInstance(getJDKFormatStyle(dateStyle), getJDKFormatStyle(timeStyle), locale.toLocale()));
-            } else {
-                return new DateFormat(java.text.DateFormat.getDateInstance(getJDKFormatStyle(dateStyle), locale.toLocale()));
-            }
-        }
-        if (timeStyle != NONE) {
-            return new DateFormat(java.text.DateFormat.getTimeInstance(getJDKFormatStyle(timeStyle), locale.toLocale()));
-        }
-        return null;
-    }
-
-    /**
-     * Returns a default date/time formatter that uses the SHORT style for both the
-     * date and the time.
-     * @stable ICU 2.0
-     */
-    public final static DateFormat getInstance() {
-        return new DateFormat(java.text.DateFormat.getInstance());
-    }
-
-    /**
-     * Returns the set of locales for which DateFormats are installed.
-     * @return the set of locales for which DateFormats are installed.
-     * @stable ICU 2.0
-     */
-    public static Locale[] getAvailableLocales()
-    {
-        return java.text.DateFormat.getAvailableLocales();
-    }
-
-    /**
-     * {@icu} Returns the set of locales for which DateFormats are installed.
-     * @return the set of locales for which DateFormats are installed.
-     * @draft ICU 3.2 (retain)
-     * @provisional This API might change or be removed in a future release.
-     */
-    public static ULocale[] getAvailableULocales()
-    {
-        if (availableULocales == null) {
-            synchronized(DateFormat.class) {
-                if (availableULocales == null) {
-                    Locale[] locales = java.text.DateFormat.getAvailableLocales();
-                    availableULocales = new ULocale[locales.length];
-                    for (int i = 0; i < locales.length; ++i) {
-                        availableULocales[i] = ULocale.forLocale(locales[i]);
-                    }
-                }
-            }
-        }
-        return availableULocales;
-    }
-    private static volatile ULocale[] availableULocales;
-
-    /**
-     * Sets the calendar to be used by this date format.  Initially, the default
-     * calendar for the specified or default locale is used.
-     * @param newCalendar the new Calendar to be used by the date format
-     * @stable ICU 2.0
-     */
-    public void setCalendar(Calendar newCalendar)
-    {
-        dateFormat.setCalendar(newCalendar.calendar);
-    }
-
-    /**
-     * Returns the calendar associated with this date/time formatter.
-     * @return the calendar associated with this date/time formatter.
-     * @stable ICU 2.0
-     */
-    public Calendar getCalendar()
-    {
-        return new Calendar(dateFormat.getCalendar());
-    }
-
-    /**
-     * Sets the number formatter.
-     * @param newNumberFormat the given new NumberFormat.
-     * @stable ICU 2.0
-     */
-    public void setNumberFormat(NumberFormat newNumberFormat)
-    {
-        dateFormat.setNumberFormat(newNumberFormat.numberFormat);
-    }
-
-    /**
-     * Returns the number formatter which this date/time formatter uses to
-     * format and parse a time.
-     * @return the number formatter which this date/time formatter uses.
-     * @stable ICU 2.0
-     */
-    public NumberFormat getNumberFormat()
-    {
-        return new NumberFormat(dateFormat.getNumberFormat());
-    }
-
-    /**
-     * Sets the time zone for the calendar of this DateFormat object.
-     * @param zone the given new time zone.
-     * @stable ICU 2.0
-     */
-    public void setTimeZone(TimeZone zone)
-    {
-        dateFormat.setTimeZone(zone.timeZone);
-    }
-
-    /**
-     * Returns the time zone.
-     * @return the time zone associated with the calendar of DateFormat.
-     * @stable ICU 2.0
-     */
-    public TimeZone getTimeZone()
-    {
-        return new TimeZone(dateFormat.getTimeZone());
-    }
-
-    /**
-     * Specifies whether date/time parsing is to be lenient.  With
-     * lenient parsing, the parser may use heuristics to interpret inputs that
-     * do not precisely match this object's format.  With strict parsing,
-     * inputs must match this object's format.
-     * @param lenient when true, parsing is lenient
-     * @see com.ibm.icu.util.Calendar#setLenient
-     * @stable ICU 2.0
-     */
-    public void setLenient(boolean lenient)
-    {
-        dateFormat.setLenient(lenient);
-    }
-
-    /**
-     * Returns whether date/time parsing is lenient.
-     * @stable ICU 2.0
-     */
-    public boolean isLenient()
-    {
-        return dateFormat.isLenient();
-    }
-
-    /**
-     * Overrides hashCode.
-     * @stable ICU 2.0
-     */
-    public int hashCode() {
-        return dateFormat.hashCode();
-    }
-
-    /**
-     * Overrides equals.
-     * @stable ICU 2.0
-     */
-    public boolean equals(Object obj) {
-        try {
-            return dateFormat.equals(((DateFormat)obj).dateFormat);
-        }
-        catch (Exception e) {
-            return false;
-        }
-    }
-
-    /**
-     * Overrides clone.
-     * @stable ICU 2.0
-     */
-    public Object clone()
-    {
-        return new DateFormat((java.text.DateFormat)dateFormat.clone());
-    }
-
-    //-------------------------------------------------------------------------
-    // Public static interface for creating custon DateFormats for different
-    // types of Calendars.
-    //-------------------------------------------------------------------------
-
-    /**
-     * Creates a {@link DateFormat} object that can be used to format dates in
-     * the calendar system specified by <code>cal</code>.
-     * <p>
-     * @param cal   The calendar system for which a date format is desired.
-     *
-     * @param dateStyle The type of date format desired.  This can be
-     *              {@link DateFormat#SHORT}, {@link DateFormat#MEDIUM},
-     *              etc.
-     *
-     * @param locale The locale for which the date format is desired.
-     * @stable ICU 2.0
-     */
-    static final public DateFormat getDateInstance(Calendar cal, int dateStyle, Locale locale)
-    {
-        DateFormat df = getDateInstance(dateStyle, locale);
-        df.setCalendar(cal);
-        return df;
-    }
-
-    /**
-     * Creates a {@link DateFormat} object that can be used to format dates in
-     * the calendar system specified by <code>cal</code>.
-     * <p>
-     * @param cal   The calendar system for which a date format is desired.
-     *
-     * @param dateStyle The type of date format desired.  This can be
-     *              {@link DateFormat#SHORT}, {@link DateFormat#MEDIUM},
-     *              etc.
-     *
-     * @param locale The locale for which the date format is desired.
-     * @stable ICU 3.2
-     */
-    static final public DateFormat getDateInstance(Calendar cal, int dateStyle, ULocale locale)
-    {
-        DateFormat df = getDateInstance(dateStyle, locale);
-        df.setCalendar(cal);
-        return df;
-    }
-
-    /**
-     * Creates a {@link DateFormat} object that can be used to format times in
-     * the calendar system specified by <code>cal</code>.
-     * <p>
-     * <b>Note:</b> When this functionality is moved into the core JDK, this method
-     * will probably be replaced by a new overload of {@link DateFormat#getInstance}.
-     * <p>
-     * @param cal   The calendar system for which a time format is desired.
-     *
-     * @param timeStyle The type of time format desired.  This can be
-     *              {@link DateFormat#SHORT}, {@link DateFormat#MEDIUM},
-     *              etc.
-     *
-     * @param locale The locale for which the time format is desired.
-     *
-     * @see DateFormat#getTimeInstance
-     * @stable ICU 2.0
-     */
-    static final public DateFormat getTimeInstance(Calendar cal, int timeStyle, Locale locale)
-    {
-        DateFormat df = getTimeInstance(timeStyle, locale);
-        df.setCalendar(cal);
-        return df;
-    }
-
-    /**
-     * Creates a {@link DateFormat} object that can be used to format times in
-     * the calendar system specified by <code>cal</code>.
-     * <p>
-     * <b>Note:</b> When this functionality is moved into the core JDK, this method
-     * will probably be replaced by a new overload of {@link DateFormat#getInstance}.
-     * <p>
-     * @param cal   The calendar system for which a time format is desired.
-     *
-     * @param timeStyle The type of time format desired.  This can be
-     *              {@link DateFormat#SHORT}, {@link DateFormat#MEDIUM},
-     *              etc.
-     *
-     * @param locale The locale for which the time format is desired.
-     *
-     * @see DateFormat#getTimeInstance
-     * @stable ICU 3.2
-     */
-    static final public DateFormat getTimeInstance(Calendar cal, int timeStyle, ULocale locale)
-    {
-        DateFormat df = getTimeInstance(timeStyle, locale);
-        df.setCalendar(cal);
-        return df;
-    }
-
-    /**
-     * Creates a {@link DateFormat} object that can be used to format dates and times in
-     * the calendar system specified by <code>cal</code>.
-     * <p>
-     * <b>Note:</b> When this functionality is moved into the core JDK, this method
-     * will probably be replaced by a new overload of {@link DateFormat#getInstance}.
-     * <p>
-     * @param cal   The calendar system for which a date/time format is desired.
-     *
-     * @param dateStyle The type of date format desired.  This can be
-     *              {@link DateFormat#SHORT}, {@link DateFormat#MEDIUM},
-     *              etc.
-     *
-     * @param timeStyle The type of time format desired.  This can be
-     *              {@link DateFormat#SHORT}, {@link DateFormat#MEDIUM},
-     *              etc.
-     *
-     * @param locale The locale for which the date/time format is desired.
-     *
-     * @see DateFormat#getDateTimeInstance
-     * @stable ICU 2.0
-     */
-    static final public DateFormat getDateTimeInstance(Calendar cal, int dateStyle,
-                                                 int timeStyle, Locale locale)
-    {
-        DateFormat df = getDateTimeInstance(dateStyle, timeStyle, locale);
-        df.setCalendar(cal);
-        return df;
-    }
-
-    /**
-     * Creates a {@link DateFormat} object that can be used to format dates and times in
-     * the calendar system specified by <code>cal</code>.
-     * <p>
-     * <b>Note:</b> When this functionality is moved into the core JDK, this method
-     * will probably be replaced by a new overload of {@link DateFormat#getInstance}.
-     * <p>
-     * @param cal   The calendar system for which a date/time format is desired.
-     *
-     * @param dateStyle The type of date format desired.  This can be
-     *              {@link DateFormat#SHORT}, {@link DateFormat#MEDIUM},
-     *              etc.
-     *
-     * @param timeStyle The type of time format desired.  This can be
-     *              {@link DateFormat#SHORT}, {@link DateFormat#MEDIUM},
-     *              etc.
-     *
-     * @param locale The locale for which the date/time format is desired.
-     *
-     * @see DateFormat#getDateTimeInstance
-     * @stable ICU 3.2
-     */
-    static final public DateFormat getDateTimeInstance(Calendar cal, int dateStyle,
-                                                 int timeStyle, ULocale locale)
-    {
-        DateFormat df = getDateTimeInstance(dateStyle, timeStyle, locale);
-        df.setCalendar(cal);
-        return df;
-    }
-
-    /**
-     * Convenience overload.
-     * @stable ICU 2.0
-     */
-    static final public DateFormat getInstance(Calendar cal, Locale locale) {
-        return getDateTimeInstance(cal, DateFormat.MEDIUM, DateFormat.SHORT, locale);
-    }
-
-    /**
-     * Convenience overload.
-     * @stable ICU 3.2
-     * @provisional This API might change or be removed in a future release.
-     */
-    static final public DateFormat getInstance(Calendar cal, ULocale locale) {
-        return getDateTimeInstance(cal, DateFormat.MEDIUM, DateFormat.SHORT, locale);
-    }
-
-    /**
-     * Convenience overload.
-     * @stable ICU 2.0
-     */
-    static final public DateFormat getInstance(Calendar cal) {
-        return getInstance(cal, ULocale.getDefault());
-    }
-
-    /**
-     * Convenience overload.
-     * @stable ICU 2.0
-     */
-    static final public DateFormat getDateInstance(Calendar cal, int dateStyle) {
-        return getDateInstance(cal, dateStyle, ULocale.getDefault());
-    }
-
-    /**
-     * Convenience overload.
-     * @stable ICU 2.0
-     */
-    static final public DateFormat getTimeInstance(Calendar cal, int timeStyle) {
-        return getTimeInstance(cal, timeStyle, ULocale.getDefault());
-    }
-
-    /**
-     * Convenience overload.
-     * @stable ICU 2.0
-     */
-    static final public DateFormat getDateTimeInstance(Calendar cal, int dateStyle, int timeStyle) {
-        return getDateTimeInstance(cal, dateStyle, timeStyle, ULocale.getDefault());
-    }
-
-    /**
-     * {@icu} Convenience overload.
-     * @stable ICU 4.0
-     */
-    public final static DateFormat getPatternInstance(String pattern) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Convenience overload.
-     * @stable ICU 4.0
-     */
-    public final static DateFormat getPatternInstance(String pattern, Locale locale) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Returns a {@link DateFormat} object that can be used to format dates and times in
-     * the given locale.
-     * <p>
-     * <b>Note:</b> When this functionality is moved into the core JDK, this method
-     * will probably be replaced by a new overload of {@link DateFormat#getInstance}.
-     * <p>
-     *
-     * @param pattern The pattern that selects the fields to be formatted. (Uses the
-     *              {@link DateTimePatternGenerator}.) This can be {@link DateFormat#ABBR_MONTH},
-     *              {@link DateFormat#MONTH_WEEKDAY_DAY}, etc.
-     *
-     * @param locale The locale for which the date/time format is desired.
-     *
-     * @stable ICU 4.0
-     */
-    public final static DateFormat getPatternInstance(String pattern, ULocale locale) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Convenience overload.
-     * @stable ICU 4.0
-     */
-    public final static DateFormat getPatternInstance(Calendar cal, String pattern, Locale locale) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Creates a {@link DateFormat} object that can be used to format dates and
-     * times in the calendar system specified by <code>cal</code>.
-     *
-     * <p><b>Note:</b> When this functionality is moved into the core JDK, this method
-     * will probably be replaced by a new overload of {@link DateFormat#getInstance}.
-     *
-     * @param cal   The calendar system for which a date/time format is desired.
-     *
-     * @param pattern The pattern that selects the fields to be formatted. (Uses the
-     *              {@link DateTimePatternGenerator}.)  This can be
-     *              {@link DateFormat#ABBR_MONTH}, {@link DateFormat#MONTH_WEEKDAY_DAY},
-     *              etc.
-     *
-     * @param locale The locale for which the date/time format is desired.
-     *
-     * @stable ICU 4.0
-     */
-    public final static DateFormat getPatternInstance(
-        Calendar cal, String pattern, ULocale locale) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * The instances of this inner class are used as attribute keys and values
-     * in AttributedCharacterIterator that
-     * DateFormat.formatToCharacterIterator() method returns.
-     *
-     * <p>There is no public constructor to this class, the only instances are the
-     * constants defined here.
-     * <p>
-     * @stable ICU 3.8
-     */
-    public static class Field extends Format.Field {
-
-        private static final long serialVersionUID = -3627456821000730829L;
-
-        // Max number of calendar fields
-        private static final int CAL_FIELD_COUNT;
-
-        // Table for mapping calendar field number to DateFormat.Field
-        private static final Field[] CAL_FIELDS;
-
-        // Map for resolving DateFormat.Field by name
-        private static final Map<String, Field> FIELD_NAME_MAP;
-
-        static {
-            Calendar cal = Calendar.getInstance();
-            CAL_FIELD_COUNT = cal.getFieldCount();
-            CAL_FIELDS = new Field[CAL_FIELD_COUNT];
-            FIELD_NAME_MAP = new HashMap<String, Field>(CAL_FIELD_COUNT);
-        }
-
-        // Java fields -------------------
-
-        /**
-         * Constant identifying the time of day indicator(am/pm).
-         * @stable ICU 3.8
-         */
-        public static final Field AM_PM = new Field("am pm", Calendar.AM_PM);
-
-        /**
-         * Constant identifying the day of month field.
-         * @stable ICU 3.8
-         */
-        public static final Field DAY_OF_MONTH = new Field("day of month", Calendar.DAY_OF_MONTH);
-
-        /**
-         * Constant identifying the day of week field.
-         * @stable ICU 3.8
-         */
-        public static final Field DAY_OF_WEEK = new Field("day of week", Calendar.DAY_OF_WEEK);
-
-        /**
-         * Constant identifying the day of week in month field.
-         * @stable ICU 3.8
-         */
-        public static final Field DAY_OF_WEEK_IN_MONTH =
-            new Field("day of week in month", Calendar.DAY_OF_WEEK_IN_MONTH);
-
-        /**
-         * Constant identifying the day of year field.
-         * @stable ICU 3.8
-         */
-        public static final Field DAY_OF_YEAR = new Field("day of year", Calendar.DAY_OF_YEAR);
-
-        /**
-         * Constant identifying the era field.
-         * @stable ICU 3.8
-         */
-        public static final Field ERA = new Field("era", Calendar.ERA);
-
-        /**
-         * Constant identifying the hour(0-23) of day field.
-         * @stable ICU 3.8
-         */
-        public static final Field HOUR_OF_DAY0 = new Field("hour of day", Calendar.HOUR_OF_DAY);
-
-        /**
-         * Constant identifying the hour(1-24) of day field.
-         * @stable ICU 3.8
-         */
-        public static final Field HOUR_OF_DAY1 = new Field("hour of day 1", -1);
-
-        /**
-         * Constant identifying the hour(0-11) field.
-         * @stable ICU 3.8
-         */
-        public static final Field HOUR0 = new Field("hour", Calendar.HOUR);
-
-        /**
-         * Constant identifying the hour(1-12) field.
-         * @stable ICU 3.8
-         */
-        public static final Field HOUR1 = new Field("hour 1", -1);
-
-        /**
-         * Constant identifying the millisecond field.
-         * @stable ICU 3.8
-         */
-        public static final Field MILLISECOND = new Field("millisecond", Calendar.MILLISECOND);
-
-        /**
-         * Constant identifying the minute field.
-         * @stable ICU 3.8
-         */
-        public static final Field MINUTE = new Field("minute", Calendar.MINUTE);
-
-        /**
-         * Constant identifying the month field.
-         * @stable ICU 3.8
-         */
-        public static final Field MONTH = new Field("month", Calendar.MONTH);
-
-        /**
-         * Constant identifying the second field.
-         * @stable ICU 3.8
-         */
-        public static final Field SECOND = new Field("second", Calendar.SECOND);
-
-        /**
-         * Constant identifying the time zone field.
-         * @stable ICU 3.8
-         */
-        public static final Field TIME_ZONE = new Field("time zone", -1);
-
-        /**
-         * Constant identifying the week of month field.
-         * @stable ICU 3.8
-         */
-        public static final Field WEEK_OF_MONTH =
-            new Field("week of month", Calendar.WEEK_OF_MONTH);
-
-        /**
-         * Constant identifying the week of year field.
-         * @stable ICU 3.8
-         */
-        public static final Field WEEK_OF_YEAR = new Field("week of year", Calendar.WEEK_OF_YEAR);
-
-        /**
-         * Constant identifying the year field.
-         * @stable ICU 3.8
-         */
-        public static final Field YEAR = new Field("year", Calendar.YEAR);
-
-
-        // ICU only fields -------------------
-
-        /**
-         * Constant identifying the local day of week field.
-         * @stable ICU 3.8
-         */
-        public static final Field DOW_LOCAL = new Field("local day of week", Calendar.DOW_LOCAL);
-
-        /**
-         * Constant identifying the extended year field.
-         * @stable ICU 3.8
-         */
-        public static final Field EXTENDED_YEAR = new Field("extended year", 
-                                                            Calendar.EXTENDED_YEAR);
-
-        /**
-         * Constant identifying the Julian day field.
-         * @stable ICU 3.8
-         */
-        public static final Field JULIAN_DAY = new Field("Julian day", Calendar.JULIAN_DAY);
-
-        /**
-         * Constant identifying the milliseconds in day field.
-         * @stable ICU 3.8
-         */
-        public static final Field MILLISECONDS_IN_DAY =
-            new Field("milliseconds in day", Calendar.MILLISECONDS_IN_DAY);
-
-        /**
-         * Constant identifying the year used with week of year field.
-         * @stable ICU 3.8
-         */
-        public static final Field YEAR_WOY = new Field("year for week of year", Calendar.YEAR_WOY);
-
-        /**
-         * Constant identifying the quarter field.
-         * @stable ICU 3.8
-         */
-        public static final Field QUARTER = new Field("quarter", -1);
-
-        // Stand alone types are variants for its base types.  So we do not define Field for
-        // them.
-        /*
-        public static final Field STANDALONE_DAY =
-            new Field("stand alone day of week", Calendar.DAY_OF_WEEK);
-        public static final Field STANDALONE_MONTH = new Field("stand alone month", Calendar.MONTH);
-        public static final Field STANDALONE_QUARTER = new Field("stand alone quarter", -1);
-        */
-
-        // Corresponding calendar field
-        private final int calendarField;
-
-        /**
-         * Constructs a <code>DateFormat.Field</code> with the given name and
-         * the <code>Calendar</code> field which this attribute represents.  Use -1 for
-         * <code>calendarField</code> if this field does not have a corresponding
-         * <code>Calendar</code> field.
-         *
-         * @param name          Name of the attribute
-         * @param calendarField <code>Calendar</code> field constant
-         *
-         * @stable ICU 3.8
-         */
-        protected Field(String name, int calendarField) {
-            super(name);
-            this.calendarField = calendarField;
-            if (this.getClass() == DateFormat.Field.class) {
-                FIELD_NAME_MAP.put(name, this);
-                if (calendarField >= 0 && calendarField < CAL_FIELD_COUNT) {
-                    CAL_FIELDS[calendarField] = this;
-                }
-            }
-        }
-
-        /**
-         * Returns the <code>Field</code> constant that corresponds to the <code>
-         * Calendar</code> field <code>calendarField</code>.  If there is no
-         * corresponding <code>Field</code> is available, null is returned.
-         *
-         * @param calendarField <code>Calendar</code> field constant
-         * @return <code>Field</code> associated with the <code>calendarField</code>,
-         * or null if no associated <code>Field</code> is available.
-         * @throws IllegalArgumentException if <code>calendarField</code> is not
-         * a valid <code>Calendar</code> field constant.
-         *
-         * @stable ICU 3.8
-         */
-        public static DateFormat.Field ofCalendarField(int calendarField) {
-            if (calendarField < 0 || calendarField >= CAL_FIELD_COUNT) {
-                throw new IllegalArgumentException("Calendar field number is out of range");
-            }
-            return CAL_FIELDS[calendarField];
-        }
-
-        /**
-         * Returns the <code>Calendar</code> field associated with this attribute.
-         * If there is no corresponding <code>Calendar</code> available, this will
-         * return -1.
-         *
-         * @return <code>Calendar</code> constant for this attribute.
-         *
-         * @stable ICU 3.8
-         */
-        public int getCalendarField() {
-            return calendarField;
-        }
-
-        /**
-         * Resolves instances being deserialized to the predefined constants.
-         *
-         * @throws InvalidObjectException if the constant could not be resolved.
-         *
-         * @stable ICU 3.8
-         */
-        protected Object readResolve() throws InvalidObjectException {
-            ///CLOVER:OFF
-            if (this.getClass() != DateFormat.Field.class) {
-                throw new InvalidObjectException(
-                    "A subclass of DateFormat.Field must implement readResolve.");
-            }
-            ///CLOVER:ON
-            Object o = FIELD_NAME_MAP.get(this.getName());
-            ///CLOVER:OFF
-            if (o == null) {
-                throw new InvalidObjectException("Unknown attribute name.");
-            }
-            ///CLOVER:ON
-            return o;
-        }
-    }
-
-    private static int getJDKFormatStyle(int icuFormatStyle) {
-        switch (icuFormatStyle) {
-        case DateFormat.FULL:
-            return java.text.DateFormat.FULL;
-        case DateFormat.LONG:
-            return java.text.DateFormat.LONG;
-        case DateFormat.MEDIUM:
-            return java.text.DateFormat.MEDIUM;
-        case DateFormat.SHORT:
-            return java.text.DateFormat.SHORT;
-        default:
-            throw new UnsupportedOperationException("Style not supported by com.ibm.icu.base");
-        }
-    }
-
-
-    protected static FieldPosition toJDKFieldPosition(FieldPosition icuPos) {
-        if (icuPos == null) {
-            return null;
-        }
-
-        int fieldID = icuPos.getField();
-        Format.Field fieldAttribute = icuPos.getFieldAttribute();
-
-        FieldPosition jdkPos = null;
-
-        if (fieldID >= 0) {
-            switch (fieldID) {
-            case ERA_FIELD:
-                fieldID = java.text.DateFormat.ERA_FIELD;
-                break;
-            case YEAR_FIELD:
-                fieldID = java.text.DateFormat.YEAR_FIELD;
-                break;
-            case MONTH_FIELD:
-                fieldID = java.text.DateFormat.MONTH_FIELD;
-                break;
-            case DATE_FIELD:
-                fieldID = java.text.DateFormat.DATE_FIELD;
-                break;
-            case HOUR_OF_DAY1_FIELD:
-                fieldID = java.text.DateFormat.HOUR_OF_DAY1_FIELD;
-                break;
-            case HOUR_OF_DAY0_FIELD:
-                fieldID = java.text.DateFormat.HOUR_OF_DAY0_FIELD;
-                break;
-            case MINUTE_FIELD:
-                fieldID = java.text.DateFormat.MINUTE_FIELD;
-                break;
-            case SECOND_FIELD:
-                fieldID = java.text.DateFormat.SECOND_FIELD;
-                break;
-            case FRACTIONAL_SECOND_FIELD: // MILLISECOND_FIELD
-                fieldID = java.text.DateFormat.MILLISECOND_FIELD;
-                break;
-            case DAY_OF_WEEK_FIELD:
-                fieldID = java.text.DateFormat.DAY_OF_WEEK_FIELD;
-                break;
-            case DAY_OF_YEAR_FIELD:
-                fieldID = java.text.DateFormat.DAY_OF_YEAR_FIELD;
-                break;
-            case DAY_OF_WEEK_IN_MONTH_FIELD:
-                fieldID = java.text.DateFormat.DAY_OF_WEEK_IN_MONTH_FIELD;
-                break;
-            case WEEK_OF_YEAR_FIELD:
-                fieldID = java.text.DateFormat.WEEK_OF_YEAR_FIELD;
-                break;
-            case WEEK_OF_MONTH_FIELD:
-                fieldID = java.text.DateFormat.WEEK_OF_MONTH_FIELD;
-                break;
-            case AM_PM_FIELD:
-                fieldID = java.text.DateFormat.AM_PM_FIELD;
-                break;
-            case HOUR1_FIELD:
-                fieldID = java.text.DateFormat.HOUR1_FIELD;
-                break;
-            case HOUR0_FIELD:
-                fieldID = java.text.DateFormat.HOUR0_FIELD;
-                break;
-            case TIMEZONE_FIELD:
-                fieldID = java.text.DateFormat.TIMEZONE_FIELD;
-                break;
-
-            case YEAR_WOY_FIELD:
-            case DOW_LOCAL_FIELD:
-            case EXTENDED_YEAR_FIELD:
-            case JULIAN_DAY_FIELD:
-            case MILLISECONDS_IN_DAY_FIELD:
-            case TIMEZONE_RFC_FIELD:
-            case TIMEZONE_GENERIC_FIELD:
-            case STANDALONE_DAY_FIELD:
-            case STANDALONE_MONTH_FIELD:
-            case QUARTER_FIELD:
-            case STANDALONE_QUARTER_FIELD:
-            case TIMEZONE_SPECIAL_FIELD:
-                throw new UnsupportedOperationException("Format Field ID not supported by com.ibm.icu.base");
-
-            default:
-                // just let it go
-                break;
-            }
-        }
-
-        if (fieldAttribute != null) {
-            // map field
-            if (fieldAttribute.equals(Field.AM_PM)) {
-                fieldAttribute = java.text.DateFormat.Field.AM_PM;
-            } else if (fieldAttribute.equals(Field.DAY_OF_MONTH)) {
-                fieldAttribute = java.text.DateFormat.Field.DAY_OF_MONTH;
-            } else if (fieldAttribute.equals(Field.DAY_OF_WEEK)) {
-                fieldAttribute = java.text.DateFormat.Field.DAY_OF_WEEK;
-            } else if (fieldAttribute.equals(Field.DAY_OF_WEEK_IN_MONTH)) {
-                fieldAttribute = java.text.DateFormat.Field.DAY_OF_WEEK_IN_MONTH;
-            } else if (fieldAttribute.equals(Field.DAY_OF_YEAR)) {
-                fieldAttribute = java.text.DateFormat.Field.DAY_OF_YEAR;
-            } else if (fieldAttribute.equals(Field.ERA)) {
-                fieldAttribute = java.text.DateFormat.Field.ERA;
-            } else if (fieldAttribute.equals(Field.HOUR_OF_DAY0)) {
-                fieldAttribute = java.text.DateFormat.Field.HOUR_OF_DAY0;
-            } else if (fieldAttribute.equals(Field.HOUR_OF_DAY1)) {
-                fieldAttribute = java.text.DateFormat.Field.HOUR_OF_DAY1;
-            } else if (fieldAttribute.equals(Field.HOUR0)) {
-                fieldAttribute = java.text.DateFormat.Field.HOUR0;
-            } else if (fieldAttribute.equals(Field.HOUR1)) {
-                fieldAttribute = java.text.DateFormat.Field.HOUR1;
-            } else if (fieldAttribute.equals(Field.MILLISECOND)) {
-                fieldAttribute = java.text.DateFormat.Field.MILLISECOND;
-            } else if (fieldAttribute.equals(Field.MINUTE)) {
-                fieldAttribute = java.text.DateFormat.Field.MINUTE;
-            } else if (fieldAttribute.equals(Field.MONTH)) {
-                fieldAttribute = java.text.DateFormat.Field.MONTH;
-            } else if (fieldAttribute.equals(Field.SECOND)) {
-                fieldAttribute = java.text.DateFormat.Field.SECOND;
-            } else if (fieldAttribute.equals(Field.TIME_ZONE)) {
-                fieldAttribute = java.text.DateFormat.Field.TIME_ZONE;
-            } else if (fieldAttribute.equals(Field.WEEK_OF_MONTH)) {
-                fieldAttribute = java.text.DateFormat.Field.WEEK_OF_MONTH;
-            } else if (fieldAttribute.equals(Field.WEEK_OF_YEAR)) {
-                fieldAttribute = java.text.DateFormat.Field.WEEK_OF_YEAR;
-            } else if (fieldAttribute.equals(Field.YEAR)) {
-                fieldAttribute = java.text.DateFormat.Field.YEAR;
-            } else if (fieldAttribute.equals(Field.DOW_LOCAL)
-                    || fieldAttribute.equals(Field.EXTENDED_YEAR)
-                    || fieldAttribute.equals(Field.JULIAN_DAY)
-                    || fieldAttribute.equals(Field.MILLISECONDS_IN_DAY)
-                    || fieldAttribute.equals(Field.YEAR_WOY)
-                    || fieldAttribute.equals(Field.QUARTER)) {
-                // Not supported
-                throw new UnsupportedOperationException("Format Field not supported by com.ibm.icu.base");
-            }
-
-            jdkPos = new FieldPosition(fieldAttribute, fieldID);
-        } else {
-            jdkPos = new FieldPosition(fieldID);
-        }
-
-        jdkPos.setBeginIndex(icuPos.getBeginIndex());
-        jdkPos.setEndIndex(icuPos.getEndIndex());
-
-        return jdkPos;
-    }
-}
+/*
+ *   Copyright (C) 1996-2011, International Business Machines
+ *   Corporation and others.  All Rights Reserved.
+ */
+
+package com.ibm.icu.text;
+
+import java.io.InvalidObjectException;
+import java.text.FieldPosition;
+import java.text.Format;
+import java.text.ParseException;
+import java.text.ParsePosition;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import com.ibm.icu.util.Calendar;
+import com.ibm.icu.util.TimeZone;
+import com.ibm.icu.util.ULocale;
+import com.ibm.icu.util.ULocale.Category;
+
+/**
+ * {@icuenhanced java.text.DateFormat}.{@icu _usage_}
+ *
+ * <p>DateFormat is an abstract class for date/time formatting subclasses which
+ * formats and parses dates or time in a language-independent manner.
+ * The date/time formatting subclass, such as SimpleDateFormat, allows for
+ * formatting (i.e., date -> text), parsing (text -> date), and
+ * normalization.  The date is represented as a <code>Date</code> object or
+ * as the milliseconds since January 1, 1970, 00:00:00 GMT.
+ *
+ * <p>DateFormat provides many class methods for obtaining default date/time
+ * formatters based on the default or a given locale and a number of formatting
+ * styles. The formatting styles include FULL, LONG, MEDIUM, and SHORT. More
+ * detail and examples of using these styles are provided in the method
+ * descriptions.
+ *
+ * <p>DateFormat helps you to format and parse dates for any locale.
+ * Your code can be completely independent of the locale conventions for
+ * months, days of the week, or even the calendar format: lunar vs. solar.
+ *
+ * <p>To format a date for the current Locale, use one of the
+ * static factory methods:
+ * <pre>
+ *  myString = DateFormat.getDateInstance().format(myDate);
+ * </pre>
+ * <p>If you are formatting multiple numbers, it is
+ * more efficient to get the format and use it multiple times so that
+ * the system doesn't have to fetch the information about the local
+ * language and country conventions multiple times.
+ * <pre>
+ *  DateFormat df = DateFormat.getDateInstance();
+ *  for (int i = 0; i < a.length; ++i) {
+ *    output.println(df.format(myDate[i]) + "; ");
+ *  }
+ * </pre>
+ * <p>To format a number for a different Locale, specify it in the
+ * call to getDateInstance().
+ * <pre>
+ *  DateFormat df = DateFormat.getDateInstance(DateFormat.LONG, Locale.FRANCE);
+ * </pre>
+ * <p>You can use a DateFormat to parse also.
+ * <pre>
+ *  myDate = df.parse(myString);
+ * </pre>
+ * <p>Use getDateInstance to get the normal date format for that country.
+ * There are other static factory methods available.
+ * Use getTimeInstance to get the time format for that country.
+ * Use getDateTimeInstance to get a date and time format. You can pass in
+ * different options to these factory methods to control the length of the
+ * result; from SHORT to MEDIUM to LONG to FULL. The exact result depends
+ * on the locale, but generally:
+ * <ul><li>SHORT is completely numeric, such as 12.13.52 or 3:30pm
+ * <li>MEDIUM is longer, such as Jan 12, 1952
+ * <li>LONG is longer, such as January 12, 1952 or 3:30:32pm
+ * <li>FULL is pretty completely specified, such as
+ * Tuesday, April 12, 1952 AD or 3:30:42pm PST.
+ * </ul>
+ *
+ * <p>You can also set the time zone on the format if you wish.
+ * If you want even more control over the format or parsing,
+ * (or want to give your users more control),
+ * you can try casting the DateFormat you get from the factory methods
+ * to a SimpleDateFormat. This will work for the majority
+ * of countries; just remember to put it in a try block in case you
+ * encounter an unusual one.
+ *
+ * <p>You can also use forms of the parse and format methods with
+ * ParsePosition and FieldPosition to
+ * allow you to
+ * <ul><li>progressively parse through pieces of a string.
+ * <li>align any particular field, or find out where it is for selection
+ * on the screen.
+ * </ul>
+ *
+ * <h4>Synchronization</h4>
+ *
+ * Date formats are not synchronized. It is recommended to create separate
+ * format instances for each thread. If multiple threads access a format
+ * concurrently, it must be synchronized externally.
+ *
+ * @see          UFormat
+ * @see          NumberFormat
+ * @see          SimpleDateFormat
+ * @see          com.ibm.icu.util.Calendar
+ * @see          com.ibm.icu.util.GregorianCalendar
+ * @see          com.ibm.icu.util.TimeZone
+ * @author       Mark Davis, Chen-Lieh Huang, Alan Liu
+ * @stable ICU 2.0
+ */
+public class DateFormat extends Format {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * @internal
+     */
+    public final java.text.DateFormat dateFormat;
+        
+    /**
+     * @internal
+     * @param delegate the DateFormat to which to delegate
+     */
+    public DateFormat(java.text.DateFormat delegate) {
+        this.dateFormat = delegate;
+    }
+    
+    /**
+     * For subclass use.  Subclasses will generally not
+     * work correctly unless they manipulate the delegate.
+     */
+    protected DateFormat() {
+        this.dateFormat = java.text.DateFormat.getInstance();
+    }
+
+    /**
+     * FieldPosition selector for 'G' field alignment,
+     * corresponding to the {@link Calendar#ERA} field.
+     * @stable ICU 2.0
+     */
+    public final static int ERA_FIELD = 0;
+
+    /**
+     * FieldPosition selector for 'y' field alignment,
+     * corresponding to the {@link Calendar#YEAR} field.
+     * @stable ICU 2.0
+     */
+    public final static int YEAR_FIELD = 1;
+
+    /**
+     * FieldPosition selector for 'M' field alignment,
+     * corresponding to the {@link Calendar#MONTH} field.
+     * @stable ICU 2.0
+     */
+    public final static int MONTH_FIELD = 2;
+
+    /**
+     * FieldPosition selector for 'd' field alignment,
+     * corresponding to the {@link Calendar#DATE} field.
+     * @stable ICU 2.0
+     */
+    public final static int DATE_FIELD = 3;
+
+    /**
+     * FieldPosition selector for 'k' field alignment,
+     * corresponding to the {@link Calendar#HOUR_OF_DAY} field.
+     * HOUR_OF_DAY1_FIELD is used for the one-based 24-hour clock.
+     * For example, 23:59 + 01:00 results in 24:59.
+     * @stable ICU 2.0
+     */
+    public final static int HOUR_OF_DAY1_FIELD = 4;
+
+    /**
+     * FieldPosition selector for 'H' field alignment,
+     * corresponding to the {@link Calendar#HOUR_OF_DAY} field.
+     * HOUR_OF_DAY0_FIELD is used for the zero-based 24-hour clock.
+     * For example, 23:59 + 01:00 results in 00:59.
+     * @stable ICU 2.0
+     */
+    public final static int HOUR_OF_DAY0_FIELD = 5;
+
+    /**
+     * FieldPosition selector for 'm' field alignment,
+     * corresponding to the {@link Calendar#MINUTE} field.
+     * @stable ICU 2.0
+     */
+    public final static int MINUTE_FIELD = 6;
+
+    /**
+     * FieldPosition selector for 's' field alignment,
+     * corresponding to the {@link Calendar#SECOND} field.
+     * @stable ICU 2.0
+     */
+    public final static int SECOND_FIELD = 7;
+
+    /**
+     * {@icu} FieldPosition selector for 'S' field alignment,
+     * corresponding to the {@link Calendar#MILLISECOND} field.
+     * @stable ICU 3.0
+     */
+    public final static int FRACTIONAL_SECOND_FIELD = 8;
+
+    /**
+     * Alias for FRACTIONAL_SECOND_FIELD.
+     * @deprecated ICU 3.0 use FRACTIONAL_SECOND_FIELD.
+     */
+    public final static int MILLISECOND_FIELD = FRACTIONAL_SECOND_FIELD;
+
+    /**
+     * FieldPosition selector for 'E' field alignment,
+     * corresponding to the {@link Calendar#DAY_OF_WEEK} field.
+     * @stable ICU 2.0
+     */
+    public final static int DAY_OF_WEEK_FIELD = 9;
+
+    /**
+     * FieldPosition selector for 'D' field alignment,
+     * corresponding to the {@link Calendar#DAY_OF_YEAR} field.
+     * @stable ICU 2.0
+     */
+    public final static int DAY_OF_YEAR_FIELD = 10;
+
+    /**
+     * FieldPosition selector for 'F' field alignment,
+     * corresponding to the {@link Calendar#DAY_OF_WEEK_IN_MONTH} field.
+     * @stable ICU 2.0
+     */
+    public final static int DAY_OF_WEEK_IN_MONTH_FIELD = 11;
+
+    /**
+     * FieldPosition selector for 'w' field alignment,
+     * corresponding to the {@link Calendar#WEEK_OF_YEAR} field.
+     * @stable ICU 2.0
+     */
+    public final static int WEEK_OF_YEAR_FIELD = 12;
+
+    /**
+     * FieldPosition selector for 'W' field alignment,
+     * corresponding to the {@link Calendar#WEEK_OF_MONTH} field.
+     * @stable ICU 2.0
+     */
+    public final static int WEEK_OF_MONTH_FIELD = 13;
+
+    /**
+     * FieldPosition selector for 'a' field alignment,
+     * corresponding to the {@link Calendar#AM_PM} field.
+     * @stable ICU 2.0
+     */
+    public final static int AM_PM_FIELD = 14;
+
+    /**
+     * FieldPosition selector for 'h' field alignment,
+     * corresponding to the {@link Calendar#HOUR} field.
+     * HOUR1_FIELD is used for the one-based 12-hour clock.
+     * For example, 11:30 PM + 1 hour results in 12:30 AM.
+     * @stable ICU 2.0
+     */
+    public final static int HOUR1_FIELD = 15;
+
+    /**
+     * FieldPosition selector for 'K' field alignment,
+     * corresponding to the {@link Calendar#HOUR} field.
+     * HOUR0_FIELD is used for the zero-based 12-hour clock.
+     * For example, 11:30 PM + 1 hour results in 00:30 AM.
+     * @stable ICU 2.0
+     */
+    public final static int HOUR0_FIELD = 16;
+
+    /**
+     * FieldPosition selector for 'z' field alignment,
+     * corresponding to the {@link Calendar#ZONE_OFFSET} and
+     * {@link Calendar#DST_OFFSET} fields.
+     * @stable ICU 2.0
+     */
+    public final static int TIMEZONE_FIELD = 17;
+
+    /**
+     * {@icu} FieldPosition selector for 'Y' field alignment,
+     * corresponding to the {@link Calendar#YEAR_WOY} field.
+     * @stable ICU 3.0
+     */
+    public final static int YEAR_WOY_FIELD = 18;
+
+    /**
+     * {@icu} FieldPosition selector for 'e' field alignment,
+     * corresponding to the {@link Calendar#DOW_LOCAL} field.
+     * @stable ICU 3.0
+     */
+    public final static int DOW_LOCAL_FIELD = 19;
+
+    /**
+     * {@icu} FieldPosition selector for 'u' field alignment,
+     * corresponding to the {@link Calendar#EXTENDED_YEAR} field.
+     * @stable ICU 3.0
+     */
+    public final static int EXTENDED_YEAR_FIELD = 20;
+
+    /**
+     * {@icu} FieldPosition selector for 'g' field alignment,
+     * corresponding to the {@link Calendar#JULIAN_DAY} field.
+     * @stable ICU 3.0
+     */
+    public final static int JULIAN_DAY_FIELD = 21;
+
+    /**
+     * {@icu} FieldPosition selector for 'A' field alignment,
+     * corresponding to the {@link Calendar#MILLISECONDS_IN_DAY} field.
+     * @stable ICU 3.0
+     */
+    public final static int MILLISECONDS_IN_DAY_FIELD = 22;
+
+    /**
+     * {@icu} FieldPosition selector for 'Z' field alignment,
+     * corresponding to the {@link Calendar#ZONE_OFFSET} and
+     * {@link Calendar#DST_OFFSET} fields.
+     * @stable ICU 3.0
+     */
+    public final static int TIMEZONE_RFC_FIELD = 23;
+
+    /**
+     * {@icu} FieldPosition selector for 'v' field alignment,
+     * corresponding to the {@link Calendar#ZONE_OFFSET} and
+     * {@link Calendar#DST_OFFSET} fields.  This displays the generic zone
+     * name, if available.
+     * @stable ICU 3.4
+     */
+    public final static int TIMEZONE_GENERIC_FIELD = 24;
+
+    /**
+     * {@icu} FieldPosition selector for 'c' field alignment,
+     * corresponding to the {@link Calendar#DAY_OF_WEEK} field.
+     * This displays the stand alone day name, if available.
+     * @stable ICU 3.4
+     */
+    public final static int STANDALONE_DAY_FIELD = 25;
+
+    /**
+     * {@icu} FieldPosition selector for 'L' field alignment,
+     * corresponding to the {@link Calendar#MONTH} field.
+     * This displays the stand alone month name, if available.
+     * @stable ICU 3.4
+     */
+    public final static int STANDALONE_MONTH_FIELD = 26;
+
+    /**
+     * {@icu} FieldPosition selector for 'Q' field alignment,
+     * corresponding to the {@link Calendar#MONTH} field.
+     * This displays the quarter.
+     * @stable ICU 3.6
+     */
+    public final static int QUARTER_FIELD = 27;
+
+    /**
+     * {@icu} FieldPosition selector for 'q' field alignment,
+     * corresponding to the {@link Calendar#MONTH} field.
+     * This displays the stand alone quarter, if available.
+     * @stable ICU 3.6
+     */
+    public final static int STANDALONE_QUARTER_FIELD = 28;
+
+    /**
+     * {@icu} FieldPosition selector for 'V' field alignment,
+     * corresponding to the {@link Calendar#ZONE_OFFSET} and
+     * {@link Calendar#DST_OFFSET} fields.  This displays the fallback timezone
+     * name when VVVV is specified, and the short standard or daylight
+     * timezone name ignoring commonlyUsed when a single V is specified.
+     * @stable ICU 3.8
+     */
+    public final static int TIMEZONE_SPECIAL_FIELD = 29;
+
+    /**
+     * {@icu} Number of FieldPosition selectors for DateFormat.
+     * Valid selectors range from 0 to FIELD_COUNT-1.
+     * @stable ICU 3.0
+     */
+    public final static int FIELD_COUNT = 30; // must == DateFormatSymbols.patternChars.length()
+
+    /**
+     * Formats a time object into a time string. Examples of time objects
+     * are a time value expressed in milliseconds and a Date object.
+     * @param obj must be a Number or a Date or a Calendar.
+     * @param toAppendTo the string buffer for the returning time string.
+     * @return the formatted time string.
+     * @param fieldPosition keeps track of the position of the field
+     * within the returned string.
+     * On input: an alignment field,
+     * if desired. On output: the offsets of the alignment field. For
+     * example, given a time text "1996.07.10 AD at 15:08:56 PDT",
+     * if the given fieldPosition is DateFormat.YEAR_FIELD, the
+     * begin index and end index of fieldPosition will be set to
+     * 0 and 4, respectively.
+     * Notice that if the same time field appears
+     * more than once in a pattern, the fieldPosition will be set for the first
+     * occurrence of that time field. For instance, formatting a Date to
+     * the time string "1 PM PDT (Pacific Daylight Time)" using the pattern
+     * "h a z (zzzz)" and the alignment field DateFormat.TIMEZONE_FIELD,
+     * the begin index and end index of fieldPosition will be set to
+     * 5 and 8, respectively, for the first occurrence of the timezone
+     * pattern character 'z'.
+     * @see java.text.Format
+     * @stable ICU 2.0
+     */
+    public final StringBuffer format(Object obj, StringBuffer toAppendTo,
+                                     FieldPosition fieldPosition)
+    {
+        if (obj instanceof Calendar) {
+            return format((Calendar)obj, toAppendTo, fieldPosition);
+        } else if (obj instanceof Date) {
+            return format((Date)obj, toAppendTo, fieldPosition);
+        } else if (obj instanceof Number) {
+            return format(new Date(((Number)obj).longValue()), toAppendTo, fieldPosition );
+        }
+
+        throw new IllegalArgumentException("Cannot format given Object (" +
+                                               obj.getClass().getName() + ") as a Date");
+    }
+
+    /**
+     * Formats a date into a date/time string.
+     * @param cal a Calendar set to the date and time to be formatted
+     * into a date/time string.  When the calendar type is different from
+     * the internal calendar held by this DateFormat instance, the date
+     * and the time zone will be inherited from the input calendar, but
+     * other calendar field values will be calculated by the internal calendar.
+     * @param toAppendTo the string buffer for the returning date/time string.
+     * @param fieldPosition keeps track of the position of the field
+     * within the returned string.
+     * On input: an alignment field,
+     * if desired. On output: the offsets of the alignment field. For
+     * example, given a time text "1996.07.10 AD at 15:08:56 PDT",
+     * if the given fieldPosition is DateFormat.YEAR_FIELD, the
+     * begin index and end index of fieldPosition will be set to
+     * 0 and 4, respectively.
+     * Notice that if the same time field appears
+     * more than once in a pattern, the fieldPosition will be set for the first
+     * occurrence of that time field. For instance, formatting a Date to
+     * the time string "1 PM PDT (Pacific Daylight Time)" using the pattern
+     * "h a z (zzzz)" and the alignment field DateFormat.TIMEZONE_FIELD,
+     * the begin index and end index of fieldPosition will be set to
+     * 5 and 8, respectively, for the first occurrence of the timezone
+     * pattern character 'z'.
+     * @return the formatted date/time string.
+     * @stable ICU 2.0
+     */
+    public StringBuffer format(Calendar cal, StringBuffer toAppendTo,
+                                        FieldPosition fieldPosition) {
+        return format(cal.getTime(), toAppendTo, fieldPosition);
+    }
+
+    /**
+     * Formats a Date into a date/time string.
+     * @param date a Date to be formatted into a date/time string.
+     * @param toAppendTo the string buffer for the returning date/time string.
+     * @param fieldPosition keeps track of the position of the field
+     * within the returned string.
+     * On input: an alignment field,
+     * if desired. On output: the offsets of the alignment field. For
+     * example, given a time text "1996.07.10 AD at 15:08:56 PDT",
+     * if the given fieldPosition is DateFormat.YEAR_FIELD, the
+     * begin index and end index of fieldPosition will be set to
+     * 0 and 4, respectively.
+     * Notice that if the same time field appears
+     * more than once in a pattern, the fieldPosition will be set for the first
+     * occurrence of that time field. For instance, formatting a Date to
+     * the time string "1 PM PDT (Pacific Daylight Time)" using the pattern
+     * "h a z (zzzz)" and the alignment field DateFormat.TIMEZONE_FIELD,
+     * the begin index and end index of fieldPosition will be set to
+     * 5 and 8, respectively, for the first occurrence of the timezone
+     * pattern character 'z'.
+     * @return the formatted date/time string.
+     * @stable ICU 2.0
+     */
+    public StringBuffer format(Date date, StringBuffer toAppendTo,
+                                     FieldPosition fieldPosition) {
+        FieldPosition jdkPos = toJDKFieldPosition(fieldPosition);
+        StringBuffer buf = dateFormat.format(date, toAppendTo, jdkPos);
+        if (jdkPos != null) {
+            fieldPosition.setBeginIndex(jdkPos.getBeginIndex());
+            fieldPosition.setEndIndex(jdkPos.getEndIndex());
+        }
+        return buf;
+    }
+
+    /**
+     * Formats a Date into a date/time string.
+     * @param date the time value to be formatted into a time string.
+     * @return the formatted time string.
+     * @stable ICU 2.0
+     */
+    public final String format(Date date)
+    {
+        return dateFormat.format(date);
+    }
+
+    /**
+     * Parses a date/time string.
+     *
+     * @param text  The date/time string to be parsed
+     *
+     * @return      A Date, or null if the input could not be parsed
+     *
+     * @exception  ParseException  If the given string cannot be parsed as a date.
+     *
+     * @see #parse(String, ParsePosition)
+     * @stable ICU 2.0
+     */
+    public Date parse(String text) throws ParseException
+    {
+        return dateFormat.parse(text);
+    }
+
+    /**
+     * Parses a date/time string according to the given parse position.
+     * For example, a time text "07/10/96 4:5 PM, PDT" will be parsed
+     * into a Calendar that is equivalent to Date(837039928046).  The
+     * caller should clear the calendar before calling this method,
+     * unless existing field information is to be kept.
+     *
+     * <p> By default, parsing is lenient: If the input is not in the form used
+     * by this object's format method but can still be parsed as a date, then
+     * the parse succeeds.  Clients may insist on strict adherence to the
+     * format by calling setLenient(false).
+     *
+     * @see #setLenient(boolean)
+     *
+     * @param text  The date/time string to be parsed
+     *
+     * @param cal   The calendar into which parsed data will be stored.
+     *              In general, this should be cleared before calling this
+     *              method.  If this parse fails, the calendar may still
+     *              have been modified.  When the calendar type is different
+     *              from the internal calendar held by this DateFormat
+     *              instance, calendar field values will be parsed based
+     *              on the internal calendar initialized with the time and
+     *              the time zone taken from this calendar, then the
+     *              parse result (time in milliseconds and time zone) will
+     *              be set back to this calendar.
+     *
+     * @param pos   On input, the position at which to start parsing; on
+     *              output, the position at which parsing terminated, or the
+     *              start position if the parse failed.
+     * @stable ICU 2.0
+     */
+    public void parse(String text, Calendar cal, ParsePosition pos) {
+        Date result = dateFormat.parse(text, pos);
+        cal.setTime(result);
+    }
+
+    /**
+     * Parses a date/time string according to the given parse position.  For
+     * example, a time text "07/10/96 4:5 PM, PDT" will be parsed into a Date
+     * that is equivalent to Date(837039928046).
+     *
+     * <p> By default, parsing is lenient: If the input is not in the form used
+     * by this object's format method but can still be parsed as a date, then
+     * the parse succeeds.  Clients may insist on strict adherence to the
+     * format by calling setLenient(false).
+     *
+     * @see #setLenient(boolean)
+     *
+     * @param text  The date/time string to be parsed
+     *
+     * @param pos   On input, the position at which to start parsing; on
+     *              output, the position at which parsing terminated, or the
+     *              start position if the parse failed.
+     *
+     * @return      A Date, or null if the input could not be parsed
+     * @stable ICU 2.0
+     */
+    public Date parse(String text, ParsePosition pos) {
+        return dateFormat.parse(text, pos);
+    }
+
+    /**
+     * Parses a date/time string into an Object.  This convenience method simply
+     * calls parse(String, ParsePosition).
+     *
+     * @see #parse(String, ParsePosition)
+     * @stable ICU 2.0
+     */
+    public Object parseObject (String source, ParsePosition pos)
+    {
+        return parse(source, pos);
+    }
+
+    /**
+     * {@icu} Constant for empty style pattern.
+     * @stable ICU 3.8
+     */
+    public static final int NONE = -1;
+
+    /**
+     * Constant for full style pattern.
+     * @stable ICU 2.0
+     */
+    public static final int FULL = 0;
+
+    /**
+     * Constant for long style pattern.
+     * @stable ICU 2.0
+     */
+    public static final int LONG = 1;
+
+    /**
+     * Constant for medium style pattern.
+     * @stable ICU 2.0
+     */
+    public static final int MEDIUM = 2;
+
+    /**
+     * Constant for short style pattern.
+     * @stable ICU 2.0
+     */
+    public static final int SHORT = 3;
+
+    /**
+     * Constant for default style pattern.  Its value is MEDIUM.
+     * @stable ICU 2.0
+     */
+    public static final int DEFAULT = MEDIUM;
+
+    /**
+     * {@icu} Constant for relative style mask.
+     * @stable ICU 3.8
+     */
+    public static final int RELATIVE = (1 << 7);
+
+    /**
+     * {@icu} Constant for relative full style pattern.
+     * @stable ICU 3.8
+     */
+    public static final int RELATIVE_FULL = RELATIVE | FULL;
+
+    /**
+     * {@icu} Constant for relative style pattern.
+     * @stable ICU 3.8
+     */
+    public static final int RELATIVE_LONG = RELATIVE | LONG;
+
+    /**
+     * {@icu} Constant for relative style pattern.
+     * @stable ICU 3.8
+     */
+    public static final int RELATIVE_MEDIUM = RELATIVE | MEDIUM;
+
+    /**
+     * {@icu} Constant for relative style pattern.
+     * @stable ICU 3.8
+     */
+    public static final int RELATIVE_SHORT = RELATIVE | SHORT;
+
+    /**
+     * {@icu} Constant for relative default style pattern.
+     * @stable ICU 3.8
+     */
+    public static final int RELATIVE_DEFAULT = RELATIVE | DEFAULT;
+
+    /* Below are pre-defined skeletons
+     *
+     * <P>
+     * A skeleton
+     * <ul>
+     * <li>
+     * 1. only keeps the field pattern letter and ignores all other parts
+     *    in a pattern, such as space, punctuations, and string literals.
+     * <li>
+     * 2. hides the order of fields.
+     * <li>
+     * 3. might hide a field's pattern letter length.
+     *
+     *    For those non-digit calendar fields, the pattern letter length is
+     *    important, such as MMM, MMMM, and MMMMM; E and EEEE,
+     *    and the field's pattern letter length is honored.
+     *
+     *    For the digit calendar fields,  such as M or MM, d or dd, yy or yyyy,
+     *    the field pattern length is ignored and the best match, which is
+     *    defined in date time patterns, will be returned without honor
+     *    the field pattern letter length in skeleton.
+     * </ul>
+     */
+    /**
+     * {@icu} Constant for date pattern with minute and second.
+     * @stable ICU 4.0
+     */
+    public static final String MINUTE_SECOND = "ms";
+
+    /**
+     * {@icu} Constant for date pattern with hour and minute in 24-hour presentation.
+     * @stable ICU 4.0
+     */
+    public static final String HOUR24_MINUTE = "Hm";
+
+    /**
+     * {@icu} Constant for date pattern with hour, minute, and second in
+     * 24-hour presentation.
+     * @stable ICU 4.0
+     */
+    public static final String HOUR24_MINUTE_SECOND = "Hms";
+
+    /**
+     * {@icu} Constant for date pattern with hour, minute, and second.
+     * @stable ICU 4.0
+     */
+    public static final String HOUR_MINUTE_SECOND = "hms";
+
+    /**
+     * {@icu} Constant for date pattern with standalone month.
+     * @stable ICU 4.0
+     */
+    public static final String STANDALONE_MONTH = "LLLL";
+
+    /**
+     * {@icu} Constant for date pattern with standalone abbreviated month.
+     * @stable ICU 4.0
+     */
+    public static final String ABBR_STANDALONE_MONTH = "LLL";
+
+    /**
+     * {@icu} Constant for date pattern with year and quarter.
+     * @stable ICU 4.0
+     */
+    public static final String YEAR_QUARTER = "yQQQ";
+
+    /**
+     * {@icu} Constant for date pattern with year and abbreviated quarter.
+     * @stable ICU 4.0
+     */
+    public static final String YEAR_ABBR_QUARTER = "yQ";
+
+
+    /* Below are skeletons that date interval pre-defined in resource file.
+     * Users are encouraged to use them in date interval format factory methods.
+     */
+    /**
+     * {@icu} Constant for date pattern with hour and minute.
+     * @stable ICU 4.0
+     */
+    public static final String HOUR_MINUTE = "hm";
+
+    /**
+     * {@icu} Constant for date pattern with year.
+     * @stable ICU 4.0
+     */
+    public static final String YEAR = "y";
+
+    /**
+     * {@icu} Constant for date pattern with day.
+     * @stable ICU 4.0
+     */
+    public static final String DAY = "d";
+
+    /**
+     * {@icu} Constant for date pattern with numeric month, weekday, and day.
+     * @stable ICU 4.0
+     */
+    public static final String NUM_MONTH_WEEKDAY_DAY = "MEd";
+
+    /**
+     * {@icu} Constant for date pattern with year and numeric month.
+     * @stable ICU 4.0
+     */
+    public static final String YEAR_NUM_MONTH = "yM";
+
+    /**
+     * {@icu} Constant for date pattern with numeric month and day.
+     * @stable ICU 4.0
+     */
+    public static final String NUM_MONTH_DAY = "Md";
+
+    /**
+     * {@icu} Constant for date pattern with year, numeric month, weekday, and day.
+     * @stable ICU 4.0
+     */
+    public static final String YEAR_NUM_MONTH_WEEKDAY_DAY = "yMEd";
+
+    /**
+     * {@icu} Constant for date pattern with abbreviated month, weekday, and day.
+     * @stable ICU 4.0
+     */
+    public static final String ABBR_MONTH_WEEKDAY_DAY = "MMMEd";
+
+    /**
+     * {@icu} Constant for date pattern with year and month.
+     * @stable ICU 4.0
+     */
+    public static final String YEAR_MONTH = "yMMMM";
+
+    /**
+     * {@icu} Constant for date pattern with year and abbreviated month.
+     * @stable ICU 4.0
+     */
+    public static final String YEAR_ABBR_MONTH = "yMMM";
+
+    /**
+     * {@icu} Constant for date pattern having month and day.
+     * @stable ICU 4.0
+     */
+    public static final String MONTH_DAY = "MMMMd";
+
+    /**
+     * {@icu} Constant for date pattern with abbreviated month and day.
+     * @stable ICU 4.0
+     */
+    public static final String ABBR_MONTH_DAY = "MMMd";
+
+    /**
+     * {@icu} Constant for date pattern with month, weekday, and day.
+     * @stable ICU 4.0
+     */
+    public static final String MONTH_WEEKDAY_DAY = "MMMMEEEEd";
+
+    /**
+     * {@icu} Constant for date pattern with year, abbreviated month, weekday,
+     * and day.
+     * @stable ICU 4.0
+     */
+    public static final String YEAR_ABBR_MONTH_WEEKDAY_DAY = "yMMMEd";
+
+    /**
+     * {@icu} Constant for date pattern with year, month, weekday, and day.
+     * @stable ICU 4.0
+     */
+    public static final String YEAR_MONTH_WEEKDAY_DAY = "yMMMMEEEEd";
+
+    /**
+     * {@icu} Constant for date pattern with year, month, and day.
+     * @stable ICU 4.0
+     */
+    public static final String YEAR_MONTH_DAY = "yMMMMd";
+
+    /**
+     * {@icu} Constant for date pattern with year, abbreviated month, and day.
+     * @stable ICU 4.0
+     */
+    public static final String YEAR_ABBR_MONTH_DAY = "yMMMd";
+
+    /**
+     * {@icu} Constant for date pattern with year, numeric month, and day.
+     * @stable ICU 4.0
+     */
+    public static final String YEAR_NUM_MONTH_DAY = "yMd";
+
+    /**
+     * {@icu} Constant for date pattern with numeric month.
+     * @stable ICU 4.0
+     */
+    public static final String NUM_MONTH = "M";
+
+    /**
+     * {@icu} Constant for date pattern with abbreviated month.
+     * @stable ICU 4.0
+     */
+    public static final String ABBR_MONTH = "MMM";
+
+    /**
+     * {@icu} Constant for date pattern with month.
+     * @stable ICU 4.0
+     */
+    public static final String MONTH = "MMMM";
+
+    /**
+     * {@icu} Constant for date pattern with hour, minute, and generic timezone.
+     * @stable ICU 4.0
+     */
+    public static final String HOUR_MINUTE_GENERIC_TZ = "hmv";
+
+    /**
+     * {@icu} Constant for date pattern with hour, minute, and timezone.
+     * @stable ICU 4.0
+     */
+    public static final String HOUR_MINUTE_TZ = "hmz";
+
+    /**
+     * {@icu} Constant for date pattern with hour.
+     * @stable ICU 4.0
+     */
+    public static final String HOUR = "h";
+
+    /**
+     * {@icu} Constant for date pattern with hour and generic timezone.
+     * @stable ICU 4.0
+     */
+    public static final String HOUR_GENERIC_TZ = "hv";
+
+    /**
+     * {@icu} Constant for date pattern with hour and timezone.
+     * @stable ICU 4.0
+     */
+    public static final String HOUR_TZ = "hz";
+
+    /**
+     * Gets the time formatter with the default formatting style
+     * for the default locale.
+     * @return a time formatter.
+     * @stable ICU 2.0
+     */
+    public final static DateFormat getTimeInstance()
+    {
+        return new DateFormat(java.text.DateFormat.getTimeInstance());
+    }
+
+    /**
+     * Returns the time formatter with the given formatting style
+     * for the default locale.
+     * @param style the given formatting style. For example,
+     * SHORT for "h:mm a" in the US locale.
+     * @return a time formatter.
+     * @stable ICU 2.0
+     */
+    public final static DateFormat getTimeInstance(int style)
+    {
+        return new DateFormat(java.text.DateFormat.getTimeInstance(getJDKFormatStyle(style)));
+    }
+
+    /**
+     * Returns the time formatter with the given formatting style
+     * for the given locale.
+     * @param style the given formatting style. For example,
+     * SHORT for "h:mm a" in the US locale.
+     * @param aLocale the given locale.
+     * @return a time formatter.
+     * @stable ICU 2.0
+     */
+    public final static DateFormat getTimeInstance(int style,
+                                                 Locale aLocale)
+    {
+        return new DateFormat(java.text.DateFormat.getTimeInstance(getJDKFormatStyle(style), aLocale));
+    }
+
+    /**
+     * Returns the time formatter with the given formatting style
+     * for the given locale.
+     * @param style the given formatting style. For example,
+     * SHORT for "h:mm a" in the US locale.
+     * @param locale the given ulocale.
+     * @return a time formatter.
+     * @stable ICU 3.2
+     */
+    public final static DateFormat getTimeInstance(int style,
+                                                 ULocale locale)
+    {
+        return new DateFormat(java.text.DateFormat.getTimeInstance(getJDKFormatStyle(style), locale.toLocale()));
+    }
+
+    /**
+     * Returns the date formatter with the default formatting style
+     * for the default locale.
+     * @return a date formatter.
+     * @stable ICU 2.0
+     */
+    public final static DateFormat getDateInstance()
+    {
+        return new DateFormat(java.text.DateFormat.getDateInstance());
+    }
+
+    /**
+     * Returns the date formatter with the given formatting style
+     * for the default locale.
+     * @param style the given formatting style. For example,
+     * SHORT for "M/d/yy" in the US locale.
+     * @return a date formatter.
+     * @stable ICU 2.0
+     */
+    public final static DateFormat getDateInstance(int style)
+    {
+        return new DateFormat(java.text.DateFormat.getDateInstance(getJDKFormatStyle(style)));
+    }
+
+    /**
+     * Returns the date formatter with the given formatting style
+     * for the given locale.
+     * @param style the given formatting style. For example,
+     * SHORT for "M/d/yy" in the US locale.
+     * @param aLocale the given locale.
+     * @return a date formatter.
+     * @stable ICU 2.0
+     */
+    public final static DateFormat getDateInstance(int style,
+                                                 Locale aLocale)
+    {
+        return new DateFormat(java.text.DateFormat.getDateInstance(getJDKFormatStyle(style), aLocale));
+    }
+
+    /**
+     * Returns the date formatter with the given formatting style
+     * for the given locale.
+     * @param style the given formatting style. For example,
+     * SHORT for "M/d/yy" in the US locale.
+     * @param locale the given ulocale.
+     * @return a date formatter.
+     * @stable ICU 3.2
+     */
+    public final static DateFormat getDateInstance(int style,
+                                                 ULocale locale)
+    {
+        return new DateFormat(java.text.DateFormat.getDateInstance(getJDKFormatStyle(style), locale.toLocale()));
+    }
+
+    /**
+     * Returns the date/time formatter with the default formatting style
+     * for the default locale.
+     * @return a date/time formatter.
+     * @stable ICU 2.0
+     */
+    public final static DateFormat getDateTimeInstance()
+    {
+        return new DateFormat(java.text.DateFormat.getDateTimeInstance());
+    }
+
+    /**
+     * Returns the date/time formatter with the given date and time
+     * formatting styles for the default locale.
+     * @param dateStyle the given date formatting style. For example,
+     * SHORT for "M/d/yy" in the US locale.
+     * @param timeStyle the given time formatting style. For example,
+     * SHORT for "h:mm a" in the US locale.
+     * @return a date/time formatter.
+     * @stable ICU 2.0
+     */
+    public final static DateFormat getDateTimeInstance(int dateStyle,
+                                                       int timeStyle)
+    {
+        if (dateStyle != NONE) {
+            if (timeStyle != NONE) {
+                return new DateFormat(java.text.DateFormat.getDateTimeInstance(getJDKFormatStyle(dateStyle), getJDKFormatStyle(timeStyle)));
+            } else {
+                return new DateFormat(java.text.DateFormat.getDateInstance(getJDKFormatStyle(dateStyle)));
+            }
+        }
+        if (timeStyle != NONE) {
+            return new DateFormat(java.text.DateFormat.getTimeInstance(getJDKFormatStyle(timeStyle)));
+        }
+        return null;
+    }
+
+    /**
+     * Returns the date/time formatter with the given formatting styles
+     * for the given locale.
+     * @param dateStyle the given date formatting style.
+     * @param timeStyle the given time formatting style.
+     * @param aLocale the given locale.
+     * @return a date/time formatter.
+     * @stable ICU 2.0
+     */
+    public final static DateFormat getDateTimeInstance(
+        int dateStyle, int timeStyle, Locale aLocale)
+    {
+        if (dateStyle != NONE) {
+            if (timeStyle != NONE) {
+                return new DateFormat(java.text.DateFormat.getDateTimeInstance(getJDKFormatStyle(dateStyle), getJDKFormatStyle(timeStyle), aLocale));
+            } else {
+                return new DateFormat(java.text.DateFormat.getDateInstance(getJDKFormatStyle(dateStyle), aLocale));
+            }
+        }
+        if (timeStyle != NONE) {
+            return new DateFormat(java.text.DateFormat.getTimeInstance(getJDKFormatStyle(timeStyle), aLocale));
+        }
+        return null;
+    }
+
+    /**
+     * Returns the date/time formatter with the given formatting styles
+     * for the given locale.
+     * @param dateStyle the given date formatting style.
+     * @param timeStyle the given time formatting style.
+     * @param locale the given ulocale.
+     * @return a date/time formatter.
+     * @stable ICU 3.2
+     */
+    public final static DateFormat getDateTimeInstance(
+        int dateStyle, int timeStyle, ULocale locale)
+    {
+        if (dateStyle != NONE) {
+            if (timeStyle != NONE) {
+                return new DateFormat(java.text.DateFormat.getDateTimeInstance(getJDKFormatStyle(dateStyle), getJDKFormatStyle(timeStyle), locale.toLocale()));
+            } else {
+                return new DateFormat(java.text.DateFormat.getDateInstance(getJDKFormatStyle(dateStyle), locale.toLocale()));
+            }
+        }
+        if (timeStyle != NONE) {
+            return new DateFormat(java.text.DateFormat.getTimeInstance(getJDKFormatStyle(timeStyle), locale.toLocale()));
+        }
+        return null;
+    }
+
+    /**
+     * Returns a default date/time formatter that uses the SHORT style for both the
+     * date and the time.
+     * @stable ICU 2.0
+     */
+    public final static DateFormat getInstance() {
+        return new DateFormat(java.text.DateFormat.getInstance());
+    }
+
+    /**
+     * Returns the set of locales for which DateFormats are installed.
+     * @return the set of locales for which DateFormats are installed.
+     * @stable ICU 2.0
+     */
+    public static Locale[] getAvailableLocales()
+    {
+        return java.text.DateFormat.getAvailableLocales();
+    }
+
+    /**
+     * {@icu} Returns the set of locales for which DateFormats are installed.
+     * @return the set of locales for which DateFormats are installed.
+     * @draft ICU 3.2 (retain)
+     * @provisional This API might change or be removed in a future release.
+     */
+    public static ULocale[] getAvailableULocales()
+    {
+        if (availableULocales == null) {
+            synchronized(DateFormat.class) {
+                if (availableULocales == null) {
+                    Locale[] locales = java.text.DateFormat.getAvailableLocales();
+                    availableULocales = new ULocale[locales.length];
+                    for (int i = 0; i < locales.length; ++i) {
+                        availableULocales[i] = ULocale.forLocale(locales[i]);
+                    }
+                }
+            }
+        }
+        return availableULocales;
+    }
+    private static volatile ULocale[] availableULocales;
+
+    /**
+     * Sets the calendar to be used by this date format.  Initially, the default
+     * calendar for the specified or default locale is used.
+     * @param newCalendar the new Calendar to be used by the date format
+     * @stable ICU 2.0
+     */
+    public void setCalendar(Calendar newCalendar)
+    {
+        dateFormat.setCalendar(newCalendar.calendar);
+    }
+
+    /**
+     * Returns the calendar associated with this date/time formatter.
+     * @return the calendar associated with this date/time formatter.
+     * @stable ICU 2.0
+     */
+    public Calendar getCalendar()
+    {
+        return new Calendar(dateFormat.getCalendar());
+    }
+
+    /**
+     * Sets the number formatter.
+     * @param newNumberFormat the given new NumberFormat.
+     * @stable ICU 2.0
+     */
+    public void setNumberFormat(NumberFormat newNumberFormat)
+    {
+        dateFormat.setNumberFormat(newNumberFormat.numberFormat);
+    }
+
+    /**
+     * Returns the number formatter which this date/time formatter uses to
+     * format and parse a time.
+     * @return the number formatter which this date/time formatter uses.
+     * @stable ICU 2.0
+     */
+    public NumberFormat getNumberFormat()
+    {
+        return new NumberFormat(dateFormat.getNumberFormat());
+    }
+
+    /**
+     * Sets the time zone for the calendar of this DateFormat object.
+     * @param zone the given new time zone.
+     * @stable ICU 2.0
+     */
+    public void setTimeZone(TimeZone zone)
+    {
+        dateFormat.setTimeZone(zone.timeZone);
+    }
+
+    /**
+     * Returns the time zone.
+     * @return the time zone associated with the calendar of DateFormat.
+     * @stable ICU 2.0
+     */
+    public TimeZone getTimeZone()
+    {
+        return new TimeZone(dateFormat.getTimeZone());
+    }
+
+    /**
+     * Specifies whether date/time parsing is to be lenient.  With
+     * lenient parsing, the parser may use heuristics to interpret inputs that
+     * do not precisely match this object's format.  With strict parsing,
+     * inputs must match this object's format.
+     * @param lenient when true, parsing is lenient
+     * @see com.ibm.icu.util.Calendar#setLenient
+     * @stable ICU 2.0
+     */
+    public void setLenient(boolean lenient)
+    {
+        dateFormat.setLenient(lenient);
+    }
+
+    /**
+     * Returns whether date/time parsing is lenient.
+     * @stable ICU 2.0
+     */
+    public boolean isLenient()
+    {
+        return dateFormat.isLenient();
+    }
+
+    /**
+     * Overrides hashCode.
+     * @stable ICU 2.0
+     */
+    public int hashCode() {
+        return dateFormat.hashCode();
+    }
+
+    /**
+     * Overrides equals.
+     * @stable ICU 2.0
+     */
+    public boolean equals(Object obj) {
+        try {
+            return dateFormat.equals(((DateFormat)obj).dateFormat);
+        }
+        catch (Exception e) {
+            return false;
+        }
+    }
+
+    /**
+     * Overrides clone.
+     * @stable ICU 2.0
+     */
+    public Object clone()
+    {
+        return new DateFormat((java.text.DateFormat)dateFormat.clone());
+    }
+
+    //-------------------------------------------------------------------------
+    // Public static interface for creating custon DateFormats for different
+    // types of Calendars.
+    //-------------------------------------------------------------------------
+
+    /**
+     * Creates a {@link DateFormat} object that can be used to format dates in
+     * the calendar system specified by <code>cal</code>.
+     * <p>
+     * @param cal   The calendar system for which a date format is desired.
+     *
+     * @param dateStyle The type of date format desired.  This can be
+     *              {@link DateFormat#SHORT}, {@link DateFormat#MEDIUM},
+     *              etc.
+     *
+     * @param locale The locale for which the date format is desired.
+     * @stable ICU 2.0
+     */
+    static final public DateFormat getDateInstance(Calendar cal, int dateStyle, Locale locale)
+    {
+        DateFormat df = getDateInstance(dateStyle, locale);
+        df.setCalendar(cal);
+        return df;
+    }
+
+    /**
+     * Creates a {@link DateFormat} object that can be used to format dates in
+     * the calendar system specified by <code>cal</code>.
+     * <p>
+     * @param cal   The calendar system for which a date format is desired.
+     *
+     * @param dateStyle The type of date format desired.  This can be
+     *              {@link DateFormat#SHORT}, {@link DateFormat#MEDIUM},
+     *              etc.
+     *
+     * @param locale The locale for which the date format is desired.
+     * @stable ICU 3.2
+     */
+    static final public DateFormat getDateInstance(Calendar cal, int dateStyle, ULocale locale)
+    {
+        DateFormat df = getDateInstance(dateStyle, locale);
+        df.setCalendar(cal);
+        return df;
+    }
+
+    /**
+     * Creates a {@link DateFormat} object that can be used to format times in
+     * the calendar system specified by <code>cal</code>.
+     * <p>
+     * <b>Note:</b> When this functionality is moved into the core JDK, this method
+     * will probably be replaced by a new overload of {@link DateFormat#getInstance}.
+     * <p>
+     * @param cal   The calendar system for which a time format is desired.
+     *
+     * @param timeStyle The type of time format desired.  This can be
+     *              {@link DateFormat#SHORT}, {@link DateFormat#MEDIUM},
+     *              etc.
+     *
+     * @param locale The locale for which the time format is desired.
+     *
+     * @see DateFormat#getTimeInstance
+     * @stable ICU 2.0
+     */
+    static final public DateFormat getTimeInstance(Calendar cal, int timeStyle, Locale locale)
+    {
+        DateFormat df = getTimeInstance(timeStyle, locale);
+        df.setCalendar(cal);
+        return df;
+    }
+
+    /**
+     * Creates a {@link DateFormat} object that can be used to format times in
+     * the calendar system specified by <code>cal</code>.
+     * <p>
+     * <b>Note:</b> When this functionality is moved into the core JDK, this method
+     * will probably be replaced by a new overload of {@link DateFormat#getInstance}.
+     * <p>
+     * @param cal   The calendar system for which a time format is desired.
+     *
+     * @param timeStyle The type of time format desired.  This can be
+     *              {@link DateFormat#SHORT}, {@link DateFormat#MEDIUM},
+     *              etc.
+     *
+     * @param locale The locale for which the time format is desired.
+     *
+     * @see DateFormat#getTimeInstance
+     * @stable ICU 3.2
+     */
+    static final public DateFormat getTimeInstance(Calendar cal, int timeStyle, ULocale locale)
+    {
+        DateFormat df = getTimeInstance(timeStyle, locale);
+        df.setCalendar(cal);
+        return df;
+    }
+
+    /**
+     * Creates a {@link DateFormat} object that can be used to format dates and times in
+     * the calendar system specified by <code>cal</code>.
+     * <p>
+     * <b>Note:</b> When this functionality is moved into the core JDK, this method
+     * will probably be replaced by a new overload of {@link DateFormat#getInstance}.
+     * <p>
+     * @param cal   The calendar system for which a date/time format is desired.
+     *
+     * @param dateStyle The type of date format desired.  This can be
+     *              {@link DateFormat#SHORT}, {@link DateFormat#MEDIUM},
+     *              etc.
+     *
+     * @param timeStyle The type of time format desired.  This can be
+     *              {@link DateFormat#SHORT}, {@link DateFormat#MEDIUM},
+     *              etc.
+     *
+     * @param locale The locale for which the date/time format is desired.
+     *
+     * @see DateFormat#getDateTimeInstance
+     * @stable ICU 2.0
+     */
+    static final public DateFormat getDateTimeInstance(Calendar cal, int dateStyle,
+                                                 int timeStyle, Locale locale)
+    {
+        DateFormat df = getDateTimeInstance(dateStyle, timeStyle, locale);
+        df.setCalendar(cal);
+        return df;
+    }
+
+    /**
+     * Creates a {@link DateFormat} object that can be used to format dates and times in
+     * the calendar system specified by <code>cal</code>.
+     * <p>
+     * <b>Note:</b> When this functionality is moved into the core JDK, this method
+     * will probably be replaced by a new overload of {@link DateFormat#getInstance}.
+     * <p>
+     * @param cal   The calendar system for which a date/time format is desired.
+     *
+     * @param dateStyle The type of date format desired.  This can be
+     *              {@link DateFormat#SHORT}, {@link DateFormat#MEDIUM},
+     *              etc.
+     *
+     * @param timeStyle The type of time format desired.  This can be
+     *              {@link DateFormat#SHORT}, {@link DateFormat#MEDIUM},
+     *              etc.
+     *
+     * @param locale The locale for which the date/time format is desired.
+     *
+     * @see DateFormat#getDateTimeInstance
+     * @stable ICU 3.2
+     */
+    static final public DateFormat getDateTimeInstance(Calendar cal, int dateStyle,
+                                                 int timeStyle, ULocale locale)
+    {
+        DateFormat df = getDateTimeInstance(dateStyle, timeStyle, locale);
+        df.setCalendar(cal);
+        return df;
+    }
+
+    /**
+     * Convenience overload.
+     * @stable ICU 2.0
+     */
+    static final public DateFormat getInstance(Calendar cal, Locale locale) {
+        return getDateTimeInstance(cal, DateFormat.MEDIUM, DateFormat.SHORT, locale);
+    }
+
+    /**
+     * Convenience overload.
+     * @stable ICU 3.2
+     * @provisional This API might change or be removed in a future release.
+     */
+    static final public DateFormat getInstance(Calendar cal, ULocale locale) {
+        return getDateTimeInstance(cal, DateFormat.MEDIUM, DateFormat.SHORT, locale);
+    }
+
+    /**
+     * Convenience overload.
+     * @stable ICU 2.0
+     */
+    static final public DateFormat getInstance(Calendar cal) {
+        return getInstance(cal, ULocale.getDefault(Category.FORMAT));
+    }
+
+    /**
+     * Convenience overload.
+     * @stable ICU 2.0
+     */
+    static final public DateFormat getDateInstance(Calendar cal, int dateStyle) {
+        return getDateInstance(cal, dateStyle, ULocale.getDefault(Category.FORMAT));
+    }
+
+    /**
+     * Convenience overload.
+     * @stable ICU 2.0
+     */
+    static final public DateFormat getTimeInstance(Calendar cal, int timeStyle) {
+        return getTimeInstance(cal, timeStyle, Locale.getDefault());
+    }
+
+    /**
+     * Convenience overload.
+     * @stable ICU 2.0
+     */
+    static final public DateFormat getDateTimeInstance(Calendar cal, int dateStyle, int timeStyle) {
+        return getDateTimeInstance(cal, dateStyle, timeStyle, ULocale.getDefault(Category.FORMAT));
+    }
+
+    /**
+     * {@icu} Convenience overload.
+     * @stable ICU 4.0
+     */
+    public final static DateFormat getPatternInstance(String pattern) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Convenience overload.
+     * @stable ICU 4.0
+     */
+    public final static DateFormat getPatternInstance(String pattern, Locale locale) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Returns a {@link DateFormat} object that can be used to format dates and times in
+     * the given locale.
+     * <p>
+     * <b>Note:</b> When this functionality is moved into the core JDK, this method
+     * will probably be replaced by a new overload of {@link DateFormat#getInstance}.
+     * <p>
+     *
+     * @param pattern The pattern that selects the fields to be formatted. (Uses the
+     *              {@link DateTimePatternGenerator}.) This can be {@link DateFormat#ABBR_MONTH},
+     *              {@link DateFormat#MONTH_WEEKDAY_DAY}, etc.
+     *
+     * @param locale The locale for which the date/time format is desired.
+     *
+     * @stable ICU 4.0
+     */
+    public final static DateFormat getPatternInstance(String pattern, ULocale locale) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Convenience overload.
+     * @stable ICU 4.0
+     */
+    public final static DateFormat getPatternInstance(Calendar cal, String pattern, Locale locale) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Creates a {@link DateFormat} object that can be used to format dates and
+     * times in the calendar system specified by <code>cal</code>.
+     *
+     * <p><b>Note:</b> When this functionality is moved into the core JDK, this method
+     * will probably be replaced by a new overload of {@link DateFormat#getInstance}.
+     *
+     * @param cal   The calendar system for which a date/time format is desired.
+     *
+     * @param pattern The pattern that selects the fields to be formatted. (Uses the
+     *              {@link DateTimePatternGenerator}.)  This can be
+     *              {@link DateFormat#ABBR_MONTH}, {@link DateFormat#MONTH_WEEKDAY_DAY},
+     *              etc.
+     *
+     * @param locale The locale for which the date/time format is desired.
+     *
+     * @stable ICU 4.0
+     */
+    public final static DateFormat getPatternInstance(
+        Calendar cal, String pattern, ULocale locale) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * The instances of this inner class are used as attribute keys and values
+     * in AttributedCharacterIterator that
+     * DateFormat.formatToCharacterIterator() method returns.
+     *
+     * <p>There is no public constructor to this class, the only instances are the
+     * constants defined here.
+     * <p>
+     * @stable ICU 3.8
+     */
+    public static class Field extends Format.Field {
+
+        private static final long serialVersionUID = -3627456821000730829L;
+
+        // Max number of calendar fields
+        private static final int CAL_FIELD_COUNT;
+
+        // Table for mapping calendar field number to DateFormat.Field
+        private static final Field[] CAL_FIELDS;
+
+        // Map for resolving DateFormat.Field by name
+        private static final Map<String, Field> FIELD_NAME_MAP;
+
+        static {
+            Calendar cal = Calendar.getInstance();
+            CAL_FIELD_COUNT = cal.getFieldCount();
+            CAL_FIELDS = new Field[CAL_FIELD_COUNT];
+            FIELD_NAME_MAP = new HashMap<String, Field>(CAL_FIELD_COUNT);
+        }
+
+        // Java fields -------------------
+
+        /**
+         * Constant identifying the time of day indicator(am/pm).
+         * @stable ICU 3.8
+         */
+        public static final Field AM_PM = new Field("am pm", Calendar.AM_PM);
+
+        /**
+         * Constant identifying the day of month field.
+         * @stable ICU 3.8
+         */
+        public static final Field DAY_OF_MONTH = new Field("day of month", Calendar.DAY_OF_MONTH);
+
+        /**
+         * Constant identifying the day of week field.
+         * @stable ICU 3.8
+         */
+        public static final Field DAY_OF_WEEK = new Field("day of week", Calendar.DAY_OF_WEEK);
+
+        /**
+         * Constant identifying the day of week in month field.
+         * @stable ICU 3.8
+         */
+        public static final Field DAY_OF_WEEK_IN_MONTH =
+            new Field("day of week in month", Calendar.DAY_OF_WEEK_IN_MONTH);
+
+        /**
+         * Constant identifying the day of year field.
+         * @stable ICU 3.8
+         */
+        public static final Field DAY_OF_YEAR = new Field("day of year", Calendar.DAY_OF_YEAR);
+
+        /**
+         * Constant identifying the era field.
+         * @stable ICU 3.8
+         */
+        public static final Field ERA = new Field("era", Calendar.ERA);
+
+        /**
+         * Constant identifying the hour(0-23) of day field.
+         * @stable ICU 3.8
+         */
+        public static final Field HOUR_OF_DAY0 = new Field("hour of day", Calendar.HOUR_OF_DAY);
+
+        /**
+         * Constant identifying the hour(1-24) of day field.
+         * @stable ICU 3.8
+         */
+        public static final Field HOUR_OF_DAY1 = new Field("hour of day 1", -1);
+
+        /**
+         * Constant identifying the hour(0-11) field.
+         * @stable ICU 3.8
+         */
+        public static final Field HOUR0 = new Field("hour", Calendar.HOUR);
+
+        /**
+         * Constant identifying the hour(1-12) field.
+         * @stable ICU 3.8
+         */
+        public static final Field HOUR1 = new Field("hour 1", -1);
+
+        /**
+         * Constant identifying the millisecond field.
+         * @stable ICU 3.8
+         */
+        public static final Field MILLISECOND = new Field("millisecond", Calendar.MILLISECOND);
+
+        /**
+         * Constant identifying the minute field.
+         * @stable ICU 3.8
+         */
+        public static final Field MINUTE = new Field("minute", Calendar.MINUTE);
+
+        /**
+         * Constant identifying the month field.
+         * @stable ICU 3.8
+         */
+        public static final Field MONTH = new Field("month", Calendar.MONTH);
+
+        /**
+         * Constant identifying the second field.
+         * @stable ICU 3.8
+         */
+        public static final Field SECOND = new Field("second", Calendar.SECOND);
+
+        /**
+         * Constant identifying the time zone field.
+         * @stable ICU 3.8
+         */
+        public static final Field TIME_ZONE = new Field("time zone", -1);
+
+        /**
+         * Constant identifying the week of month field.
+         * @stable ICU 3.8
+         */
+        public static final Field WEEK_OF_MONTH =
+            new Field("week of month", Calendar.WEEK_OF_MONTH);
+
+        /**
+         * Constant identifying the week of year field.
+         * @stable ICU 3.8
+         */
+        public static final Field WEEK_OF_YEAR = new Field("week of year", Calendar.WEEK_OF_YEAR);
+
+        /**
+         * Constant identifying the year field.
+         * @stable ICU 3.8
+         */
+        public static final Field YEAR = new Field("year", Calendar.YEAR);
+
+
+        // ICU only fields -------------------
+
+        /**
+         * Constant identifying the local day of week field.
+         * @stable ICU 3.8
+         */
+        public static final Field DOW_LOCAL = new Field("local day of week", Calendar.DOW_LOCAL);
+
+        /**
+         * Constant identifying the extended year field.
+         * @stable ICU 3.8
+         */
+        public static final Field EXTENDED_YEAR = new Field("extended year", 
+                                                            Calendar.EXTENDED_YEAR);
+
+        /**
+         * Constant identifying the Julian day field.
+         * @stable ICU 3.8
+         */
+        public static final Field JULIAN_DAY = new Field("Julian day", Calendar.JULIAN_DAY);
+
+        /**
+         * Constant identifying the milliseconds in day field.
+         * @stable ICU 3.8
+         */
+        public static final Field MILLISECONDS_IN_DAY =
+            new Field("milliseconds in day", Calendar.MILLISECONDS_IN_DAY);
+
+        /**
+         * Constant identifying the year used with week of year field.
+         * @stable ICU 3.8
+         */
+        public static final Field YEAR_WOY = new Field("year for week of year", Calendar.YEAR_WOY);
+
+        /**
+         * Constant identifying the quarter field.
+         * @stable ICU 3.8
+         */
+        public static final Field QUARTER = new Field("quarter", -1);
+
+        // Stand alone types are variants for its base types.  So we do not define Field for
+        // them.
+        /*
+        public static final Field STANDALONE_DAY =
+            new Field("stand alone day of week", Calendar.DAY_OF_WEEK);
+        public static final Field STANDALONE_MONTH = new Field("stand alone month", Calendar.MONTH);
+        public static final Field STANDALONE_QUARTER = new Field("stand alone quarter", -1);
+        */
+
+        // Corresponding calendar field
+        private final int calendarField;
+
+        /**
+         * Constructs a <code>DateFormat.Field</code> with the given name and
+         * the <code>Calendar</code> field which this attribute represents.  Use -1 for
+         * <code>calendarField</code> if this field does not have a corresponding
+         * <code>Calendar</code> field.
+         *
+         * @param name          Name of the attribute
+         * @param calendarField <code>Calendar</code> field constant
+         *
+         * @stable ICU 3.8
+         */
+        protected Field(String name, int calendarField) {
+            super(name);
+            this.calendarField = calendarField;
+            if (this.getClass() == DateFormat.Field.class) {
+                FIELD_NAME_MAP.put(name, this);
+                if (calendarField >= 0 && calendarField < CAL_FIELD_COUNT) {
+                    CAL_FIELDS[calendarField] = this;
+                }
+            }
+        }
+
+        /**
+         * Returns the <code>Field</code> constant that corresponds to the <code>
+         * Calendar</code> field <code>calendarField</code>.  If there is no
+         * corresponding <code>Field</code> is available, null is returned.
+         *
+         * @param calendarField <code>Calendar</code> field constant
+         * @return <code>Field</code> associated with the <code>calendarField</code>,
+         * or null if no associated <code>Field</code> is available.
+         * @throws IllegalArgumentException if <code>calendarField</code> is not
+         * a valid <code>Calendar</code> field constant.
+         *
+         * @stable ICU 3.8
+         */
+        public static DateFormat.Field ofCalendarField(int calendarField) {
+            if (calendarField < 0 || calendarField >= CAL_FIELD_COUNT) {
+                throw new IllegalArgumentException("Calendar field number is out of range");
+            }
+            return CAL_FIELDS[calendarField];
+        }
+
+        /**
+         * Returns the <code>Calendar</code> field associated with this attribute.
+         * If there is no corresponding <code>Calendar</code> available, this will
+         * return -1.
+         *
+         * @return <code>Calendar</code> constant for this attribute.
+         *
+         * @stable ICU 3.8
+         */
+        public int getCalendarField() {
+            return calendarField;
+        }
+
+        /**
+         * Resolves instances being deserialized to the predefined constants.
+         *
+         * @throws InvalidObjectException if the constant could not be resolved.
+         *
+         * @stable ICU 3.8
+         */
+        protected Object readResolve() throws InvalidObjectException {
+            ///CLOVER:OFF
+            if (this.getClass() != DateFormat.Field.class) {
+                throw new InvalidObjectException(
+                    "A subclass of DateFormat.Field must implement readResolve.");
+            }
+            ///CLOVER:ON
+            Object o = FIELD_NAME_MAP.get(this.getName());
+            ///CLOVER:OFF
+            if (o == null) {
+                throw new InvalidObjectException("Unknown attribute name.");
+            }
+            ///CLOVER:ON
+            return o;
+        }
+    }
+
+    private static int getJDKFormatStyle(int icuFormatStyle) {
+        switch (icuFormatStyle) {
+        case DateFormat.FULL:
+            return java.text.DateFormat.FULL;
+        case DateFormat.LONG:
+            return java.text.DateFormat.LONG;
+        case DateFormat.MEDIUM:
+            return java.text.DateFormat.MEDIUM;
+        case DateFormat.SHORT:
+            return java.text.DateFormat.SHORT;
+        default:
+            throw new UnsupportedOperationException("Style not supported by com.ibm.icu.base");
+        }
+    }
+
+
+    protected static FieldPosition toJDKFieldPosition(FieldPosition icuPos) {
+        if (icuPos == null) {
+            return null;
+        }
+
+        int fieldID = icuPos.getField();
+        Format.Field fieldAttribute = icuPos.getFieldAttribute();
+
+        FieldPosition jdkPos = null;
+
+        if (fieldID >= 0) {
+            switch (fieldID) {
+            case ERA_FIELD:
+                fieldID = java.text.DateFormat.ERA_FIELD;
+                break;
+            case YEAR_FIELD:
+                fieldID = java.text.DateFormat.YEAR_FIELD;
+                break;
+            case MONTH_FIELD:
+                fieldID = java.text.DateFormat.MONTH_FIELD;
+                break;
+            case DATE_FIELD:
+                fieldID = java.text.DateFormat.DATE_FIELD;
+                break;
+            case HOUR_OF_DAY1_FIELD:
+                fieldID = java.text.DateFormat.HOUR_OF_DAY1_FIELD;
+                break;
+            case HOUR_OF_DAY0_FIELD:
+                fieldID = java.text.DateFormat.HOUR_OF_DAY0_FIELD;
+                break;
+            case MINUTE_FIELD:
+                fieldID = java.text.DateFormat.MINUTE_FIELD;
+                break;
+            case SECOND_FIELD:
+                fieldID = java.text.DateFormat.SECOND_FIELD;
+                break;
+            case FRACTIONAL_SECOND_FIELD: // MILLISECOND_FIELD
+                fieldID = java.text.DateFormat.MILLISECOND_FIELD;
+                break;
+            case DAY_OF_WEEK_FIELD:
+                fieldID = java.text.DateFormat.DAY_OF_WEEK_FIELD;
+                break;
+            case DAY_OF_YEAR_FIELD:
+                fieldID = java.text.DateFormat.DAY_OF_YEAR_FIELD;
+                break;
+            case DAY_OF_WEEK_IN_MONTH_FIELD:
+                fieldID = java.text.DateFormat.DAY_OF_WEEK_IN_MONTH_FIELD;
+                break;
+            case WEEK_OF_YEAR_FIELD:
+                fieldID = java.text.DateFormat.WEEK_OF_YEAR_FIELD;
+                break;
+            case WEEK_OF_MONTH_FIELD:
+                fieldID = java.text.DateFormat.WEEK_OF_MONTH_FIELD;
+                break;
+            case AM_PM_FIELD:
+                fieldID = java.text.DateFormat.AM_PM_FIELD;
+                break;
+            case HOUR1_FIELD:
+                fieldID = java.text.DateFormat.HOUR1_FIELD;
+                break;
+            case HOUR0_FIELD:
+                fieldID = java.text.DateFormat.HOUR0_FIELD;
+                break;
+            case TIMEZONE_FIELD:
+                fieldID = java.text.DateFormat.TIMEZONE_FIELD;
+                break;
+
+            case YEAR_WOY_FIELD:
+            case DOW_LOCAL_FIELD:
+            case EXTENDED_YEAR_FIELD:
+            case JULIAN_DAY_FIELD:
+            case MILLISECONDS_IN_DAY_FIELD:
+            case TIMEZONE_RFC_FIELD:
+            case TIMEZONE_GENERIC_FIELD:
+            case STANDALONE_DAY_FIELD:
+            case STANDALONE_MONTH_FIELD:
+            case QUARTER_FIELD:
+            case STANDALONE_QUARTER_FIELD:
+            case TIMEZONE_SPECIAL_FIELD:
+                throw new UnsupportedOperationException("Format Field ID not supported by com.ibm.icu.base");
+
+            default:
+                // just let it go
+                break;
+            }
+        }
+
+        if (fieldAttribute != null) {
+            // map field
+            if (fieldAttribute.equals(Field.AM_PM)) {
+                fieldAttribute = java.text.DateFormat.Field.AM_PM;
+            } else if (fieldAttribute.equals(Field.DAY_OF_MONTH)) {
+                fieldAttribute = java.text.DateFormat.Field.DAY_OF_MONTH;
+            } else if (fieldAttribute.equals(Field.DAY_OF_WEEK)) {
+                fieldAttribute = java.text.DateFormat.Field.DAY_OF_WEEK;
+            } else if (fieldAttribute.equals(Field.DAY_OF_WEEK_IN_MONTH)) {
+                fieldAttribute = java.text.DateFormat.Field.DAY_OF_WEEK_IN_MONTH;
+            } else if (fieldAttribute.equals(Field.DAY_OF_YEAR)) {
+                fieldAttribute = java.text.DateFormat.Field.DAY_OF_YEAR;
+            } else if (fieldAttribute.equals(Field.ERA)) {
+                fieldAttribute = java.text.DateFormat.Field.ERA;
+            } else if (fieldAttribute.equals(Field.HOUR_OF_DAY0)) {
+                fieldAttribute = java.text.DateFormat.Field.HOUR_OF_DAY0;
+            } else if (fieldAttribute.equals(Field.HOUR_OF_DAY1)) {
+                fieldAttribute = java.text.DateFormat.Field.HOUR_OF_DAY1;
+            } else if (fieldAttribute.equals(Field.HOUR0)) {
+                fieldAttribute = java.text.DateFormat.Field.HOUR0;
+            } else if (fieldAttribute.equals(Field.HOUR1)) {
+                fieldAttribute = java.text.DateFormat.Field.HOUR1;
+            } else if (fieldAttribute.equals(Field.MILLISECOND)) {
+                fieldAttribute = java.text.DateFormat.Field.MILLISECOND;
+            } else if (fieldAttribute.equals(Field.MINUTE)) {
+                fieldAttribute = java.text.DateFormat.Field.MINUTE;
+            } else if (fieldAttribute.equals(Field.MONTH)) {
+                fieldAttribute = java.text.DateFormat.Field.MONTH;
+            } else if (fieldAttribute.equals(Field.SECOND)) {
+                fieldAttribute = java.text.DateFormat.Field.SECOND;
+            } else if (fieldAttribute.equals(Field.TIME_ZONE)) {
+                fieldAttribute = java.text.DateFormat.Field.TIME_ZONE;
+            } else if (fieldAttribute.equals(Field.WEEK_OF_MONTH)) {
+                fieldAttribute = java.text.DateFormat.Field.WEEK_OF_MONTH;
+            } else if (fieldAttribute.equals(Field.WEEK_OF_YEAR)) {
+                fieldAttribute = java.text.DateFormat.Field.WEEK_OF_YEAR;
+            } else if (fieldAttribute.equals(Field.YEAR)) {
+                fieldAttribute = java.text.DateFormat.Field.YEAR;
+            } else if (fieldAttribute.equals(Field.DOW_LOCAL)
+                    || fieldAttribute.equals(Field.EXTENDED_YEAR)
+                    || fieldAttribute.equals(Field.JULIAN_DAY)
+                    || fieldAttribute.equals(Field.MILLISECONDS_IN_DAY)
+                    || fieldAttribute.equals(Field.YEAR_WOY)
+                    || fieldAttribute.equals(Field.QUARTER)) {
+                // Not supported
+                throw new UnsupportedOperationException("Format Field not supported by com.ibm.icu.base");
+            }
+
+            jdkPos = new FieldPosition(fieldAttribute, fieldID);
+        } else {
+            jdkPos = new FieldPosition(fieldID);
+        }
+
+        jdkPos.setBeginIndex(icuPos.getBeginIndex());
+        jdkPos.setEndIndex(icuPos.getEndIndex());
+
+        return jdkPos;
+    }
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/DateFormatSymbols.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/DateFormatSymbols.java
index ab0f9c9..2cff97c 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/DateFormatSymbols.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/DateFormatSymbols.java
@@ -1,840 +1,861 @@
-/*
- *******************************************************************************
- * Copyright (C) 1996-2011, International Business Machines Corporation and    *
- * others. All Rights Reserved.                                                *
- *******************************************************************************
- */
-
-package com.ibm.icu.text;
-
-import java.io.Serializable;
-import java.util.Locale;
-import java.util.MissingResourceException;
-import java.util.ResourceBundle;
-
-import com.ibm.icu.util.Calendar;
-import com.ibm.icu.util.ULocale;
-
-/**
- * {@icuenhanced java.text.DateFormatSymbols}.{@icu _usage_}
- *
- * <p><code>DateFormatSymbols</code> is a public class for encapsulating
- * localizable date-time formatting data, such as the names of the
- * months, the names of the days of the week, and the time zone data.
- * <code>DateFormat</code> and <code>SimpleDateFormat</code> both use
- * <code>DateFormatSymbols</code> to encapsulate this information.
- *
- * <p>Typically you shouldn't use <code>DateFormatSymbols</code> directly.
- * Rather, you are encouraged to create a date-time formatter with the
- * <code>DateFormat</code> class's factory methods: <code>getTimeInstance</code>,
- * <code>getDateInstance</code>, or <code>getDateTimeInstance</code>.
- * These methods automatically create a <code>DateFormatSymbols</code> for
- * the formatter so that you don't have to. After the
- * formatter is created, you may modify its format pattern using the
- * <code>setPattern</code> method. For more information about
- * creating formatters using <code>DateFormat</code>'s factory methods,
- * see {@link DateFormat}.
- *
- * <p>If you decide to create a date-time formatter with a specific
- * format pattern for a specific locale, you can do so with:
- * <blockquote>
- * <pre>
- * new SimpleDateFormat(aPattern, new DateFormatSymbols(aLocale)).
- * </pre>
- * </blockquote>
- *
- * <p><code>DateFormatSymbols</code> objects are clonable. When you obtain
- * a <code>DateFormatSymbols</code> object, feel free to modify the
- * date-time formatting data. For instance, you can replace the localized
- * date-time format pattern characters with the ones that you feel easy
- * to remember. Or you can change the representative cities
- * to your favorite ones.
- *
- * <p>New <code>DateFormatSymbols</code> subclasses may be added to support
- * <code>SimpleDateFormat</code> for date-time formatting for additional locales.
- *
- * @see          DateFormat
- * @see          SimpleDateFormat
- * @see          com.ibm.icu.util.SimpleTimeZone
- * @author       Chen-Lieh Huang
- * @stable ICU 2.0
- */
-public class DateFormatSymbols implements Serializable, Cloneable {
-
-    private static final long serialVersionUID = 1L;
-    
-    /** @internal */
-    public java.text.DateFormatSymbols dfs;
-        
-    /** @internal */
-    public DateFormatSymbols(java.text.DateFormatSymbols delegate) {
-        this.dfs = delegate;
-    }
-
-    // TODO make sure local pattern char string is 18 characters long,
-    // that is, that it encompasses the new 'u' char for
-    // EXTENDED_YEAR.  Two options: 1. Make sure resource data is
-    // correct; 2. Make code add in 'u' at end if len == 17.
-
-    // Constants for context
-    /**
-     * {@icu} Constant for context.
-     * @stable ICU 3.6
-     */
-    public static final int FORMAT = 0;
-
-    /**
-     * {@icu} Constant for context.
-     * @stable ICU 3.6
-     */
-    public static final int STANDALONE = 1;
-
-    /**
-     * {@icu} Constant for context.
-     * @internal
-     * @deprecated This API is ICU internal only.
-     */
-    public static final int DT_CONTEXT_COUNT = 2;
-
-    // Constants for width
-
-    /**
-     * {@icu} Constant for width.
-     * @stable ICU 3.6
-     */
-    public static final int ABBREVIATED = 0;
-
-    /**
-     * {@icu} Constant for width.
-     * @stable ICU 3.6
-     */
-    public static final int WIDE = 1;
-
-    /**
-     * {@icu} Constant for width.
-     * @stable ICU 3.6
-     */
-    public static final int NARROW = 2;
-
-    /**
-     * {@icu} Constant for width.
-     * @internal
-     * @deprecated This API is ICU internal only.
-     */
-    public static final int DT_WIDTH_COUNT = 3;
-
-    /**
-     * Constructs a DateFormatSymbols object by loading format data from
-     * resources for the default locale.
-     *
-     * @throws java.util.MissingResourceException if the resources for the default locale
-     *          cannot be found or cannot be loaded.
-     * @stable ICU 2.0
-     */
-    public DateFormatSymbols()
-    {
-        this(new java.text.DateFormatSymbols());
-    }
-
-    /**
-     * Constructs a DateFormatSymbols object by loading format data from
-     * resources for the given locale.
-     *
-     * @throws java.util.MissingResourceException if the resources for the specified
-     *          locale cannot be found or cannot be loaded.
-     * @stable ICU 2.0
-     */
-    public DateFormatSymbols(Locale locale)
-    {
-        this(new java.text.DateFormatSymbols(locale));
-    }
-
-    /**
-     * {@icu} Constructs a DateFormatSymbols object by loading format data from
-     * resources for the given ulocale.
-     *
-     * @throws java.util.MissingResourceException if the resources for the specified
-     *          locale cannot be found or cannot be loaded.
-     * @stable ICU 3.2
-     */
-    public DateFormatSymbols(ULocale locale)
-    {
-        this(new java.text.DateFormatSymbols(locale.toLocale()));
-    }
-
-    /**
-     * Returns a DateFormatSymbols instance for the default locale.
-     *
-     * {@icunote} Unlike <code>java.text.DateFormatSymbols#getInstance</code>,
-     * this method simply returns <code>new com.ibm.icu.text.DateFormatSymbols()</code>.
-     * ICU does not support <code>DateFormatSymbolsProvider</code> introduced in Java 6
-     * or its equivalent implementation for now.
-     *
-     * @return A DateFormatSymbols instance.
-     * @stable ICU 3.8
-     */
-    public static DateFormatSymbols getInstance() {
-        return new DateFormatSymbols(java.text.DateFormatSymbols.getInstance());
-    }
-
-    /**
-     * Returns a DateFormatSymbols instance for the given locale.
-     *
-     * {@icunote} Unlike <code>java.text.DateFormatSymbols#getInstance</code>,
-     * this method simply returns <code>new com.ibm.icu.text.DateFormatSymbols(locale)</code>.
-     * ICU does not support <code>DateFormatSymbolsProvider</code> introduced in Java 6
-     * or its equivalent implementation for now.
-     *
-     * @param locale the locale.
-     * @return A DateFormatSymbols instance.
-     * @stable ICU 3.8
-     */
-    public static DateFormatSymbols getInstance(Locale locale) {
-        return new DateFormatSymbols(java.text.DateFormatSymbols.getInstance(locale));
-    }
-
-    /**
-     * {@icu} Returns a DateFormatSymbols instance for the given locale.
-     *
-     * {@icunote} Unlike <code>java.text.DateFormatSymbols#getInstance</code>,
-     * this method simply returns <code>new com.ibm.icu.text.DateFormatSymbols(locale)</code>.
-     * ICU does not support <code>DateFormatSymbolsProvider</code> introduced in Java 6
-     * or its equivalent implementation for now.
-     *
-     * @param locale the locale.
-     * @return A DateFormatSymbols instance.
-     * @stable ICU 3.8
-     */
-    public static DateFormatSymbols getInstance(ULocale locale) {
-        return new DateFormatSymbols(java.text.DateFormatSymbols.getInstance(locale.toLocale()));
-    }
-
-    /**
-     * Returns an array of all locales for which the <code>getInstance</code> methods of
-     * this class can return localized instances.
-     *
-     * {@icunote} Unlike <code>java.text.DateFormatSymbols#getAvailableLocales</code>,
-     * this method simply returns the array of <code>Locale</code>s available in this
-     * class.  ICU does not support <code>DateFormatSymbolsProvider</code> introduced in
-     * Java 6 or its equivalent implementation for now.
-     *
-     * @return An array of <code>Locale</code>s for which localized
-     * <code>DateFormatSymbols</code> instances are available.
-     * @stable ICU 3.8
-     */
-    public static Locale[] getAvailableLocales() {
-        return java.text.DateFormatSymbols.getAvailableLocales();
-    }
-
-    /**
-     * {@icu} Returns an array of all locales for which the <code>getInstance</code>
-     * methods of this class can return localized instances.
-     *
-     * {@icunote} Unlike <code>java.text.DateFormatSymbols#getAvailableLocales</code>,
-     * this method simply returns the array of <code>ULocale</code>s available in this
-     * class.  ICU does not support <code>DateFormatSymbolsProvider</code> introduced in
-     * Java 6 or its equivalent implementation for now.
-     *
-     * @return An array of <code>ULocale</code>s for which localized
-     * <code>DateFormatSymbols</code> instances are available.
-     * @draft ICU 3.8 (retain)
-     * @provisional This API might change or be removed in a future release.
-     */
-    public static ULocale[] getAvailableULocales() {
-        Locale[] locales = java.text.DateFormatSymbols.getAvailableLocales();
-        ULocale[] ulocales = new ULocale[locales.length];
-        for (int i = 0; i < locales.length; ++i) {
-            ulocales[i] = ULocale.forLocale(locales[i]);
-        }
-        return ulocales;
-    }
-
-    /**
-     * Returns era strings. For example: "AD" and "BC".
-     * @return the era strings.
-     * @stable ICU 2.0
-     */
-    public String[] getEras() {
-        return dfs.getEras();
-    }
-
-    /**
-     * Sets era strings. For example: "AD" and "BC".
-     * @param newEras the new era strings.
-     * @stable ICU 2.0
-     */
-    public void setEras(String[] newEras) {
-        dfs.setEras(newEras);
-    }
-
-    /**
-     * {@icu} Returns era name strings. For example: "Anno Domini" and "Before Christ".
-     * @return the era strings.
-     * @stable ICU 3.4
-     */
-    public String[] getEraNames() {
-        return getEras(); // Java has no distinction between era strings and era name strings
-    }
-
-    /**
-     * {@icu} Sets era name strings. For example: "Anno Domini" and "Before Christ".
-     * @param newEraNames the new era strings.
-     * @stable ICU 3.8
-     */
-    public void setEraNames(String[] newEraNames) {
-        setEras(newEraNames); // Java has no distinction between era strings and era name strings
-    }
-
-    /**
-     * Returns month strings. For example: "January", "February", etc.
-     * @return the month strings.
-     * @stable ICU 2.0
-     */
-    public String[] getMonths() {
-        return dfs.getMonths();
-    }
-
-    /**
-     * Returns month strings. For example: "January", "February", etc.
-     * @param context    The month context, FORMAT or STANDALONE.
-     * @param width      The width or the returned month string,
-     *                   either WIDE, ABBREVIATED, or NARROW.
-     * @return the month strings.
-     * @stable ICU 3.4
-     */
-    public String[] getMonths(int context, int width) {
-        // JDK does not support context / narrow months
-        switch (width) {
-        case WIDE:
-            return dfs.getMonths();
-
-        case ABBREVIATED:
-        case NARROW:
-            return dfs.getShortMonths();
-
-        default:
-            throw new IllegalArgumentException("Unsupported width argument value");
-        }
-    }
-
-    /**
-     * Sets month strings. For example: "January", "February", etc.
-     * @param newMonths the new month strings.
-     * @stable ICU 2.0
-     */
-    public void setMonths(String[] newMonths) {
-        dfs.setMonths(newMonths);
-    }
-
-    /**
-     * Sets month strings. For example: "January", "February", etc.
-     * @param newMonths the new month strings.
-     * @param context    The formatting context, FORMAT or STANDALONE.
-     * @param width      The width of the month string,
-     *                   either WIDE, ABBREVIATED, or NARROW.
-     * @stable ICU 3.8
-     */
-    public void setMonths(String[] newMonths, int context, int width) {
-        // JDK does not support context / narrow months
-        switch (width) {
-        case WIDE:
-            dfs.setMonths(newMonths);
-            break;
-
-        case ABBREVIATED:
-        case NARROW:
-            dfs.setShortMonths(newMonths);
-            break;
-
-        default:
-            throw new IllegalArgumentException("Unsupported width argument value");
-        }
-    }
-
-    /**
-     * Returns short month strings. For example: "Jan", "Feb", etc.
-     * @return the short month strings.
-     * @stable ICU 2.0
-     */
-    public String[] getShortMonths() {
-        return dfs.getShortMonths();
-    }
-
-    /**
-     * Sets short month strings. For example: "Jan", "Feb", etc.
-     * @param newShortMonths the new short month strings.
-     * @stable ICU 2.0
-     */
-    public void setShortMonths(String[] newShortMonths) {
-        dfs.setShortMonths(newShortMonths);
-    }
-
-    /**
-     * Returns weekday strings. For example: "Sunday", "Monday", etc.
-     * @return the weekday strings. Use <code>Calendar.SUNDAY</code>,
-     * <code>Calendar.MONDAY</code>, etc. to index the result array.
-     * @stable ICU 2.0
-     */
-    public String[] getWeekdays() {
-        return dfs.getWeekdays();
-    }
-
-    /**
-     * Returns weekday strings. For example: "Sunday", "Monday", etc.
-     * @return the weekday strings. Use <code>Calendar.SUNDAY</code>,
-     * <code>Calendar.MONDAY</code>, etc. to index the result array.
-     * @param context    Formatting context, either FORMAT or STANDALONE.
-     * @param width      Width of strings to be returned, either
-     *                   WIDE, ABBREVIATED, or NARROW
-     * @stable ICU 3.4
-     */
-    public String[] getWeekdays(int context, int width) {
-        // JDK does not support context / narrow weekdays
-        switch (width) {
-        case WIDE:
-            return dfs.getWeekdays();
-
-        case ABBREVIATED:
-        case NARROW:
-            return dfs.getShortWeekdays();
-
-        default:
-            throw new IllegalArgumentException("Unsupported width argument value");
-        }
-    }
-
-    /**
-     * Sets weekday strings. For example: "Sunday", "Monday", etc.
-     * @param newWeekdays The new weekday strings.
-     * @param context     The formatting context, FORMAT or STANDALONE.
-     * @param width       The width of the strings,
-     *                    either WIDE, ABBREVIATED, or NARROW.
-     * @stable ICU 3.8
-     */
-    public void setWeekdays(String[] newWeekdays, int context, int width) {
-        // JDK does not support context / narrow weekdays
-        switch (width) {
-        case WIDE:
-            dfs.setWeekdays(newWeekdays);
-            break;
-
-        case ABBREVIATED:
-        case NARROW:
-            dfs.setShortWeekdays(newWeekdays);
-            break;
-
-        default:
-            throw new IllegalArgumentException("Unsupported width argument value");
-        }
-    }
-
-    /**
-     * Sets weekday strings. For example: "Sunday", "Monday", etc.
-     * @param newWeekdays the new weekday strings. The array should
-     * be indexed by <code>Calendar.SUNDAY</code>,
-     * <code>Calendar.MONDAY</code>, etc.
-     * @stable ICU 2.0
-     */
-    public void setWeekdays(String[] newWeekdays) {
-        dfs.setWeekdays(newWeekdays);
-    }
-
-    /**
-     * Returns short weekday strings. For example: "Sun", "Mon", etc.
-     * @return the short weekday strings. Use <code>Calendar.SUNDAY</code>,
-     * <code>Calendar.MONDAY</code>, etc. to index the result array.
-     * @stable ICU 2.0
-     */
-    public String[] getShortWeekdays() {
-        return dfs.getShortWeekdays();
-    }
-
-    /**
-     * Sets short weekday strings. For example: "Sun", "Mon", etc.
-     * @param newShortWeekdays the new short weekday strings. The array should
-     * be indexed by <code>Calendar.SUNDAY</code>,
-     * <code>Calendar.MONDAY</code>, etc.
-     * @stable ICU 2.0
-     */
-    public void setShortWeekdays(String[] newShortWeekdays) {
-        dfs.setShortWeekdays(newShortWeekdays);
-    }
-    /**
-     * {@icu} Returns quarter strings. For example: "1st Quarter", "2nd Quarter", etc.
-     * @param context    The quarter context, FORMAT or STANDALONE.
-     * @param width      The width or the returned quarter string,
-     *                   either WIDE or ABBREVIATED. There are no NARROW quarters.
-     * @return the quarter strings.
-     * @stable ICU 3.6
-     */
-    public String[] getQuarters(int context, int width) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Sets quarter strings. For example: "1st Quarter", "2nd Quarter", etc.
-     * @param newQuarters the new quarter strings.
-     * @param context    The formatting context, FORMAT or STANDALONE.
-     * @param width      The width of the quarter string,
-     *                   either WIDE or ABBREVIATED. There are no NARROW quarters.
-     * @stable ICU 3.8
-     */
-    public void setQuarters(String[] newQuarters, int context, int width) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Returns am/pm strings. For example: "AM" and "PM".
-     * @return the weekday strings.
-     * @stable ICU 2.0
-     */
-    public String[] getAmPmStrings() {
-        return dfs.getAmPmStrings();
-    }
-
-    /**
-     * Sets am/pm strings. For example: "AM" and "PM".
-     * @param newAmpms the new ampm strings.
-     * @stable ICU 2.0
-     */
-    public void setAmPmStrings(String[] newAmpms) {
-        dfs.setAmPmStrings(newAmpms);
-    }
-
-    /**
-     * Returns timezone strings.
-     * @return the timezone strings.
-     * @stable ICU 2.0
-     */
-    public String[][] getZoneStrings() {
-        return dfs.getZoneStrings();
-    }
-
-    /**
-     * Sets timezone strings.
-     * @param newZoneStrings the new timezone strings.
-     * @stable ICU 2.0
-     */
-    public void setZoneStrings(String[][] newZoneStrings) {
-        dfs.setZoneStrings(newZoneStrings);
-    }
-
-    /**
-     * Returns localized date-time pattern characters. For example: 'u', 't', etc.
-     *
-     * <p>Note: ICU no longer provides localized date-time pattern characters for a locale
-     * starting ICU 3.8.  This method returns the non-localized date-time pattern
-     * characters unless user defined localized data is set by setLocalPatternChars.
-     * @return the localized date-time pattern characters.
-     * @stable ICU 2.0
-     */
-    public String getLocalPatternChars() {
-        return dfs.getLocalPatternChars();
-    }
-
-    /**
-     * Sets localized date-time pattern characters. For example: 'u', 't', etc.
-     * @param newLocalPatternChars the new localized date-time
-     * pattern characters.
-     * @stable ICU 2.0
-     */
-    public void setLocalPatternChars(String newLocalPatternChars) {
-        dfs.setLocalPatternChars(newLocalPatternChars);
-    }
-
-    /**
-     * Overrides clone.
-     * @stable ICU 2.0
-     */
-    public Object clone()
-    {
-        return new DateFormatSymbols((java.text.DateFormatSymbols)dfs.clone());
-    }
-
-    /**
-     * Override hashCode.
-     * Generates a hash code for the DateFormatSymbols object.
-     * @stable ICU 2.0
-     */
-    public int hashCode() {
-        return dfs.hashCode();
-    }
-
-    /**
-     * Overrides equals.
-     * @stable ICU 2.0
-     */
-    public boolean equals(Object obj)
-    {
-        try {
-            return dfs.equals(((DateFormatSymbols)obj).dfs);
-        }
-        catch (Exception e) {
-            return false;
-        }
-    }
-
-    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-    /**
-     * Returns the {@link DateFormatSymbols} object that should be used to format a
-     * calendar system's dates in the given locale.
-     * <p>
-     * <b>Subclassing:</b><br>
-     * When creating a new Calendar subclass, you must create the
-     * {@link ResourceBundle ResourceBundle}
-     * containing its {@link DateFormatSymbols DateFormatSymbols} in a specific place.
-     * The resource bundle name is based on the calendar's fully-specified
-     * class name, with ".resources" inserted at the end of the package name
-     * (just before the class name) and "Symbols" appended to the end.
-     * For example, the bundle corresponding to "com.ibm.icu.util.HebrewCalendar"
-     * is "com.ibm.icu.impl.data.HebrewCalendarSymbols".
-     * <p>
-     * Within the ResourceBundle, this method searches for five keys:
-     * <ul>
-     * <li><b>DayNames</b> -
-     *      An array of strings corresponding to each possible
-     *      value of the <code>DAY_OF_WEEK</code> field.  Even though
-     *      <code>DAY_OF_WEEK</code> starts with <code>SUNDAY</code> = 1,
-     *      This array is 0-based; the name for Sunday goes in the
-     *      first position, at index 0.  If this key is not found
-     *      in the bundle, the day names are inherited from the
-     *      default <code>DateFormatSymbols</code> for the requested locale.
-     *
-     * <li><b>DayAbbreviations</b> -
-     *      An array of abbreviated day names corresponding
-     *      to the values in the "DayNames" array.  If this key
-     *      is not found in the resource bundle, the "DayNames"
-     *      values are used instead.  If neither key is found,
-     *      the day abbreviations are inherited from the default
-     *      <code>DateFormatSymbols</code> for the locale.
-     *
-     * <li><b>MonthNames</b> -
-     *      An array of strings corresponding to each possible
-     *      value of the <code>MONTH</code> field.  If this key is not found
-     *      in the bundle, the month names are inherited from the
-     *      default <code>DateFormatSymbols</code> for the requested locale.
-     *
-     * <li><b>MonthAbbreviations</b> -
-     *      An array of abbreviated day names corresponding
-     *      to the values in the "MonthNames" array.  If this key
-     *      is not found in the resource bundle, the "MonthNames"
-     *      values are used instead.  If neither key is found,
-     *      the day abbreviations are inherited from the default
-     *      <code>DateFormatSymbols</code> for the locale.
-     *
-     * <li><b>Eras</b> -
-     *      An array of strings corresponding to each possible
-     *      value of the <code>ERA</code> field.  If this key is not found
-     *      in the bundle, the era names are inherited from the
-     *      default <code>DateFormatSymbols</code> for the requested locale.
-     * </ul>
-     * <p>
-     * @param cal       The calendar system whose date format symbols are desired.
-     * @param locale    The locale whose symbols are desired.
-     *
-     * @see DateFormatSymbols#DateFormatSymbols(java.util.Locale)
-     * @stable ICU 2.0
-     */
-    public DateFormatSymbols(Calendar cal, Locale locale) {
-        throw new UnsupportedOperationException("Constructor not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Returns the {@link DateFormatSymbols} object that should be used to format a
-     * calendar system's dates in the given locale.
-     * <p>
-     * <b>Subclassing:</b><br>
-     * When creating a new Calendar subclass, you must create the
-     * {@link ResourceBundle ResourceBundle}
-     * containing its {@link DateFormatSymbols DateFormatSymbols} in a specific place.
-     * The resource bundle name is based on the calendar's fully-specified
-     * class name, with ".resources" inserted at the end of the package name
-     * (just before the class name) and "Symbols" appended to the end.
-     * For example, the bundle corresponding to "com.ibm.icu.util.HebrewCalendar"
-     * is "com.ibm.icu.impl.data.HebrewCalendarSymbols".
-     * <p>
-     * Within the ResourceBundle, this method searches for five keys:
-     * <ul>
-     * <li><b>DayNames</b> -
-     *      An array of strings corresponding to each possible
-     *      value of the <code>DAY_OF_WEEK</code> field.  Even though
-     *      <code>DAY_OF_WEEK</code> starts with <code>SUNDAY</code> = 1,
-     *      This array is 0-based; the name for Sunday goes in the
-     *      first position, at index 0.  If this key is not found
-     *      in the bundle, the day names are inherited from the
-     *      default <code>DateFormatSymbols</code> for the requested locale.
-     *
-     * <li><b>DayAbbreviations</b> -
-     *      An array of abbreviated day names corresponding
-     *      to the values in the "DayNames" array.  If this key
-     *      is not found in the resource bundle, the "DayNames"
-     *      values are used instead.  If neither key is found,
-     *      the day abbreviations are inherited from the default
-     *      <code>DateFormatSymbols</code> for the locale.
-     *
-     * <li><b>MonthNames</b> -
-     *      An array of strings corresponding to each possible
-     *      value of the <code>MONTH</code> field.  If this key is not found
-     *      in the bundle, the month names are inherited from the
-     *      default <code>DateFormatSymbols</code> for the requested locale.
-     *
-     * <li><b>MonthAbbreviations</b> -
-     *      An array of abbreviated day names corresponding
-     *      to the values in the "MonthNames" array.  If this key
-     *      is not found in the resource bundle, the "MonthNames"
-     *      values are used instead.  If neither key is found,
-     *      the day abbreviations are inherited from the default
-     *      <code>DateFormatSymbols</code> for the locale.
-     *
-     * <li><b>Eras</b> -
-     *      An array of strings corresponding to each possible
-     *      value of the <code>ERA</code> field.  If this key is not found
-     *      in the bundle, the era names are inherited from the
-     *      default <code>DateFormatSymbols</code> for the requested locale.
-     * </ul>
-     * <p>
-     * @param cal       The calendar system whose date format symbols are desired.
-     * @param locale    The ulocale whose symbols are desired.
-     *
-     * @see DateFormatSymbols#DateFormatSymbols(java.util.Locale)
-     * @stable ICU 3.2
-     */
-    public DateFormatSymbols(Calendar cal, ULocale locale) {
-        throw new UnsupportedOperationException("Constructor not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Variant of DateFormatSymbols(Calendar, Locale) that takes the Calendar class
-     * instead of a Calandar instance.
-     * @see #DateFormatSymbols(Calendar, Locale)
-     * @stable ICU 2.2
-     */
-    public DateFormatSymbols(Class<? extends Calendar> calendarClass, Locale locale) {
-        throw new UnsupportedOperationException("Constructor not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Variant of DateFormatSymbols(Calendar, ULocale) that takes the Calendar class
-     * instead of a Calandar instance.
-     * @see #DateFormatSymbols(Calendar, Locale)
-     * @stable ICU 3.2
-     */
-    public DateFormatSymbols(Class<? extends Calendar> calendarClass, ULocale locale) {
-        throw new UnsupportedOperationException("Constructor not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Fetches a custom calendar's DateFormatSymbols out of the given resource
-     * bundle.  Symbols that are not overridden are inherited from the
-     * default DateFormatSymbols for the locale.
-     * @see DateFormatSymbols#DateFormatSymbols(java.util.Locale)
-     * @stable ICU 2.0
-     */
-    public DateFormatSymbols(ResourceBundle bundle, Locale locale) {
-        throw new UnsupportedOperationException("Constructor not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Fetches a custom calendar's DateFormatSymbols out of the given resource
-     * bundle.  Symbols that are not overridden are inherited from the
-     * default DateFormatSymbols for the locale.
-     * @see DateFormatSymbols#DateFormatSymbols(java.util.Locale)
-     * @stable ICU 3.2
-     */
-    public DateFormatSymbols(ResourceBundle bundle, ULocale locale) {
-        throw new UnsupportedOperationException("Constructor not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Finds the ResourceBundle containing the date format information for
-     * a specified calendar subclass in a given locale.
-     * <p>
-     * The resource bundle name is based on the calendar's fully-specified
-     * class name, with ".resources" inserted at the end of the package name
-     * (just before the class name) and "Symbols" appended to the end.
-     * For example, the bundle corresponding to "com.ibm.icu.util.HebrewCalendar"
-     * is "com.ibm.icu.impl.data.HebrewCalendarSymbols".
-     * <p>
-     * <b>Note:</b>Because of the structural changes in the ICU locale bundle,
-     * this API no longer works as described.  This method always returns null.
-     * @deprecated ICU 4.0
-     */
-    // This API was formerly @stable ICU 2.0
-    static public ResourceBundle getDateFormatBundle(Class<? extends Calendar> calendarClass,
-                                                     Locale locale) throws MissingResourceException {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");    }
-
-    /**
-     * Finds the ResourceBundle containing the date format information for
-     * a specified calendar subclass in a given locale.
-     * <p>
-     * The resource bundle name is based on the calendar's fully-specified
-     * class name, with ".resources" inserted at the end of the package name
-     * (just before the class name) and "Symbols" appended to the end.
-     * For example, the bundle corresponding to "com.ibm.icu.util.HebrewCalendar"
-     * is "com.ibm.icu.impl.data.HebrewCalendarSymbols".
-     * <p>
-     * <b>Note:</b>Because of the structural changes in the ICU locale bundle,
-     * this API no longer works as described.  This method always returns null.
-     * @deprecated ICU 4.0
-     */
-    // This API was formerly @stable ICU 3.2
-    static public ResourceBundle getDateFormatBundle(Class<? extends Calendar> calendarClass,
-                                                     ULocale locale) throws MissingResourceException {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");    }
-
-    /**
-     * Variant of getDateFormatBundle(java.lang.Class, java.util.Locale) that takes
-     * a Calendar instance instead of a Calendar class.
-     * <p>
-     * <b>Note:</b>Because of the structural changes in the ICU locale bundle,
-     * this API no longer works as described.  This method always returns null.
-     * @see #getDateFormatBundle(java.lang.Class, java.util.Locale)
-     * @deprecated ICU 4.0
-     */
-    // This API was formerly @stable ICU 2.2
-    public static ResourceBundle getDateFormatBundle(Calendar cal, Locale locale) throws MissingResourceException {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");    }
-
-    /**
-     * Variant of getDateFormatBundle(java.lang.Class, java.util.Locale) that takes
-     * a Calendar instance instead of a Calendar class.
-     * <p>
-     * <b>Note:</b>Because of the structural changes in the ICU locale bundle,
-     * this API no longer works as described.  This method always returns null.
-     * @see #getDateFormatBundle(java.lang.Class, java.util.Locale)
-     * @deprecated ICU 4.0
-     */
-    // This API was formerly @stable ICU 3.2
-    public static ResourceBundle getDateFormatBundle(Calendar cal, ULocale locale) throws MissingResourceException {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");    }
-
-    /**
-     * Returns the locale that was used to create this object, or null.
-     * This may may differ from the locale requested at the time of
-     * this object's creation.  For example, if an object is created
-     * for locale <tt>en_US_CALIFORNIA</tt>, the actual data may be
-     * drawn from <tt>en</tt> (the <i>actual</i> locale), and
-     * <tt>en_US</tt> may be the most specific locale that exists (the
-     * <i>valid</i> locale).
-     *
-     * <p>Note: This method will be implemented in ICU 3.0; ICU 2.8
-     * contains a partial preview implementation.  The * <i>actual</i>
-     * locale is returned correctly, but the <i>valid</i> locale is
-     * not, in most cases.
-     * @param type type of information requested, either {@link
-     * com.ibm.icu.util.ULocale#VALID_LOCALE} or {@link
-     * com.ibm.icu.util.ULocale#ACTUAL_LOCALE}.
-     * @return the information specified by <i>type</i>, or null if
-     * this object was not constructed from locale data.
-     * @see com.ibm.icu.util.ULocale
-     * @see com.ibm.icu.util.ULocale#VALID_LOCALE
-     * @see com.ibm.icu.util.ULocale#ACTUAL_LOCALE
-     * @draft ICU 2.8 (retain)
-     * @provisional This API might change or be removed in a future release.
-     */
-    public final ULocale getLocale(ULocale.Type type) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-}
+/*
+ *******************************************************************************
+ * Copyright (C) 1996-2011, International Business Machines Corporation and    *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+
+package com.ibm.icu.text;
+
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+import com.ibm.icu.util.Calendar;
+import com.ibm.icu.util.ULocale;
+
+/**
+ * {@icuenhanced java.text.DateFormatSymbols}.{@icu _usage_}
+ *
+ * <p><code>DateFormatSymbols</code> is a public class for encapsulating
+ * localizable date-time formatting data, such as the names of the
+ * months, the names of the days of the week, and the time zone data.
+ * <code>DateFormat</code> and <code>SimpleDateFormat</code> both use
+ * <code>DateFormatSymbols</code> to encapsulate this information.
+ *
+ * <p>Typically you shouldn't use <code>DateFormatSymbols</code> directly.
+ * Rather, you are encouraged to create a date-time formatter with the
+ * <code>DateFormat</code> class's factory methods: <code>getTimeInstance</code>,
+ * <code>getDateInstance</code>, or <code>getDateTimeInstance</code>.
+ * These methods automatically create a <code>DateFormatSymbols</code> for
+ * the formatter so that you don't have to. After the
+ * formatter is created, you may modify its format pattern using the
+ * <code>setPattern</code> method. For more information about
+ * creating formatters using <code>DateFormat</code>'s factory methods,
+ * see {@link DateFormat}.
+ *
+ * <p>If you decide to create a date-time formatter with a specific
+ * format pattern for a specific locale, you can do so with:
+ * <blockquote>
+ * <pre>
+ * new SimpleDateFormat(aPattern, new DateFormatSymbols(aLocale)).
+ * </pre>
+ * </blockquote>
+ *
+ * <p><code>DateFormatSymbols</code> objects are clonable. When you obtain
+ * a <code>DateFormatSymbols</code> object, feel free to modify the
+ * date-time formatting data. For instance, you can replace the localized
+ * date-time format pattern characters with the ones that you feel easy
+ * to remember. Or you can change the representative cities
+ * to your favorite ones.
+ *
+ * <p>New <code>DateFormatSymbols</code> subclasses may be added to support
+ * <code>SimpleDateFormat</code> for date-time formatting for additional locales.
+ *
+ * @see          DateFormat
+ * @see          SimpleDateFormat
+ * @see          com.ibm.icu.util.SimpleTimeZone
+ * @author       Chen-Lieh Huang
+ * @stable ICU 2.0
+ */
+public class DateFormatSymbols implements Serializable, Cloneable {
+
+    private static final long serialVersionUID = 1L;
+    
+    /** @internal */
+    public java.text.DateFormatSymbols dfs;
+        
+    /** @internal */
+    public DateFormatSymbols(java.text.DateFormatSymbols delegate) {
+        this.dfs = delegate;
+    }
+
+    // TODO make sure local pattern char string is 18 characters long,
+    // that is, that it encompasses the new 'u' char for
+    // EXTENDED_YEAR.  Two options: 1. Make sure resource data is
+    // correct; 2. Make code add in 'u' at end if len == 17.
+
+    // Constants for context
+    /**
+     * {@icu} Constant for context.
+     * @stable ICU 3.6
+     */
+    public static final int FORMAT = 0;
+
+    /**
+     * {@icu} Constant for context.
+     * @stable ICU 3.6
+     */
+    public static final int STANDALONE = 1;
+
+    /**
+     * {@icu} Constant for context.
+     * @internal
+     * @deprecated This API is ICU internal only.
+     */
+    public static final int DT_CONTEXT_COUNT = 2;
+
+    // Constants for width
+
+    /**
+     * {@icu} Constant for width.
+     * @stable ICU 3.6
+     */
+    public static final int ABBREVIATED = 0;
+
+    /**
+     * {@icu} Constant for width.
+     * @stable ICU 3.6
+     */
+    public static final int WIDE = 1;
+
+    /**
+     * {@icu} Constant for width.
+     * @stable ICU 3.6
+     */
+    public static final int NARROW = 2;
+
+    /**
+     * {@icu} Constant for width.
+     * @internal
+     * @deprecated This API is ICU internal only.
+     */
+    public static final int DT_WIDTH_COUNT = 3;
+
+    /**
+     * Constructs a DateFormatSymbols object by loading format data from
+     * resources for the default locale.
+     *
+     * @throws java.util.MissingResourceException if the resources for the default locale
+     *          cannot be found or cannot be loaded.
+     * @stable ICU 2.0
+     */
+    public DateFormatSymbols()
+    {
+        this(new java.text.DateFormatSymbols());
+    }
+
+    /**
+     * Constructs a DateFormatSymbols object by loading format data from
+     * resources for the given locale.
+     *
+     * @throws java.util.MissingResourceException if the resources for the specified
+     *          locale cannot be found or cannot be loaded.
+     * @stable ICU 2.0
+     */
+    public DateFormatSymbols(Locale locale)
+    {
+        this(new java.text.DateFormatSymbols(locale));
+    }
+
+    /**
+     * {@icu} Constructs a DateFormatSymbols object by loading format data from
+     * resources for the given ulocale.
+     *
+     * @throws java.util.MissingResourceException if the resources for the specified
+     *          locale cannot be found or cannot be loaded.
+     * @stable ICU 3.2
+     */
+    public DateFormatSymbols(ULocale locale)
+    {
+        this(new java.text.DateFormatSymbols(locale.toLocale()));
+    }
+
+    /**
+     * Returns a DateFormatSymbols instance for the default locale.
+     *
+     * {@icunote} Unlike <code>java.text.DateFormatSymbols#getInstance</code>,
+     * this method simply returns <code>new com.ibm.icu.text.DateFormatSymbols()</code>.
+     * ICU does not support <code>DateFormatSymbolsProvider</code> introduced in Java 6
+     * or its equivalent implementation for now.
+     *
+     * @return A DateFormatSymbols instance.
+     * @stable ICU 3.8
+     */
+    public static DateFormatSymbols getInstance() {
+        return new DateFormatSymbols(new java.text.DateFormatSymbols());
+    }
+
+    /**
+     * Returns a DateFormatSymbols instance for the given locale.
+     *
+     * {@icunote} Unlike <code>java.text.DateFormatSymbols#getInstance</code>,
+     * this method simply returns <code>new com.ibm.icu.text.DateFormatSymbols(locale)</code>.
+     * ICU does not support <code>DateFormatSymbolsProvider</code> introduced in Java 6
+     * or its equivalent implementation for now.
+     *
+     * @param locale the locale.
+     * @return A DateFormatSymbols instance.
+     * @stable ICU 3.8
+     */
+    public static DateFormatSymbols getInstance(Locale locale) {
+        return new DateFormatSymbols(new java.text.DateFormatSymbols(locale));
+    }
+
+    /**
+     * {@icu} Returns a DateFormatSymbols instance for the given locale.
+     *
+     * {@icunote} Unlike <code>java.text.DateFormatSymbols#getInstance</code>,
+     * this method simply returns <code>new com.ibm.icu.text.DateFormatSymbols(locale)</code>.
+     * ICU does not support <code>DateFormatSymbolsProvider</code> introduced in Java 6
+     * or its equivalent implementation for now.
+     *
+     * @param locale the locale.
+     * @return A DateFormatSymbols instance.
+     * @stable ICU 3.8
+     */
+    public static DateFormatSymbols getInstance(ULocale locale) {
+        return new DateFormatSymbols(new java.text.DateFormatSymbols(locale.toLocale()));
+    }
+
+    /**
+     * Returns an array of all locales for which the <code>getInstance</code> methods of
+     * this class can return localized instances.
+     *
+     * {@icunote} Unlike <code>java.text.DateFormatSymbols#getAvailableLocales</code>,
+     * this method simply returns the array of <code>Locale</code>s available in this
+     * class.  ICU does not support <code>DateFormatSymbolsProvider</code> introduced in
+     * Java 6 or its equivalent implementation for now.
+     *
+     * @return An array of <code>Locale</code>s for which localized
+     * <code>DateFormatSymbols</code> instances are available.
+     * @stable ICU 3.8
+     */
+    public static Locale[] getAvailableLocales() {
+        Locale[] avlocs = null;
+        boolean isJava5 = true;
+        try {
+            Method mGetAvailableLocales = java.text.DateFormatSymbols.class.getMethod("getAvailableLocales", (Class[])null);
+            avlocs = (Locale[]) mGetAvailableLocales.invoke(null, (Object[]) null);
+            isJava5 = false;
+        } catch (NoSuchMethodException nsme) {
+            // fall through
+        } catch (InvocationTargetException ite) {
+            // fall through
+        } catch (IllegalAccessException iae) {
+            // fall through
+        }
+
+        if (isJava5) {
+            // Use DateFormat's getAvailableLocales as fallback
+           avlocs = DateFormat.getAvailableLocales();
+        }
+
+        return avlocs;
+    }
+
+    /**
+     * {@icu} Returns an array of all locales for which the <code>getInstance</code>
+     * methods of this class can return localized instances.
+     *
+     * {@icunote} Unlike <code>java.text.DateFormatSymbols#getAvailableLocales</code>,
+     * this method simply returns the array of <code>ULocale</code>s available in this
+     * class.  ICU does not support <code>DateFormatSymbolsProvider</code> introduced in
+     * Java 6 or its equivalent implementation for now.
+     *
+     * @return An array of <code>ULocale</code>s for which localized
+     * <code>DateFormatSymbols</code> instances are available.
+     * @draft ICU 3.8 (retain)
+     * @provisional This API might change or be removed in a future release.
+     */
+    public static ULocale[] getAvailableULocales() {
+        Locale[] locales = getAvailableLocales();
+        ULocale[] ulocales = new ULocale[locales.length];
+        for (int i = 0; i < locales.length; ++i) {
+            ulocales[i] = ULocale.forLocale(locales[i]);
+        }
+        return ulocales;
+    }
+
+    /**
+     * Returns era strings. For example: "AD" and "BC".
+     * @return the era strings.
+     * @stable ICU 2.0
+     */
+    public String[] getEras() {
+        return dfs.getEras();
+    }
+
+    /**
+     * Sets era strings. For example: "AD" and "BC".
+     * @param newEras the new era strings.
+     * @stable ICU 2.0
+     */
+    public void setEras(String[] newEras) {
+        dfs.setEras(newEras);
+    }
+
+    /**
+     * {@icu} Returns era name strings. For example: "Anno Domini" and "Before Christ".
+     * @return the era strings.
+     * @stable ICU 3.4
+     */
+    public String[] getEraNames() {
+        return getEras(); // Java has no distinction between era strings and era name strings
+    }
+
+    /**
+     * {@icu} Sets era name strings. For example: "Anno Domini" and "Before Christ".
+     * @param newEraNames the new era strings.
+     * @stable ICU 3.8
+     */
+    public void setEraNames(String[] newEraNames) {
+        setEras(newEraNames); // Java has no distinction between era strings and era name strings
+    }
+
+    /**
+     * Returns month strings. For example: "January", "February", etc.
+     * @return the month strings.
+     * @stable ICU 2.0
+     */
+    public String[] getMonths() {
+        return dfs.getMonths();
+    }
+
+    /**
+     * Returns month strings. For example: "January", "February", etc.
+     * @param context    The month context, FORMAT or STANDALONE.
+     * @param width      The width or the returned month string,
+     *                   either WIDE, ABBREVIATED, or NARROW.
+     * @return the month strings.
+     * @stable ICU 3.4
+     */
+    public String[] getMonths(int context, int width) {
+        // JDK does not support context / narrow months
+        switch (width) {
+        case WIDE:
+            return dfs.getMonths();
+
+        case ABBREVIATED:
+        case NARROW:
+            return dfs.getShortMonths();
+
+        default:
+            throw new IllegalArgumentException("Unsupported width argument value");
+        }
+    }
+
+    /**
+     * Sets month strings. For example: "January", "February", etc.
+     * @param newMonths the new month strings.
+     * @stable ICU 2.0
+     */
+    public void setMonths(String[] newMonths) {
+        dfs.setMonths(newMonths);
+    }
+
+    /**
+     * Sets month strings. For example: "January", "February", etc.
+     * @param newMonths the new month strings.
+     * @param context    The formatting context, FORMAT or STANDALONE.
+     * @param width      The width of the month string,
+     *                   either WIDE, ABBREVIATED, or NARROW.
+     * @stable ICU 3.8
+     */
+    public void setMonths(String[] newMonths, int context, int width) {
+        // JDK does not support context / narrow months
+        switch (width) {
+        case WIDE:
+            dfs.setMonths(newMonths);
+            break;
+
+        case ABBREVIATED:
+        case NARROW:
+            dfs.setShortMonths(newMonths);
+            break;
+
+        default:
+            throw new IllegalArgumentException("Unsupported width argument value");
+        }
+    }
+
+    /**
+     * Returns short month strings. For example: "Jan", "Feb", etc.
+     * @return the short month strings.
+     * @stable ICU 2.0
+     */
+    public String[] getShortMonths() {
+        return dfs.getShortMonths();
+    }
+
+    /**
+     * Sets short month strings. For example: "Jan", "Feb", etc.
+     * @param newShortMonths the new short month strings.
+     * @stable ICU 2.0
+     */
+    public void setShortMonths(String[] newShortMonths) {
+        dfs.setShortMonths(newShortMonths);
+    }
+
+    /**
+     * Returns weekday strings. For example: "Sunday", "Monday", etc.
+     * @return the weekday strings. Use <code>Calendar.SUNDAY</code>,
+     * <code>Calendar.MONDAY</code>, etc. to index the result array.
+     * @stable ICU 2.0
+     */
+    public String[] getWeekdays() {
+        return dfs.getWeekdays();
+    }
+
+    /**
+     * Returns weekday strings. For example: "Sunday", "Monday", etc.
+     * @return the weekday strings. Use <code>Calendar.SUNDAY</code>,
+     * <code>Calendar.MONDAY</code>, etc. to index the result array.
+     * @param context    Formatting context, either FORMAT or STANDALONE.
+     * @param width      Width of strings to be returned, either
+     *                   WIDE, ABBREVIATED, or NARROW
+     * @stable ICU 3.4
+     */
+    public String[] getWeekdays(int context, int width) {
+        // JDK does not support context / narrow weekdays
+        switch (width) {
+        case WIDE:
+            return dfs.getWeekdays();
+
+        case ABBREVIATED:
+        case NARROW:
+            return dfs.getShortWeekdays();
+
+        default:
+            throw new IllegalArgumentException("Unsupported width argument value");
+        }
+    }
+
+    /**
+     * Sets weekday strings. For example: "Sunday", "Monday", etc.
+     * @param newWeekdays The new weekday strings.
+     * @param context     The formatting context, FORMAT or STANDALONE.
+     * @param width       The width of the strings,
+     *                    either WIDE, ABBREVIATED, or NARROW.
+     * @stable ICU 3.8
+     */
+    public void setWeekdays(String[] newWeekdays, int context, int width) {
+        // JDK does not support context / narrow weekdays
+        switch (width) {
+        case WIDE:
+            dfs.setWeekdays(newWeekdays);
+            break;
+
+        case ABBREVIATED:
+        case NARROW:
+            dfs.setShortWeekdays(newWeekdays);
+            break;
+
+        default:
+            throw new IllegalArgumentException("Unsupported width argument value");
+        }
+    }
+
+    /**
+     * Sets weekday strings. For example: "Sunday", "Monday", etc.
+     * @param newWeekdays the new weekday strings. The array should
+     * be indexed by <code>Calendar.SUNDAY</code>,
+     * <code>Calendar.MONDAY</code>, etc.
+     * @stable ICU 2.0
+     */
+    public void setWeekdays(String[] newWeekdays) {
+        dfs.setWeekdays(newWeekdays);
+    }
+
+    /**
+     * Returns short weekday strings. For example: "Sun", "Mon", etc.
+     * @return the short weekday strings. Use <code>Calendar.SUNDAY</code>,
+     * <code>Calendar.MONDAY</code>, etc. to index the result array.
+     * @stable ICU 2.0
+     */
+    public String[] getShortWeekdays() {
+        return dfs.getShortWeekdays();
+    }
+
+    /**
+     * Sets short weekday strings. For example: "Sun", "Mon", etc.
+     * @param newShortWeekdays the new short weekday strings. The array should
+     * be indexed by <code>Calendar.SUNDAY</code>,
+     * <code>Calendar.MONDAY</code>, etc.
+     * @stable ICU 2.0
+     */
+    public void setShortWeekdays(String[] newShortWeekdays) {
+        dfs.setShortWeekdays(newShortWeekdays);
+    }
+    /**
+     * {@icu} Returns quarter strings. For example: "1st Quarter", "2nd Quarter", etc.
+     * @param context    The quarter context, FORMAT or STANDALONE.
+     * @param width      The width or the returned quarter string,
+     *                   either WIDE or ABBREVIATED. There are no NARROW quarters.
+     * @return the quarter strings.
+     * @stable ICU 3.6
+     */
+    public String[] getQuarters(int context, int width) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Sets quarter strings. For example: "1st Quarter", "2nd Quarter", etc.
+     * @param newQuarters the new quarter strings.
+     * @param context    The formatting context, FORMAT or STANDALONE.
+     * @param width      The width of the quarter string,
+     *                   either WIDE or ABBREVIATED. There are no NARROW quarters.
+     * @stable ICU 3.8
+     */
+    public void setQuarters(String[] newQuarters, int context, int width) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Returns am/pm strings. For example: "AM" and "PM".
+     * @return the weekday strings.
+     * @stable ICU 2.0
+     */
+    public String[] getAmPmStrings() {
+        return dfs.getAmPmStrings();
+    }
+
+    /**
+     * Sets am/pm strings. For example: "AM" and "PM".
+     * @param newAmpms the new ampm strings.
+     * @stable ICU 2.0
+     */
+    public void setAmPmStrings(String[] newAmpms) {
+        dfs.setAmPmStrings(newAmpms);
+    }
+
+    /**
+     * Returns timezone strings.
+     * @return the timezone strings.
+     * @stable ICU 2.0
+     */
+    public String[][] getZoneStrings() {
+        return dfs.getZoneStrings();
+    }
+
+    /**
+     * Sets timezone strings.
+     * @param newZoneStrings the new timezone strings.
+     * @stable ICU 2.0
+     */
+    public void setZoneStrings(String[][] newZoneStrings) {
+        dfs.setZoneStrings(newZoneStrings);
+    }
+
+    /**
+     * Returns localized date-time pattern characters. For example: 'u', 't', etc.
+     *
+     * <p>Note: ICU no longer provides localized date-time pattern characters for a locale
+     * starting ICU 3.8.  This method returns the non-localized date-time pattern
+     * characters unless user defined localized data is set by setLocalPatternChars.
+     * @return the localized date-time pattern characters.
+     * @stable ICU 2.0
+     */
+    public String getLocalPatternChars() {
+        return dfs.getLocalPatternChars();
+    }
+
+    /**
+     * Sets localized date-time pattern characters. For example: 'u', 't', etc.
+     * @param newLocalPatternChars the new localized date-time
+     * pattern characters.
+     * @stable ICU 2.0
+     */
+    public void setLocalPatternChars(String newLocalPatternChars) {
+        dfs.setLocalPatternChars(newLocalPatternChars);
+    }
+
+    /**
+     * Overrides clone.
+     * @stable ICU 2.0
+     */
+    public Object clone()
+    {
+        return new DateFormatSymbols((java.text.DateFormatSymbols)dfs.clone());
+    }
+
+    /**
+     * Override hashCode.
+     * Generates a hash code for the DateFormatSymbols object.
+     * @stable ICU 2.0
+     */
+    public int hashCode() {
+        return dfs.hashCode();
+    }
+
+    /**
+     * Overrides equals.
+     * @stable ICU 2.0
+     */
+    public boolean equals(Object obj)
+    {
+        try {
+            return dfs.equals(((DateFormatSymbols)obj).dfs);
+        }
+        catch (Exception e) {
+            return false;
+        }
+    }
+
+    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    /**
+     * Returns the {@link DateFormatSymbols} object that should be used to format a
+     * calendar system's dates in the given locale.
+     * <p>
+     * <b>Subclassing:</b><br>
+     * When creating a new Calendar subclass, you must create the
+     * {@link ResourceBundle ResourceBundle}
+     * containing its {@link DateFormatSymbols DateFormatSymbols} in a specific place.
+     * The resource bundle name is based on the calendar's fully-specified
+     * class name, with ".resources" inserted at the end of the package name
+     * (just before the class name) and "Symbols" appended to the end.
+     * For example, the bundle corresponding to "com.ibm.icu.util.HebrewCalendar"
+     * is "com.ibm.icu.impl.data.HebrewCalendarSymbols".
+     * <p>
+     * Within the ResourceBundle, this method searches for five keys:
+     * <ul>
+     * <li><b>DayNames</b> -
+     *      An array of strings corresponding to each possible
+     *      value of the <code>DAY_OF_WEEK</code> field.  Even though
+     *      <code>DAY_OF_WEEK</code> starts with <code>SUNDAY</code> = 1,
+     *      This array is 0-based; the name for Sunday goes in the
+     *      first position, at index 0.  If this key is not found
+     *      in the bundle, the day names are inherited from the
+     *      default <code>DateFormatSymbols</code> for the requested locale.
+     *
+     * <li><b>DayAbbreviations</b> -
+     *      An array of abbreviated day names corresponding
+     *      to the values in the "DayNames" array.  If this key
+     *      is not found in the resource bundle, the "DayNames"
+     *      values are used instead.  If neither key is found,
+     *      the day abbreviations are inherited from the default
+     *      <code>DateFormatSymbols</code> for the locale.
+     *
+     * <li><b>MonthNames</b> -
+     *      An array of strings corresponding to each possible
+     *      value of the <code>MONTH</code> field.  If this key is not found
+     *      in the bundle, the month names are inherited from the
+     *      default <code>DateFormatSymbols</code> for the requested locale.
+     *
+     * <li><b>MonthAbbreviations</b> -
+     *      An array of abbreviated day names corresponding
+     *      to the values in the "MonthNames" array.  If this key
+     *      is not found in the resource bundle, the "MonthNames"
+     *      values are used instead.  If neither key is found,
+     *      the day abbreviations are inherited from the default
+     *      <code>DateFormatSymbols</code> for the locale.
+     *
+     * <li><b>Eras</b> -
+     *      An array of strings corresponding to each possible
+     *      value of the <code>ERA</code> field.  If this key is not found
+     *      in the bundle, the era names are inherited from the
+     *      default <code>DateFormatSymbols</code> for the requested locale.
+     * </ul>
+     * <p>
+     * @param cal       The calendar system whose date format symbols are desired.
+     * @param locale    The locale whose symbols are desired.
+     *
+     * @see DateFormatSymbols#DateFormatSymbols(java.util.Locale)
+     * @stable ICU 2.0
+     */
+    public DateFormatSymbols(Calendar cal, Locale locale) {
+        throw new UnsupportedOperationException("Constructor not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Returns the {@link DateFormatSymbols} object that should be used to format a
+     * calendar system's dates in the given locale.
+     * <p>
+     * <b>Subclassing:</b><br>
+     * When creating a new Calendar subclass, you must create the
+     * {@link ResourceBundle ResourceBundle}
+     * containing its {@link DateFormatSymbols DateFormatSymbols} in a specific place.
+     * The resource bundle name is based on the calendar's fully-specified
+     * class name, with ".resources" inserted at the end of the package name
+     * (just before the class name) and "Symbols" appended to the end.
+     * For example, the bundle corresponding to "com.ibm.icu.util.HebrewCalendar"
+     * is "com.ibm.icu.impl.data.HebrewCalendarSymbols".
+     * <p>
+     * Within the ResourceBundle, this method searches for five keys:
+     * <ul>
+     * <li><b>DayNames</b> -
+     *      An array of strings corresponding to each possible
+     *      value of the <code>DAY_OF_WEEK</code> field.  Even though
+     *      <code>DAY_OF_WEEK</code> starts with <code>SUNDAY</code> = 1,
+     *      This array is 0-based; the name for Sunday goes in the
+     *      first position, at index 0.  If this key is not found
+     *      in the bundle, the day names are inherited from the
+     *      default <code>DateFormatSymbols</code> for the requested locale.
+     *
+     * <li><b>DayAbbreviations</b> -
+     *      An array of abbreviated day names corresponding
+     *      to the values in the "DayNames" array.  If this key
+     *      is not found in the resource bundle, the "DayNames"
+     *      values are used instead.  If neither key is found,
+     *      the day abbreviations are inherited from the default
+     *      <code>DateFormatSymbols</code> for the locale.
+     *
+     * <li><b>MonthNames</b> -
+     *      An array of strings corresponding to each possible
+     *      value of the <code>MONTH</code> field.  If this key is not found
+     *      in the bundle, the month names are inherited from the
+     *      default <code>DateFormatSymbols</code> for the requested locale.
+     *
+     * <li><b>MonthAbbreviations</b> -
+     *      An array of abbreviated day names corresponding
+     *      to the values in the "MonthNames" array.  If this key
+     *      is not found in the resource bundle, the "MonthNames"
+     *      values are used instead.  If neither key is found,
+     *      the day abbreviations are inherited from the default
+     *      <code>DateFormatSymbols</code> for the locale.
+     *
+     * <li><b>Eras</b> -
+     *      An array of strings corresponding to each possible
+     *      value of the <code>ERA</code> field.  If this key is not found
+     *      in the bundle, the era names are inherited from the
+     *      default <code>DateFormatSymbols</code> for the requested locale.
+     * </ul>
+     * <p>
+     * @param cal       The calendar system whose date format symbols are desired.
+     * @param locale    The ulocale whose symbols are desired.
+     *
+     * @see DateFormatSymbols#DateFormatSymbols(java.util.Locale)
+     * @stable ICU 3.2
+     */
+    public DateFormatSymbols(Calendar cal, ULocale locale) {
+        throw new UnsupportedOperationException("Constructor not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Variant of DateFormatSymbols(Calendar, Locale) that takes the Calendar class
+     * instead of a Calandar instance.
+     * @see #DateFormatSymbols(Calendar, Locale)
+     * @stable ICU 2.2
+     */
+    public DateFormatSymbols(Class<? extends Calendar> calendarClass, Locale locale) {
+        throw new UnsupportedOperationException("Constructor not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Variant of DateFormatSymbols(Calendar, ULocale) that takes the Calendar class
+     * instead of a Calandar instance.
+     * @see #DateFormatSymbols(Calendar, Locale)
+     * @stable ICU 3.2
+     */
+    public DateFormatSymbols(Class<? extends Calendar> calendarClass, ULocale locale) {
+        throw new UnsupportedOperationException("Constructor not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Fetches a custom calendar's DateFormatSymbols out of the given resource
+     * bundle.  Symbols that are not overridden are inherited from the
+     * default DateFormatSymbols for the locale.
+     * @see DateFormatSymbols#DateFormatSymbols(java.util.Locale)
+     * @stable ICU 2.0
+     */
+    public DateFormatSymbols(ResourceBundle bundle, Locale locale) {
+        throw new UnsupportedOperationException("Constructor not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Fetches a custom calendar's DateFormatSymbols out of the given resource
+     * bundle.  Symbols that are not overridden are inherited from the
+     * default DateFormatSymbols for the locale.
+     * @see DateFormatSymbols#DateFormatSymbols(java.util.Locale)
+     * @stable ICU 3.2
+     */
+    public DateFormatSymbols(ResourceBundle bundle, ULocale locale) {
+        throw new UnsupportedOperationException("Constructor not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Finds the ResourceBundle containing the date format information for
+     * a specified calendar subclass in a given locale.
+     * <p>
+     * The resource bundle name is based on the calendar's fully-specified
+     * class name, with ".resources" inserted at the end of the package name
+     * (just before the class name) and "Symbols" appended to the end.
+     * For example, the bundle corresponding to "com.ibm.icu.util.HebrewCalendar"
+     * is "com.ibm.icu.impl.data.HebrewCalendarSymbols".
+     * <p>
+     * <b>Note:</b>Because of the structural changes in the ICU locale bundle,
+     * this API no longer works as described.  This method always returns null.
+     * @deprecated ICU 4.0
+     */
+    // This API was formerly @stable ICU 2.0
+    static public ResourceBundle getDateFormatBundle(Class<? extends Calendar> calendarClass,
+                                                     Locale locale) throws MissingResourceException {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");    }
+
+    /**
+     * Finds the ResourceBundle containing the date format information for
+     * a specified calendar subclass in a given locale.
+     * <p>
+     * The resource bundle name is based on the calendar's fully-specified
+     * class name, with ".resources" inserted at the end of the package name
+     * (just before the class name) and "Symbols" appended to the end.
+     * For example, the bundle corresponding to "com.ibm.icu.util.HebrewCalendar"
+     * is "com.ibm.icu.impl.data.HebrewCalendarSymbols".
+     * <p>
+     * <b>Note:</b>Because of the structural changes in the ICU locale bundle,
+     * this API no longer works as described.  This method always returns null.
+     * @deprecated ICU 4.0
+     */
+    // This API was formerly @stable ICU 3.2
+    static public ResourceBundle getDateFormatBundle(Class<? extends Calendar> calendarClass,
+                                                     ULocale locale) throws MissingResourceException {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");    }
+
+    /**
+     * Variant of getDateFormatBundle(java.lang.Class, java.util.Locale) that takes
+     * a Calendar instance instead of a Calendar class.
+     * <p>
+     * <b>Note:</b>Because of the structural changes in the ICU locale bundle,
+     * this API no longer works as described.  This method always returns null.
+     * @see #getDateFormatBundle(java.lang.Class, java.util.Locale)
+     * @deprecated ICU 4.0
+     */
+    // This API was formerly @stable ICU 2.2
+    public static ResourceBundle getDateFormatBundle(Calendar cal, Locale locale) throws MissingResourceException {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");    }
+
+    /**
+     * Variant of getDateFormatBundle(java.lang.Class, java.util.Locale) that takes
+     * a Calendar instance instead of a Calendar class.
+     * <p>
+     * <b>Note:</b>Because of the structural changes in the ICU locale bundle,
+     * this API no longer works as described.  This method always returns null.
+     * @see #getDateFormatBundle(java.lang.Class, java.util.Locale)
+     * @deprecated ICU 4.0
+     */
+    // This API was formerly @stable ICU 3.2
+    public static ResourceBundle getDateFormatBundle(Calendar cal, ULocale locale) throws MissingResourceException {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");    }
+
+    /**
+     * Returns the locale that was used to create this object, or null.
+     * This may may differ from the locale requested at the time of
+     * this object's creation.  For example, if an object is created
+     * for locale <tt>en_US_CALIFORNIA</tt>, the actual data may be
+     * drawn from <tt>en</tt> (the <i>actual</i> locale), and
+     * <tt>en_US</tt> may be the most specific locale that exists (the
+     * <i>valid</i> locale).
+     *
+     * <p>Note: This method will be implemented in ICU 3.0; ICU 2.8
+     * contains a partial preview implementation.  The * <i>actual</i>
+     * locale is returned correctly, but the <i>valid</i> locale is
+     * not, in most cases.
+     * @param type type of information requested, either {@link
+     * com.ibm.icu.util.ULocale#VALID_LOCALE} or {@link
+     * com.ibm.icu.util.ULocale#ACTUAL_LOCALE}.
+     * @return the information specified by <i>type</i>, or null if
+     * this object was not constructed from locale data.
+     * @see com.ibm.icu.util.ULocale
+     * @see com.ibm.icu.util.ULocale#VALID_LOCALE
+     * @see com.ibm.icu.util.ULocale#ACTUAL_LOCALE
+     * @draft ICU 2.8 (retain)
+     * @provisional This API might change or be removed in a future release.
+     */
+    public final ULocale getLocale(ULocale.Type type) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/DecimalFormat.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/DecimalFormat.java
index 21021b0..14eea14 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/DecimalFormat.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/DecimalFormat.java
@@ -1,1762 +1,1762 @@
-/*
- *******************************************************************************
- * Copyright (C) 1996-2011, International Business Machines Corporation and    *
- * others. All Rights Reserved.                                                *
- *******************************************************************************
- */
-package com.ibm.icu.text;
-
-import java.math.BigInteger;
-import java.text.AttributedCharacterIterator;
-import java.text.AttributedCharacterIterator.Attribute;
-import java.text.AttributedString;
-import java.text.CharacterIterator;
-import java.text.FieldPosition;
-import java.text.ParsePosition;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import com.ibm.icu.math.BigDecimal;
-import com.ibm.icu.math.MathContext;
-import com.ibm.icu.util.Currency;
-import com.ibm.icu.util.CurrencyAmount;
-
-/**
- * {@icuenhanced java.text.DecimalFormat}.{@icu _usage_}
- *
- * <code>DecimalFormat</code> is a concrete subclass of {@link NumberFormat} that formats
- * decimal numbers. It has a variety of features designed to make it possible to parse and
- * format numbers in any locale, including support for Western, Arabic, or Indic digits.
- * It also supports different flavors of numbers, including integers ("123"), fixed-point
- * numbers ("123.4"), scientific notation ("1.23E4"), percentages ("12%"), and currency
- * amounts ("$123.00", "USD123.00", "123.00 US dollars").  All of these flavors can be
- * easily localized.
- *
- * <p>To obtain a {@link NumberFormat} for a specific locale (including the default
- * locale) call one of <code>NumberFormat</code>'s factory methods such as {@link
- * NumberFormat#getInstance}. Do not call the <code>DecimalFormat</code> constructors
- * directly, unless you know what you are doing, since the {@link NumberFormat} factory
- * methods may return subclasses other than <code>DecimalFormat</code>. If you need to
- * customize the format object, do something like this:
- *
- * <blockquote><pre>
- * NumberFormat f = NumberFormat.getInstance(loc);
- * if (f instanceof DecimalFormat) {
- *     ((DecimalFormat) f).setDecimalSeparatorAlwaysShown(true);
- * }</pre></blockquote>
- *
- * <p><strong>Example Usage</strong>
- *
- * Print out a number using the localized number, currency, and percent
- * format for each locale.
- *
- * <blockquote><pre>
- * Locale[] locales = NumberFormat.getAvailableLocales();
- * double myNumber = -1234.56;
- * NumberFormat format;
- * for (int j=0; j<3; ++j) {
- *     System.out.println("FORMAT");
- *     for (int i = 0; i < locales.length; ++i) {
- *         if (locales[i].getCountry().length() == 0) {
- *            // Skip language-only locales
- *            continue;
- *         }
- *         System.out.print(locales[i].getDisplayName());
- *         switch (j) {
- *         case 0:
- *             format = NumberFormat.getInstance(locales[i]); break;
- *         case 1:
- *             format = NumberFormat.getCurrencyInstance(locales[i]); break;
- *         default:
- *             format = NumberFormat.getPercentInstance(locales[i]); break;
- *         }
- *         try {
- *             // Assume format is a DecimalFormat
- *             System.out.print(": " + ((DecimalFormat) format).toPattern()
- *                              + " -> " + form.format(myNumber));
- *         } catch (Exception e) {}
- *         try {
- *             System.out.println(" -> " + format.parse(form.format(myNumber)));
- *         } catch (ParseException e) {}
- *     }
- * }</pre></blockquote>
- *
- * <p>Another example use getInstance(style).<br/>
- * Print out a number using the localized number, currency, percent,
- * scientific, integer, iso currency, and plural currency format for each locale.
- *
- * <blockquote><pre>
- * ULocale locale = new ULocale("en_US");
- * double myNumber = 1234.56;
- * for (int j=NumberFormat.NUMBERSTYLE; j<=NumberFormat.PLURALCURRENCYSTYLE; ++j) {
- *     NumberFormat format = NumberFormat.getInstance(locale, j);
- *     try {
- *         // Assume format is a DecimalFormat
- *         System.out.print(": " + ((DecimalFormat) format).toPattern()
- *                          + " -> " + form.format(myNumber));
- *     } catch (Exception e) {}
- *     try {
- *         System.out.println(" -> " + format.parse(form.format(myNumber)));
- *     } catch (ParseException e) {}
- * }</pre></blockquote>
- *
- * <h4>Patterns</h4>
- *
- * <p>A <code>DecimalFormat</code> consists of a <em>pattern</em> and a set of
- * <em>symbols</em>.  The pattern may be set directly using {@link #applyPattern}, or
- * indirectly using other API methods which manipulate aspects of the pattern, such as the
- * minimum number of integer digits.  The symbols are stored in a {@link
- * DecimalFormatSymbols} object.  When using the {@link NumberFormat} factory methods, the
- * pattern and symbols are read from ICU's locale data.
- *
- * <h4>Special Pattern Characters</h4>
- *
- * <p>Many characters in a pattern are taken literally; they are matched during parsing
- * and output unchanged during formatting.  Special characters, on the other hand, stand
- * for other characters, strings, or classes of characters.  For example, the '#'
- * character is replaced by a localized digit.  Often the replacement character is the
- * same as the pattern character; in the U.S. locale, the ',' grouping character is
- * replaced by ','.  However, the replacement is still happening, and if the symbols are
- * modified, the grouping character changes.  Some special characters affect the behavior
- * of the formatter by their presence; for example, if the percent character is seen, then
- * the value is multiplied by 100 before being displayed.
- *
- * <p>To insert a special character in a pattern as a literal, that is, without any
- * special meaning, the character must be quoted.  There are some exceptions to this which
- * are noted below.
- *
- * <p>The characters listed here are used in non-localized patterns.  Localized patterns
- * use the corresponding characters taken from this formatter's {@link
- * DecimalFormatSymbols} object instead, and these characters lose their special status.
- * Two exceptions are the currency sign and quote, which are not localized.
- *
- * <blockquote>
- * <table border=0 cellspacing=3 cellpadding=0 summary="Chart showing symbol,
- *  location, localized, and meaning.">
- *   <tr bgcolor="#ccccff">
- *     <th align=left>Symbol
- *     <th align=left>Location
- *     <th align=left>Localized?
- *     <th align=left>Meaning
- *   <tr valign=top>
- *     <td><code>0</code>
- *     <td>Number
- *     <td>Yes
- *     <td>Digit
- *   <tr valign=top bgcolor="#eeeeff">
- *     <td><code>1-9</code>
- *     <td>Number
- *     <td>Yes
- *     <td>'1' through '9' indicate rounding.
- *   <tr valign=top>
- *     <td><code>@</code>
- *     <td>Number
- *     <td>No
- *     <td>Significant digit
- *   <tr valign=top bgcolor="#eeeeff">
- *     <td><code>#</code>
- *     <td>Number
- *     <td>Yes
- *     <td>Digit, zero shows as absent
- *   <tr valign=top>
- *     <td><code>.</code>
- *     <td>Number
- *     <td>Yes
- *     <td>Decimal separator or monetary decimal separator
- *   <tr valign=top bgcolor="#eeeeff">
- *     <td><code>-</code>
- *     <td>Number
- *     <td>Yes
- *     <td>Minus sign
- *   <tr valign=top>
- *     <td><code>,</code>
- *     <td>Number
- *     <td>Yes
- *     <td>Grouping separator
- *   <tr valign=top bgcolor="#eeeeff">
- *     <td><code>E</code>
- *     <td>Number
- *     <td>Yes
- *     <td>Separates mantissa and exponent in scientific notation.
- *         <em>Need not be quoted in prefix or suffix.</em>
- *   <tr valign=top>
- *     <td><code>+</code>
- *     <td>Exponent
- *     <td>Yes
- *     <td>Prefix positive exponents with localized plus sign.
- *         <em>Need not be quoted in prefix or suffix.</em>
- *   <tr valign=top bgcolor="#eeeeff">
- *     <td><code>;</code>
- *     <td>Subpattern boundary
- *     <td>Yes
- *     <td>Separates positive and negative subpatterns
- *   <tr valign=top>
- *     <td><code>%</code>
- *     <td>Prefix or suffix
- *     <td>Yes
- *     <td>Multiply by 100 and show as percentage
- *   <tr valign=top bgcolor="#eeeeff">
- *     <td><code>&#92;u2030</code>
- *     <td>Prefix or suffix
- *     <td>Yes
- *     <td>Multiply by 1000 and show as per mille
- *   <tr valign=top>
- *     <td><code>&#164;</code> (<code>&#92;u00A4</code>)
- *     <td>Prefix or suffix
- *     <td>No
- *     <td>Currency sign, replaced by currency symbol.  If
- *         doubled, replaced by international currency symbol.
- *         If tripled, replaced by currency plural names, for example,
- *         "US dollar" or "US dollars" for America.
- *         If present in a pattern, the monetary decimal separator
- *         is used instead of the decimal separator.
- *   <tr valign=top bgcolor="#eeeeff">
- *     <td><code>'</code>
- *     <td>Prefix or suffix
- *     <td>No
- *     <td>Used to quote special characters in a prefix or suffix,
- *         for example, <code>"'#'#"</code> formats 123 to
- *         <code>"#123"</code>.  To create a single quote
- *         itself, use two in a row: <code>"# o''clock"</code>.
- *   <tr valign=top>
- *     <td><code>*</code>
- *     <td>Prefix or suffix boundary
- *     <td>Yes
- *     <td>Pad escape, precedes pad character
- * </table>
- * </blockquote>
- *
- * <p>A <code>DecimalFormat</code> pattern contains a postive and negative subpattern, for
- * example, "#,##0.00;(#,##0.00)".  Each subpattern has a prefix, a numeric part, and a
- * suffix.  If there is no explicit negative subpattern, the negative subpattern is the
- * localized minus sign prefixed to the positive subpattern. That is, "0.00" alone is
- * equivalent to "0.00;-0.00".  If there is an explicit negative subpattern, it serves
- * only to specify the negative prefix and suffix; the number of digits, minimal digits,
- * and other characteristics are ignored in the negative subpattern. That means that
- * "#,##0.0#;(#)" has precisely the same result as "#,##0.0#;(#,##0.0#)".
- *
- * <p>The prefixes, suffixes, and various symbols used for infinity, digits, thousands
- * separators, decimal separators, etc. may be set to arbitrary values, and they will
- * appear properly during formatting.  However, care must be taken that the symbols and
- * strings do not conflict, or parsing will be unreliable.  For example, either the
- * positive and negative prefixes or the suffixes must be distinct for {@link #parse} to
- * be able to distinguish positive from negative values.  Another example is that the
- * decimal separator and thousands separator should be distinct characters, or parsing
- * will be impossible.
- *
- * <p>The <em>grouping separator</em> is a character that separates clusters of integer
- * digits to make large numbers more legible.  It commonly used for thousands, but in some
- * locales it separates ten-thousands.  The <em>grouping size</em> is the number of digits
- * between the grouping separators, such as 3 for "100,000,000" or 4 for "1 0000
- * 0000". There are actually two different grouping sizes: One used for the least
- * significant integer digits, the <em>primary grouping size</em>, and one used for all
- * others, the <em>secondary grouping size</em>.  In most locales these are the same, but
- * sometimes they are different. For example, if the primary grouping interval is 3, and
- * the secondary is 2, then this corresponds to the pattern "#,##,##0", and the number
- * 123456789 is formatted as "12,34,56,789".  If a pattern contains multiple grouping
- * separators, the interval between the last one and the end of the integer defines the
- * primary grouping size, and the interval between the last two defines the secondary
- * grouping size. All others are ignored, so "#,##,###,####" == "###,###,####" ==
- * "##,#,###,####".
- *
- * <p>Illegal patterns, such as "#.#.#" or "#.###,###", will cause
- * <code>DecimalFormat</code> to throw an {@link IllegalArgumentException} with a message
- * that describes the problem.
- *
- * <h4>Pattern BNF</h4>
- *
- * <pre>
- * pattern    := subpattern (';' subpattern)?
- * subpattern := prefix? number exponent? suffix?
- * number     := (integer ('.' fraction)?) | sigDigits
- * prefix     := '&#92;u0000'..'&#92;uFFFD' - specialCharacters
- * suffix     := '&#92;u0000'..'&#92;uFFFD' - specialCharacters
- * integer    := '#'* '0'* '0'
- * fraction   := '0'* '#'*
- * sigDigits  := '#'* '@' '@'* '#'*
- * exponent   := 'E' '+'? '0'* '0'
- * padSpec    := '*' padChar
- * padChar    := '&#92;u0000'..'&#92;uFFFD' - quote
- * &#32;
- * Notation:
- *   X*       0 or more instances of X
- *   X?       0 or 1 instances of X
- *   X|Y      either X or Y
- *   C..D     any character from C up to D, inclusive
- *   S-T      characters in S, except those in T
- * </pre>
- * The first subpattern is for positive numbers. The second (optional)
- * subpattern is for negative numbers.
- *
- * <p>Not indicated in the BNF syntax above:
- *
- * <ul>
- *
- * <li>The grouping separator ',' can occur inside the integer and sigDigits
- * elements, between any two pattern characters of that element, as long as the integer or
- * sigDigits element is not followed by the exponent element.
- *
- * <li>Two grouping intervals are recognized: That between the decimal point and the first
- * grouping symbol, and that between the first and second grouping symbols. These
- * intervals are identical in most locales, but in some locales they differ. For example,
- * the pattern &quot;#,##,###&quot; formats the number 123456789 as
- * &quot;12,34,56,789&quot;.
- *
- * <li>The pad specifier <code>padSpec</code> may appear before the prefix, after the
- * prefix, before the suffix, after the suffix, or not at all.
- *
- * <li>In place of '0', the digits '1' through '9' may be used to indicate a rounding
- * increment.
- *
- * </ul>
- *
- * <h4>Parsing</h4>
- *
- * <p><code>DecimalFormat</code> parses all Unicode characters that represent decimal
- * digits, as defined by {@link UCharacter#digit}.  In addition,
- * <code>DecimalFormat</code> also recognizes as digits the ten consecutive characters
- * starting with the localized zero digit defined in the {@link DecimalFormatSymbols}
- * object.  During formatting, the {@link DecimalFormatSymbols}-based digits are output.
- *
- * <p>During parsing, grouping separators are ignored.
- *
- * <p>For currency parsing, the formatter is able to parse every currency style formats no
- * matter which style the formatter is constructed with.  For example, a formatter
- * instance gotten from NumberFormat.getInstance(ULocale, NumberFormat.CURRENCYSTYLE) can
- * parse formats such as "USD1.00" and "3.00 US dollars".
- *
- * <p>If {@link #parse(String, ParsePosition)} fails to parse a string, it returns
- * <code>null</code> and leaves the parse position unchanged.  The convenience method
- * {@link #parse(String)} indicates parse failure by throwing a {@link
- * java.text.ParseException}.
- *
- * <h4>Formatting</h4>
- *
- * <p>Formatting is guided by several parameters, all of which can be specified either
- * using a pattern or using the API.  The following description applies to formats that do
- * not use <a href="#sci">scientific notation</a> or <a href="#sigdig">significant
- * digits</a>.
- *
- * <ul><li>If the number of actual integer digits exceeds the <em>maximum integer
- * digits</em>, then only the least significant digits are shown.  For example, 1997 is
- * formatted as "97" if the maximum integer digits is set to 2.
- *
- * <li>If the number of actual integer digits is less than the <em>minimum integer
- * digits</em>, then leading zeros are added.  For example, 1997 is formatted as "01997"
- * if the minimum integer digits is set to 5.
- *
- * <li>If the number of actual fraction digits exceeds the <em>maximum fraction
- * digits</em>, then half-even rounding it performed to the maximum fraction digits.  For
- * example, 0.125 is formatted as "0.12" if the maximum fraction digits is 2.  This
- * behavior can be changed by specifying a rounding increment and a rounding mode.
- *
- * <li>If the number of actual fraction digits is less than the <em>minimum fraction
- * digits</em>, then trailing zeros are added.  For example, 0.125 is formatted as
- * "0.1250" if the mimimum fraction digits is set to 4.
- *
- * <li>Trailing fractional zeros are not displayed if they occur <em>j</em> positions
- * after the decimal, where <em>j</em> is less than the maximum fraction digits. For
- * example, 0.10004 is formatted as "0.1" if the maximum fraction digits is four or less.
- * </ul>
- *
- * <p><strong>Special Values</strong>
- *
- * <p><code>NaN</code> is represented as a single character, typically
- * <code>&#92;uFFFD</code>.  This character is determined by the {@link
- * DecimalFormatSymbols} object.  This is the only value for which the prefixes and
- * suffixes are not used.
- *
- * <p>Infinity is represented as a single character, typically <code>&#92;u221E</code>,
- * with the positive or negative prefixes and suffixes applied.  The infinity character is
- * determined by the {@link DecimalFormatSymbols} object.
- *
- * <a name="sci"><h4>Scientific Notation</h4></a>
- *
- * <p>Numbers in scientific notation are expressed as the product of a mantissa and a
- * power of ten, for example, 1234 can be expressed as 1.234 x 10<sup>3</sup>. The
- * mantissa is typically in the half-open interval [1.0, 10.0) or sometimes [0.0, 1.0),
- * but it need not be.  <code>DecimalFormat</code> supports arbitrary mantissas.
- * <code>DecimalFormat</code> can be instructed to use scientific notation through the API
- * or through the pattern.  In a pattern, the exponent character immediately followed by
- * one or more digit characters indicates scientific notation.  Example: "0.###E0" formats
- * the number 1234 as "1.234E3".
- *
- * <ul>
- *
- * <li>The number of digit characters after the exponent character gives the minimum
- * exponent digit count.  There is no maximum.  Negative exponents are formatted using the
- * localized minus sign, <em>not</em> the prefix and suffix from the pattern.  This allows
- * patterns such as "0.###E0 m/s".  To prefix positive exponents with a localized plus
- * sign, specify '+' between the exponent and the digits: "0.###E+0" will produce formats
- * "1E+1", "1E+0", "1E-1", etc.  (In localized patterns, use the localized plus sign
- * rather than '+'.)
- *
- * <li>The minimum number of integer digits is achieved by adjusting the exponent.
- * Example: 0.00123 formatted with "00.###E0" yields "12.3E-4".  This only happens if
- * there is no maximum number of integer digits.  If there is a maximum, then the minimum
- * number of integer digits is fixed at one.
- *
- * <li>The maximum number of integer digits, if present, specifies the exponent grouping.
- * The most common use of this is to generate <em>engineering notation</em>, in which the
- * exponent is a multiple of three, e.g., "##0.###E0".  The number 12345 is formatted
- * using "##0.####E0" as "12.345E3".
- *
- * <li>When using scientific notation, the formatter controls the digit counts using
- * significant digits logic.  The maximum number of significant digits limits the total
- * number of integer and fraction digits that will be shown in the mantissa; it does not
- * affect parsing.  For example, 12345 formatted with "##0.##E0" is "12.3E3".  See the
- * section on significant digits for more details.
- *
- * <li>The number of significant digits shown is determined as follows: If
- * areSignificantDigitsUsed() returns false, then the minimum number of significant digits
- * shown is one, and the maximum number of significant digits shown is the sum of the
- * <em>minimum integer</em> and <em>maximum fraction</em> digits, and is unaffected by the
- * maximum integer digits.  If this sum is zero, then all significant digits are shown.
- * If areSignificantDigitsUsed() returns true, then the significant digit counts are
- * specified by getMinimumSignificantDigits() and getMaximumSignificantDigits().  In this
- * case, the number of integer digits is fixed at one, and there is no exponent grouping.
- *
- * <li>Exponential patterns may not contain grouping separators.
- *
- * </ul>
- *
- * <a name="sigdig"><h4>Significant Digits</h4></a>
- *
- * <code>DecimalFormat</code> has two ways of controlling how many digits are shows: (a)
- * significant digits counts, or (b) integer and fraction digit counts.  Integer and
- * fraction digit counts are described above.  When a formatter is using significant
- * digits counts, the number of integer and fraction digits is not specified directly, and
- * the formatter settings for these counts are ignored.  Instead, the formatter uses
- * however many integer and fraction digits are required to display the specified number
- * of significant digits.  Examples:
- *
- * <blockquote>
- * <table border=0 cellspacing=3 cellpadding=0>
- *   <tr bgcolor="#ccccff">
- *     <th align=left>Pattern
- *     <th align=left>Minimum significant digits
- *     <th align=left>Maximum significant digits
- *     <th align=left>Number
- *     <th align=left>Output of format()
- *   <tr valign=top>
- *     <td><code>@@@</code>
- *     <td>3
- *     <td>3
- *     <td>12345
- *     <td><code>12300</code>
- *   <tr valign=top bgcolor="#eeeeff">
- *     <td><code>@@@</code>
- *     <td>3
- *     <td>3
- *     <td>0.12345
- *     <td><code>0.123</code>
- *   <tr valign=top>
- *     <td><code>@@##</code>
- *     <td>2
- *     <td>4
- *     <td>3.14159
- *     <td><code>3.142</code>
- *   <tr valign=top bgcolor="#eeeeff">
- *     <td><code>@@##</code>
- *     <td>2
- *     <td>4
- *     <td>1.23004
- *     <td><code>1.23</code>
- * </table>
- * </blockquote>
- *
- * <ul>
- *
- * <li>Significant digit counts may be expressed using patterns that specify a minimum and
- * maximum number of significant digits.  These are indicated by the <code>'@'</code> and
- * <code>'#'</code> characters.  The minimum number of significant digits is the number of
- * <code>'@'</code> characters.  The maximum number of significant digits is the number of
- * <code>'@'</code> characters plus the number of <code>'#'</code> characters following on
- * the right.  For example, the pattern <code>"@@@"</code> indicates exactly 3 significant
- * digits.  The pattern <code>"@##"</code> indicates from 1 to 3 significant digits.
- * Trailing zero digits to the right of the decimal separator are suppressed after the
- * minimum number of significant digits have been shown.  For example, the pattern
- * <code>"@##"</code> formats the number 0.1203 as <code>"0.12"</code>.
- *
- * <li>If a pattern uses significant digits, it may not contain a decimal separator, nor
- * the <code>'0'</code> pattern character.  Patterns such as <code>"@00"</code> or
- * <code>"@.###"</code> are disallowed.
- *
- * <li>Any number of <code>'#'</code> characters may be prepended to the left of the
- * leftmost <code>'@'</code> character.  These have no effect on the minimum and maximum
- * significant digits counts, but may be used to position grouping separators.  For
- * example, <code>"#,#@#"</code> indicates a minimum of one significant digits, a maximum
- * of two significant digits, and a grouping size of three.
- *
- * <li>In order to enable significant digits formatting, use a pattern containing the
- * <code>'@'</code> pattern character.  Alternatively, call {@link
- * #setSignificantDigitsUsed setSignificantDigitsUsed(true)}.
- *
- * <li>In order to disable significant digits formatting, use a pattern that does not
- * contain the <code>'@'</code> pattern character. Alternatively, call {@link
- * #setSignificantDigitsUsed setSignificantDigitsUsed(false)}.
- *
- * <li>The number of significant digits has no effect on parsing.
- *
- * <li>Significant digits may be used together with exponential notation. Such patterns
- * are equivalent to a normal exponential pattern with a minimum and maximum integer digit
- * count of one, a minimum fraction digit count of <code>getMinimumSignificantDigits() -
- * 1</code>, and a maximum fraction digit count of <code>getMaximumSignificantDigits() -
- * 1</code>. For example, the pattern <code>"@@###E0"</code> is equivalent to
- * <code>"0.0###E0"</code>.
- *
- * <li>If signficant digits are in use, then the integer and fraction digit counts, as set
- * via the API, are ignored.  If significant digits are not in use, then the signficant
- * digit counts, as set via the API, are ignored.
- *
- * </ul>
- *
- * <h4>Padding</h4>
- *
- * <p><code>DecimalFormat</code> supports padding the result of {@link #format} to a
- * specific width.  Padding may be specified either through the API or through the pattern
- * syntax.  In a pattern the pad escape character, followed by a single pad character,
- * causes padding to be parsed and formatted.  The pad escape character is '*' in
- * unlocalized patterns, and can be localized using {@link
- * DecimalFormatSymbols#setPadEscape}.  For example, <code>"$*x#,##0.00"</code> formats
- * 123 to <code>"$xx123.00"</code>, and 1234 to <code>"$1,234.00"</code>.
- *
- * <ul>
- *
- * <li>When padding is in effect, the width of the positive subpattern, including prefix
- * and suffix, determines the format width.  For example, in the pattern <code>"* #0
- * o''clock"</code>, the format width is 10.
- *
- * <li>The width is counted in 16-bit code units (Java <code>char</code>s).
- *
- * <li>Some parameters which usually do not matter have meaning when padding is used,
- * because the pattern width is significant with padding.  In the pattern "*
- * ##,##,#,##0.##", the format width is 14.  The initial characters "##,##," do not affect
- * the grouping size or maximum integer digits, but they do affect the format width.
- *
- * <li>Padding may be inserted at one of four locations: before the prefix, after the
- * prefix, before the suffix, or after the suffix.  If padding is specified in any other
- * location, {@link #applyPattern} throws an {@link IllegalArgumentException}.  If there
- * is no prefix, before the prefix and after the prefix are equivalent, likewise for the
- * suffix.
- *
- * <li>When specified in a pattern, the 16-bit <code>char</code> immediately following the
- * pad escape is the pad character. This may be any character, including a special pattern
- * character. That is, the pad escape <em>escapes</em> the following character. If there
- * is no character after the pad escape, then the pattern is illegal.
- *
- * </ul>
- *
- * <p>
- * <strong>Rounding</strong>
- *
- * <p><code>DecimalFormat</code> supports rounding to a specific increment.  For example,
- * 1230 rounded to the nearest 50 is 1250.  1.234 rounded to the nearest 0.65 is 1.3.  The
- * rounding increment may be specified through the API or in a pattern.  To specify a
- * rounding increment in a pattern, include the increment in the pattern itself.  "#,#50"
- * specifies a rounding increment of 50.  "#,##0.05" specifies a rounding increment of
- * 0.05.
- *
- * <ul>
- *
- * <li>Rounding only affects the string produced by formatting.  It does not affect
- * parsing or change any numerical values.
- *
- * <li>A <em>rounding mode</em> determines how values are rounded; see the {@link
- * com.ibm.icu.math.BigDecimal} documentation for a description of the modes.  Rounding
- * increments specified in patterns use the default mode, {@link
- * com.ibm.icu.math.BigDecimal#ROUND_HALF_EVEN}.
- *
- * <li>Some locales use rounding in their currency formats to reflect the smallest
- * currency denomination.
- *
- * <li>In a pattern, digits '1' through '9' specify rounding, but otherwise behave
- * identically to digit '0'.
- *
- * </ul>
- *
- * <h4>Synchronization</h4>
- *
- * <p><code>DecimalFormat</code> objects are not synchronized.  Multiple threads should
- * not access one formatter concurrently.
- *
- * @see          java.text.Format
- * @see          NumberFormat
- * @author       Mark Davis
- * @author       Alan Liu
- * @stable ICU 2.0
- */
-public class DecimalFormat extends NumberFormat {
-
-    private static final long serialVersionUID = 1L;
-    /**
-     * @internal
-     * @param delegate the NumberFormat to which to delegate
-     */
-    public DecimalFormat(java.text.DecimalFormat delegate) {
-        super(delegate);
-    }
-
-    /**
-     * Creates a DecimalFormat using the default pattern and symbols for the default
-     * locale. This is a convenient way to obtain a DecimalFormat when
-     * internationalization is not the main concern.
-     *
-     * <p>To obtain standard formats for a given locale, use the factory methods on
-     * NumberFormat such as getNumberInstance.  These factories will return the most
-     * appropriate sub-class of NumberFormat for a given locale.
-     *
-     * @see NumberFormat#getInstance
-     * @see NumberFormat#getNumberInstance
-     * @see NumberFormat#getCurrencyInstance
-     * @see NumberFormat#getPercentInstance
-     * @stable ICU 2.0
-     */
-    public DecimalFormat() {
-        this(new java.text.DecimalFormat());
-    }
-
-    /**
-     * Creates a DecimalFormat from the given pattern and the symbols for the default
-     * locale. This is a convenient way to obtain a DecimalFormat when
-     * internationalization is not the main concern.
-     *
-     * <p>To obtain standard formats for a given locale, use the factory methods on
-     * NumberFormat such as getNumberInstance.  These factories will return the most
-     * appropriate sub-class of NumberFormat for a given locale.
-     *
-     * @param pattern A non-localized pattern string.
-     * @throws IllegalArgumentException if the given pattern is invalid.
-     * @see NumberFormat#getInstance
-     * @see NumberFormat#getNumberInstance
-     * @see NumberFormat#getCurrencyInstance
-     * @see NumberFormat#getPercentInstance
-     * @stable ICU 2.0
-     */
-    public DecimalFormat(String pattern) {
-        this(new java.text.DecimalFormat(pattern));
-    }
-
-    /**
-     * Creates a DecimalFormat from the given pattern and symbols. Use this constructor
-     * when you need to completely customize the behavior of the format.
-     *
-     * <p>To obtain standard formats for a given locale, use the factory methods on
-     * NumberFormat such as getInstance or getCurrencyInstance. If you need only minor
-     * adjustments to a standard format, you can modify the format returned by a
-     * NumberFormat factory method.
-     *
-     * @param pattern a non-localized pattern string
-     * @param symbols the set of symbols to be used
-     * @exception IllegalArgumentException if the given pattern is invalid
-     * @see NumberFormat#getInstance
-     * @see NumberFormat#getNumberInstance
-     * @see NumberFormat#getCurrencyInstance
-     * @see NumberFormat#getPercentInstance
-     * @see DecimalFormatSymbols
-     * @stable ICU 2.0
-     */
-    public DecimalFormat(String pattern, DecimalFormatSymbols symbols) {
-        this(new java.text.DecimalFormat(pattern, symbols.dfs));
-    }
-
-    /**
-     * Creates a DecimalFormat from the given pattern, symbols, information used for
-     * currency plural format, and format style. Use this constructor when you need to
-     * completely customize the behavior of the format.
-     *
-     * <p>To obtain standard formats for a given locale, use the factory methods on
-     * NumberFormat such as getInstance or getCurrencyInstance.
-     *
-     * <p>If you need only minor adjustments to a standard format, you can modify the
-     * format returned by a NumberFormat factory method using the setters.
-     *
-     * <p>If you want to completely customize a decimal format, using your own
-     * DecimalFormatSymbols (such as group separators) and your own information for
-     * currency plural formatting (such as plural rule and currency plural patterns), you
-     * can use this constructor.
-     *
-     * @param pattern a non-localized pattern string
-     * @param symbols the set of symbols to be used
-     * @param infoInput the information used for currency plural format, including
-     * currency plural patterns and plural rules.
-     * @param style the decimal formatting style, it is one of the following values:
-     * NumberFormat.NUMBERSTYLE; NumberFormat.CURRENCYSTYLE; NumberFormat.PERCENTSTYLE;
-     * NumberFormat.SCIENTIFICSTYLE; NumberFormat.INTEGERSTYLE;
-     * NumberFormat.ISOCURRENCYSTYLE; NumberFormat.PLURALCURRENCYSTYLE;
-     * @stable ICU 4.2
-     */
-    public DecimalFormat(String pattern, DecimalFormatSymbols symbols, CurrencyPluralInfo infoInput,
-                         int style) {
-        throw new UnsupportedOperationException("Constructor not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@inheritDoc}
-     * @stable ICU 2.0
-     */
-    public StringBuffer format(double number, StringBuffer result, FieldPosition fieldPosition) {
-        return super.format(number, result, fieldPosition);
-    }
-
-    /**
-     * @stable ICU 2.0
-     */
-    // [Spark/CDL] Delegate to format_long_StringBuffer_FieldPosition_boolean
-    public StringBuffer format(long number, StringBuffer result, FieldPosition fieldPosition) {
-        return super.format(number, result, fieldPosition);
-    }
-
-    /**
-     * Formats a BigInteger number.
-     *
-     * @stable ICU 2.0
-     */
-    public StringBuffer format(BigInteger number, StringBuffer result,
-                               FieldPosition fieldPosition) {
-        return super.format(number, result, fieldPosition);
-    }
-
-    /**
-     * Formats a BigDecimal number.
-     *
-     * @stable ICU 2.0
-     */
-    public StringBuffer format(java.math.BigDecimal number, StringBuffer result,
-                               FieldPosition fieldPosition) {
-        return super.format(number, result, fieldPosition);
-    }
-
-    /**
-     * Formats a BigDecimal number.
-     *
-     * @stable ICU 2.0
-     */
-    public StringBuffer format(BigDecimal number, StringBuffer result,
-                               FieldPosition fieldPosition) {
-        return super.format(number, result, fieldPosition);
-    }
-
-    /**
-     * Parses the given string, returning a <code>Number</code> object to represent the
-     * parsed value. <code>Double</code> objects are returned to represent non-integral
-     * values which cannot be stored in a <code>BigDecimal</code>. These are
-     * <code>NaN</code>, infinity, -infinity, and -0.0. If {@link #isParseBigDecimal()} is
-     * false (the default), all other values are returned as <code>Long</code>,
-     * <code>BigInteger</code>, or <code>BigDecimal</code> values, in that order of
-     * preference. If {@link #isParseBigDecimal()} is true, all other values are returned
-     * as <code>BigDecimal</code> valuse. If the parse fails, null is returned.
-     *
-     * @param text the string to be parsed
-     * @param parsePosition defines the position where parsing is to begin, and upon
-     * return, the position where parsing left off. If the position has not changed upon
-     * return, then parsing failed.
-     * @return a <code>Number</code> object with the parsed value or
-     * <code>null</code> if the parse failed
-     * @stable ICU 2.0
-     */
-    public Number parse(String text, ParsePosition parsePosition) {
-        return super.parse(text, parsePosition);
-    }
-
-    /**
-     * Parses text from the given string as a CurrencyAmount. Unlike the parse() method,
-     * this method will attempt to parse a generic currency name, searching for a match of
-     * this object's locale's currency display names, or for a 3-letter ISO currency
-     * code. This method will fail if this format is not a currency format, that is, if it
-     * does not contain the currency pattern symbol (U+00A4) in its prefix or suffix.
-     *
-     * @param text the string to parse
-     * @param pos input-output position; on input, the position within text to match; must
-     *  have 0 <= pos.getIndex() < text.length(); on output, the position after the last
-     *  matched character. If the parse fails, the position in unchanged upon output.
-     * @return a CurrencyAmount, or null upon failure
-     */
-    CurrencyAmount parseCurrency(String text, ParsePosition pos) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Returns a copy of the decimal format symbols used by this format.
-     *
-     * @return desired DecimalFormatSymbols
-     * @see DecimalFormatSymbols
-     * @stable ICU 2.0
-     */
-    public DecimalFormatSymbols getDecimalFormatSymbols() {
-        return new DecimalFormatSymbols(((java.text.DecimalFormat)numberFormat).getDecimalFormatSymbols());
-    }
-
-    /**
-     * Sets the decimal format symbols used by this format. The format uses a copy of the
-     * provided symbols.
-     *
-     * @param newSymbols desired DecimalFormatSymbols
-     * @see DecimalFormatSymbols
-     * @stable ICU 2.0
-     */
-    public void setDecimalFormatSymbols(DecimalFormatSymbols newSymbols) {
-        ((java.text.DecimalFormat)numberFormat).setDecimalFormatSymbols(newSymbols.dfs);
-    }
-
-    /**
-     * Returns the positive prefix.
-     *
-     * <p>Examples: +123, $123, sFr123
-     * @return the prefix
-     * @stable ICU 2.0
-     */
-    public String getPositivePrefix() {
-        return ((java.text.DecimalFormat)numberFormat).getPositivePrefix();
-    }
-
-    /**
-     * Sets the positive prefix.
-     *
-     * <p>Examples: +123, $123, sFr123
-     * @param newValue the prefix
-     * @stable ICU 2.0
-     */
-    public void setPositivePrefix(String newValue) {
-        ((java.text.DecimalFormat)numberFormat).setPositivePrefix(newValue);
-    }
-
-    /**
-     * Returns the negative prefix.
-     *
-     * <p>Examples: -123, ($123) (with negative suffix), sFr-123
-     *
-     * @return the prefix
-     * @stable ICU 2.0
-     */
-    public String getNegativePrefix() {
-        return ((java.text.DecimalFormat)numberFormat).getNegativePrefix();
-    }
-
-    /**
-     * Sets the negative prefix.
-     *
-     * <p>Examples: -123, ($123) (with negative suffix), sFr-123
-     * @param newValue the prefix
-     * @stable ICU 2.0
-     */
-    public void setNegativePrefix(String newValue) {
-        ((java.text.DecimalFormat)numberFormat).setNegativePrefix(newValue);
-    }
-
-    /**
-     * Returns the positive suffix.
-     *
-     * <p>Example: 123%
-     *
-     * @return the suffix
-     * @stable ICU 2.0
-     */
-    public String getPositiveSuffix() {
-        return ((java.text.DecimalFormat)numberFormat).getPositiveSuffix();
-    }
-
-    /**
-     * Sets the positive suffix.
-     *
-     * <p>Example: 123%
-     * @param newValue the suffix
-     * @stable ICU 2.0
-     */
-    public void setPositiveSuffix(String newValue) {
-        ((java.text.DecimalFormat)numberFormat).setPositiveSuffix(newValue);
-    }
-
-    /**
-     * Returns the negative suffix.
-     *
-     * <p>Examples: -123%, ($123) (with positive suffixes)
-     *
-     * @return the suffix
-     * @stable ICU 2.0
-     */
-    public String getNegativeSuffix() {
-        return ((java.text.DecimalFormat)numberFormat).getNegativeSuffix();
-    }
-
-    /**
-     * Sets the positive suffix.
-     *
-     * <p>Examples: 123%
-     * @param newValue the suffix
-     * @stable ICU 2.0
-     */
-    public void setNegativeSuffix(String newValue) {
-        ((java.text.DecimalFormat)numberFormat).setNegativeSuffix(newValue);
-    }
-
-    /**
-     * Returns the multiplier for use in percent, permill, etc. For a percentage, set the
-     * suffixes to have "%" and the multiplier to be 100. (For Arabic, use arabic percent
-     * symbol). For a permill, set the suffixes to have "\u2031" and the multiplier to be
-     * 1000.
-     *
-     * <p>Examples: with 100, 1.23 -> "123", and "123" -> 1.23
-     *
-     * @return the multiplier
-     * @stable ICU 2.0
-     */
-    public int getMultiplier() {
-        return ((java.text.DecimalFormat)numberFormat).getMultiplier();
-    }
-
-    /**
-     * Sets the multiplier for use in percent, permill, etc. For a percentage, set the
-     * suffixes to have "%" and the multiplier to be 100. (For Arabic, use arabic percent
-     * symbol). For a permill, set the suffixes to have "\u2031" and the multiplier to be
-     * 1000.
-     *
-     * <p>Examples: with 100, 1.23 -> "123", and "123" -> 1.23
-     *
-     * @param newValue the multiplier
-     * @stable ICU 2.0
-     */
-    public void setMultiplier(int newValue) {
-        ((java.text.DecimalFormat)numberFormat).setMultiplier(newValue);
-    }
-
-    /**
-     * {@icu} Returns the rounding increment.
-     *
-     * @return A positive rounding increment, or <code>null</code> if rounding is not in
-     * effect.
-     * @see #setRoundingIncrement
-     * @see #getRoundingMode
-     * @see #setRoundingMode
-     * @stable ICU 2.0
-     */
-    public BigDecimal getRoundingIncrement() {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Sets the rounding increment. This method also controls whether rounding is
-     * enabled.
-     *
-     * @param newValue A positive rounding increment, or <code>null</code> or
-     * <code>BigDecimal(0.0)</code> to disable rounding.
-     * @throws IllegalArgumentException if <code>newValue</code> is < 0.0
-     * @see #getRoundingIncrement
-     * @see #getRoundingMode
-     * @see #setRoundingMode
-     * @stable ICU 2.0
-     */
-    public void setRoundingIncrement(java.math.BigDecimal newValue) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Sets the rounding increment. This method also controls whether rounding is
-     * enabled.
-     *
-     * @param newValue A positive rounding increment, or <code>null</code> or
-     * <code>BigDecimal(0.0)</code> to disable rounding.
-     * @throws IllegalArgumentException if <code>newValue</code> is < 0.0
-     * @see #getRoundingIncrement
-     * @see #getRoundingMode
-     * @see #setRoundingMode
-     * @stable ICU 3.6
-     */
-    public void setRoundingIncrement(BigDecimal newValue) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Sets the rounding increment. This method also controls whether rounding is
-     * enabled.
-     *
-     * @param newValue A positive rounding increment, or 0.0 to disable rounding.
-     * @throws IllegalArgumentException if <code>newValue</code> is < 0.0
-     * @see #getRoundingIncrement
-     * @see #getRoundingMode
-     * @see #setRoundingMode
-     * @stable ICU 2.0
-     */
-    public void setRoundingIncrement(double newValue) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Returns the rounding mode.
-     *
-     * @return A rounding mode, between <code>BigDecimal.ROUND_UP</code> and
-     * <code>BigDecimal.ROUND_UNNECESSARY</code>.
-     * @see #setRoundingIncrement
-     * @see #getRoundingIncrement
-     * @see #setRoundingMode
-     * @see java.math.BigDecimal
-     * @stable ICU 2.0
-     */
-    public int getRoundingMode() {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Sets the rounding mode. This has no effect unless the rounding increment is greater
-     * than zero.
-     *
-     * @param roundingMode A rounding mode, between <code>BigDecimal.ROUND_UP</code> and
-     * <code>BigDecimal.ROUND_UNNECESSARY</code>.
-     * @exception IllegalArgumentException if <code>roundingMode</code> is unrecognized.
-     * @see #setRoundingIncrement
-     * @see #getRoundingIncrement
-     * @see #getRoundingMode
-     * @see java.math.BigDecimal
-     * @stable ICU 2.0
-     */
-    public void setRoundingMode(int roundingMode) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Returns the width to which the output of <code>format()</code> is padded. The width is
-     * counted in 16-bit code units.
-     *
-     * @return the format width, or zero if no padding is in effect
-     * @see #setFormatWidth
-     * @see #getPadCharacter
-     * @see #setPadCharacter
-     * @see #getPadPosition
-     * @see #setPadPosition
-     * @stable ICU 2.0
-     */
-    public int getFormatWidth() {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Sets the width to which the output of <code>format()</code> is
-     * padded. The width is counted in 16-bit code units.  This method
-     * also controls whether padding is enabled.
-     *
-     * @param width the width to which to pad the result of
-     * <code>format()</code>, or zero to disable padding
-     * @exception IllegalArgumentException if <code>width</code> is < 0
-     * @see #getFormatWidth
-     * @see #getPadCharacter
-     * @see #setPadCharacter
-     * @see #getPadPosition
-     * @see #setPadPosition
-     * @stable ICU 2.0
-     */
-    public void setFormatWidth(int width) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Returns the character used to pad to the format width. The default is ' '.
-     *
-     * @return the pad character
-     * @see #setFormatWidth
-     * @see #getFormatWidth
-     * @see #setPadCharacter
-     * @see #getPadPosition
-     * @see #setPadPosition
-     * @stable ICU 2.0
-     */
-    public char getPadCharacter() {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Sets the character used to pad to the format width. If padding is not
-     * enabled, then this will take effect if padding is later enabled.
-     *
-     * @param padChar the pad character
-     * @see #setFormatWidth
-     * @see #getFormatWidth
-     * @see #getPadCharacter
-     * @see #getPadPosition
-     * @see #setPadPosition
-     * @stable ICU 2.0
-     */
-    public void setPadCharacter(char padChar) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Returns the position at which padding will take place. This is the location at
-     * which padding will be inserted if the result of <code>format()</code> is shorter
-     * than the format width.
-     *
-     * @return the pad position, one of <code>PAD_BEFORE_PREFIX</code>,
-     *         <code>PAD_AFTER_PREFIX</code>, <code>PAD_BEFORE_SUFFIX</code>, or
-     *         <code>PAD_AFTER_SUFFIX</code>.
-     * @see #setFormatWidth
-     * @see #getFormatWidth
-     * @see #setPadCharacter
-     * @see #getPadCharacter
-     * @see #setPadPosition
-     * @see #PAD_BEFORE_PREFIX
-     * @see #PAD_AFTER_PREFIX
-     * @see #PAD_BEFORE_SUFFIX
-     * @see #PAD_AFTER_SUFFIX
-     * @stable ICU 2.0
-     */
-    public int getPadPosition() {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Sets the position at which padding will take place. This is the location at
-     * which padding will be inserted if the result of <code>format()</code> is shorter
-     * than the format width. This has no effect unless padding is enabled.
-     *
-     * @param padPos the pad position, one of <code>PAD_BEFORE_PREFIX</code>,
-     * <code>PAD_AFTER_PREFIX</code>, <code>PAD_BEFORE_SUFFIX</code>, or
-     * <code>PAD_AFTER_SUFFIX</code>.
-     * @exception IllegalArgumentException if the pad position in unrecognized
-     * @see #setFormatWidth
-     * @see #getFormatWidth
-     * @see #setPadCharacter
-     * @see #getPadCharacter
-     * @see #getPadPosition
-     * @see #PAD_BEFORE_PREFIX
-     * @see #PAD_AFTER_PREFIX
-     * @see #PAD_BEFORE_SUFFIX
-     * @see #PAD_AFTER_SUFFIX
-     * @stable ICU 2.0
-     */
-    public void setPadPosition(int padPos) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Returns whether or not scientific notation is used.
-     *
-     * @return true if this object formats and parses scientific notation
-     * @see #setScientificNotation
-     * @see #getMinimumExponentDigits
-     * @see #setMinimumExponentDigits
-     * @see #isExponentSignAlwaysShown
-     * @see #setExponentSignAlwaysShown
-     * @stable ICU 2.0
-     */
-    public boolean isScientificNotation() {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Sets whether or not scientific notation is used. When scientific notation is
-     * used, the effective maximum number of integer digits is <= 8. If the maximum number
-     * of integer digits is set to more than 8, the effective maximum will be 1. This
-     * allows this call to generate a 'default' scientific number format without
-     * additional changes.
-     *
-     * @param useScientific true if this object formats and parses scientific notation
-     * @see #isScientificNotation
-     * @see #getMinimumExponentDigits
-     * @see #setMinimumExponentDigits
-     * @see #isExponentSignAlwaysShown
-     * @see #setExponentSignAlwaysShown
-     * @stable ICU 2.0
-     */
-    public void setScientificNotation(boolean useScientific) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Returns the minimum exponent digits that will be shown.
-     *
-     * @return the minimum exponent digits that will be shown
-     * @see #setScientificNotation
-     * @see #isScientificNotation
-     * @see #setMinimumExponentDigits
-     * @see #isExponentSignAlwaysShown
-     * @see #setExponentSignAlwaysShown
-     * @stable ICU 2.0
-     */
-    public byte getMinimumExponentDigits() {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Sets the minimum exponent digits that will be shown. This has no effect
-     * unless scientific notation is in use.
-     *
-     * @param minExpDig a value >= 1 indicating the fewest exponent
-     * digits that will be shown
-     * @exception IllegalArgumentException if <code>minExpDig</code> < 1
-     * @see #setScientificNotation
-     * @see #isScientificNotation
-     * @see #getMinimumExponentDigits
-     * @see #isExponentSignAlwaysShown
-     * @see #setExponentSignAlwaysShown
-     * @stable ICU 2.0
-     */
-    public void setMinimumExponentDigits(byte minExpDig) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Returns whether the exponent sign is always shown.
-     *
-     * @return true if the exponent is always prefixed with either the localized minus
-     * sign or the localized plus sign, false if only negative exponents are prefixed with
-     * the localized minus sign.
-     * @see #setScientificNotation
-     * @see #isScientificNotation
-     * @see #setMinimumExponentDigits
-     * @see #getMinimumExponentDigits
-     * @see #setExponentSignAlwaysShown
-     * @stable ICU 2.0
-     */
-    public boolean isExponentSignAlwaysShown() {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Sets whether the exponent sign is always shown. This has no effect unless
-     * scientific notation is in use.
-     *
-     * @param expSignAlways true if the exponent is always prefixed with either the
-     * localized minus sign or the localized plus sign, false if only negative exponents
-     * are prefixed with the localized minus sign.
-     * @see #setScientificNotation
-     * @see #isScientificNotation
-     * @see #setMinimumExponentDigits
-     * @see #getMinimumExponentDigits
-     * @see #isExponentSignAlwaysShown
-     * @stable ICU 2.0
-     */
-    public void setExponentSignAlwaysShown(boolean expSignAlways) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Returns the grouping size. Grouping size is the number of digits between grouping
-     * separators in the integer portion of a number. For example, in the number
-     * "123,456.78", the grouping size is 3.
-     *
-     * @see #setGroupingSize
-     * @see NumberFormat#isGroupingUsed
-     * @see DecimalFormatSymbols#getGroupingSeparator
-     * @stable ICU 2.0
-     */
-    public int getGroupingSize() {
-        return ((java.text.DecimalFormat)numberFormat).getGroupingSize();
-    }
-
-    /**
-     * Sets the grouping size. Grouping size is the number of digits between grouping
-     * separators in the integer portion of a number. For example, in the number
-     * "123,456.78", the grouping size is 3.
-     *
-     * @see #getGroupingSize
-     * @see NumberFormat#setGroupingUsed
-     * @see DecimalFormatSymbols#setGroupingSeparator
-     * @stable ICU 2.0
-     */
-    public void setGroupingSize(int newValue) {
-        ((java.text.DecimalFormat)numberFormat).setGroupingSize(newValue);
-    }
-
-    /**
-     * {@icu} Returns the secondary grouping size. In some locales one grouping interval
-     * is used for the least significant integer digits (the primary grouping size), and
-     * another is used for all others (the secondary grouping size). A formatter
-     * supporting a secondary grouping size will return a positive integer unequal to the
-     * primary grouping size returned by <code>getGroupingSize()</code>. For example, if
-     * the primary grouping size is 4, and the secondary grouping size is 2, then the
-     * number 123456789 formats as "1,23,45,6789", and the pattern appears as "#,##,###0".
-     *
-     * @return the secondary grouping size, or a value less than one if there is none
-     * @see #setSecondaryGroupingSize
-     * @see NumberFormat#isGroupingUsed
-     * @see DecimalFormatSymbols#getGroupingSeparator
-     * @stable ICU 2.0
-     */
-    public int getSecondaryGroupingSize() {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Sets the secondary grouping size. If set to a value less than 1, then
-     * secondary grouping is turned off, and the primary grouping size is used for all
-     * intervals, not just the least significant.
-     *
-     * @see #getSecondaryGroupingSize
-     * @see NumberFormat#setGroupingUsed
-     * @see DecimalFormatSymbols#setGroupingSeparator
-     * @stable ICU 2.0
-     */
-    public void setSecondaryGroupingSize(int newValue) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Returns the MathContext used by this format.
-     *
-     * @return desired MathContext
-     * @see #getMathContext
-     * @stable ICU 4.2
-     */
-    public MathContext getMathContextICU() {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Returns the MathContext used by this format.
-     *
-     * @return desired MathContext
-     * @see #getMathContext
-     * @stable ICU 4.2
-     */
-    public java.math.MathContext getMathContext() {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Sets the MathContext used by this format.
-     *
-     * @param newValue desired MathContext
-     * @see #getMathContext
-     * @stable ICU 4.2
-     */
-    public void setMathContextICU(MathContext newValue) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Sets the MathContext used by this format.
-     *
-     * @param newValue desired MathContext
-     * @see #getMathContext
-     * @stable ICU 4.2
-     */
-    public void setMathContext(java.math.MathContext newValue) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Returns the behavior of the decimal separator with integers. (The decimal
-     * separator will always appear with decimals.)  <p> Example: Decimal ON: 12345 ->
-     * 12345.; OFF: 12345 -> 12345
-     *
-     * @stable ICU 2.0
-     */
-    public boolean isDecimalSeparatorAlwaysShown() {
-        return ((java.text.DecimalFormat)numberFormat).isDecimalSeparatorAlwaysShown();
-    }
-
-    /**
-     * Sets the behavior of the decimal separator with integers. (The decimal separator
-     * will always appear with decimals.)
-     *
-     * <p>This only affects formatting, and only where there might be no digits after the
-     * decimal point, e.g., if true, 3456.00 -> "3,456." if false, 3456.00 -> "3456" This
-     * is independent of parsing. If you want parsing to stop at the decimal point, use
-     * setParseIntegerOnly.
-     *
-     * <p>
-     * Example: Decimal ON: 12345 -> 12345.; OFF: 12345 -> 12345
-     *
-     * @stable ICU 2.0
-     */
-    public void setDecimalSeparatorAlwaysShown(boolean newValue) {
-        ((java.text.DecimalFormat)numberFormat).setDecimalSeparatorAlwaysShown(newValue);
-    }
-
-    /**
-     * {@icu} Returns a copy of the CurrencyPluralInfo used by this format. It might
-     * return null if the decimal format is not a plural type currency decimal
-     * format. Plural type currency decimal format means either the pattern in the decimal
-     * format contains 3 currency signs, or the decimal format is initialized with
-     * PLURALCURRENCYSTYLE.
-     *
-     * @return desired CurrencyPluralInfo
-     * @see CurrencyPluralInfo
-     * @stable ICU 4.2
-     */
-    public CurrencyPluralInfo getCurrencyPluralInfo() {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Sets the CurrencyPluralInfo used by this format. The format uses a copy of
-     * the provided information.
-     *
-     * @param newInfo desired CurrencyPluralInfo
-     * @see CurrencyPluralInfo
-     * @stable ICU 4.2
-     */
-    public void setCurrencyPluralInfo(CurrencyPluralInfo newInfo) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Overrides clone.
-     * @stable ICU 2.0
-     */
-    public Object clone() {
-        return new DecimalFormatSymbols((java.text.DecimalFormatSymbols)numberFormat.clone());
-    }
-
-    /**
-     * Overrides equals.
-     * @stable ICU 2.0
-     */
-    public boolean equals(Object obj) {
-        return super.equals(obj);
-    }
-
-    /**
-     * Overrides hashCode.
-     * @stable ICU 2.0
-     */
-    public int hashCode() {
-        return super.hashCode();
-    }
-
-    /**
-     * Synthesizes a pattern string that represents the current state of this Format
-     * object.
-     *
-     * @see #applyPattern
-     * @stable ICU 2.0
-     */
-    public String toPattern() {
-        return ((java.text.DecimalFormat)numberFormat).toPattern();
-    }
-
-    /**
-     * Synthesizes a localized pattern string that represents the current state of this
-     * Format object.
-     *
-     * @see #applyPattern
-     * @stable ICU 2.0
-     */
-    public String toLocalizedPattern() {
-        return ((java.text.DecimalFormat)numberFormat).toLocalizedPattern();
-    }
-
-    /**
-     * Formats the object to an attributed string, and return the corresponding iterator.
-     *
-     * @stable ICU 3.6
-     */
-    public AttributedCharacterIterator formatToCharacterIterator(Object obj) {
-        AttributedCharacterIterator it = numberFormat.formatToCharacterIterator(obj);
-
-        // Extract formatted String first
-        StringBuilder sb = new StringBuilder();
-        for (char c = it.first(); c != CharacterIterator.DONE; c = it.next()) {
-            sb.append(c);
-        }
-
-        // Create AttributedString
-        AttributedString attrstr = new AttributedString(sb.toString());
-
-        // Map JDK Field to ICU Field
-        int idx = 0;
-        it.first();
-        while (idx < it.getEndIndex()) {
-            int end = it.getRunLimit();
-            Map<Attribute, Object> attributes = it.getAttributes();
-            if (attributes != null) {
-                for (Entry<Attribute, Object> entry : attributes.entrySet()) {
-                    Attribute attr = entry.getKey();
-                    Object val = entry.getValue();
-                    if (attr.equals(java.text.NumberFormat.Field.CURRENCY)) {
-                        val = attr = Field.CURRENCY;
-                    } else if (attr.equals(java.text.NumberFormat.Field.DECIMAL_SEPARATOR)) {
-                        val = attr = Field.DECIMAL_SEPARATOR;
-                    } else if (attr.equals(java.text.NumberFormat.Field.EXPONENT)) {
-                        val = attr = Field.EXPONENT;
-                    } else if (attr.equals(java.text.NumberFormat.Field.EXPONENT_SIGN)) {
-                        val = attr = Field.EXPONENT_SIGN;
-                    } else if (attr.equals(java.text.NumberFormat.Field.EXPONENT_SYMBOL)) {
-                        val = attr = Field.EXPONENT_SYMBOL;
-                    } else if (attr.equals(java.text.NumberFormat.Field.FRACTION)) {
-                        val = attr = Field.FRACTION;
-                    } else if (attr.equals(java.text.NumberFormat.Field.GROUPING_SEPARATOR)) {
-                        val = attr = Field.GROUPING_SEPARATOR;
-                    } else if (attr.equals(java.text.NumberFormat.Field.INTEGER)) {
-                        val = attr = Field.INTEGER;
-                    } else if (attr.equals(java.text.NumberFormat.Field.PERCENT)) {
-                        val = attr = Field.PERCENT;
-                    } else if (attr.equals(java.text.NumberFormat.Field.PERMILLE)) {
-                        val = attr = Field.PERMILLE;
-                    } else if (attr.equals(java.text.NumberFormat.Field.SIGN)) {
-                        val = attr = Field.SIGN;
-                    }
-                    attrstr.addAttribute(attr, val, idx, end);
-                }
-            }
-            idx = end;
-            while (it.getIndex() < idx) {
-                it.next();
-            }
-        }
-
-        return attrstr.getIterator();
-    }
-
-    /**
-     * Applies the given pattern to this Format object. A pattern is a short-hand
-     * specification for the various formatting properties. These properties can also be
-     * changed individually through the various setter methods.
-     *
-     * <p>There is no limit to integer digits are set by this routine, since that is the
-     * typical end-user desire; use setMaximumInteger if you want to set a real value. For
-     * negative numbers, use a second pattern, separated by a semicolon
-     *
-     * <p>Example "#,#00.0#" -> 1,234.56
-     *
-     * <p>This means a minimum of 2 integer digits, 1 fraction digit, and a maximum of 2
-     * fraction digits.
-     *
-     * <p>Example: "#,#00.0#;(#,#00.0#)" for negatives in parentheses.
-     *
-     * <p>In negative patterns, the minimum and maximum counts are ignored; these are
-     * presumed to be set in the positive pattern.
-     *
-     * @stable ICU 2.0
-     */
-    public void applyPattern(String pattern) {
-        ((java.text.DecimalFormat)numberFormat).applyPattern(pattern);
-    }
-
-    /**
-     * Applies the given pattern to this Format object. The pattern is assumed to be in a
-     * localized notation. A pattern is a short-hand specification for the various
-     * formatting properties. These properties can also be changed individually through
-     * the various setter methods.
-     *
-     * <p>There is no limit to integer digits are set by this routine, since that is the
-     * typical end-user desire; use setMaximumInteger if you want to set a real value. For
-     * negative numbers, use a second pattern, separated by a semicolon
-     *
-     * <p>Example "#,#00.0#" -> 1,234.56
-     *
-     * <p>This means a minimum of 2 integer digits, 1 fraction digit, and a maximum of 2
-     * fraction digits.
-     *
-     * <p>Example: "#,#00.0#;(#,#00.0#)" for negatives in parantheses.
-     *
-     * <p>In negative patterns, the minimum and maximum counts are ignored; these are
-     * presumed to be set in the positive pattern.
-     *
-     * @stable ICU 2.0
-     */
-    public void applyLocalizedPattern(String pattern) {
-        ((java.text.DecimalFormat)numberFormat).applyLocalizedPattern(pattern);
-    }
-
-    /**
-     * Sets the maximum number of digits allowed in the integer portion of a number. This
-     * override limits the integer digit count to 309.
-     *
-     * @see NumberFormat#setMaximumIntegerDigits
-     * @stable ICU 2.0
-     */
-    public void setMaximumIntegerDigits(int newValue) {
-        super.setMaximumIntegerDigits(newValue);
-    }
-
-    /**
-     * Sets the minimum number of digits allowed in the integer portion of a number. This
-     * override limits the integer digit count to 309.
-     *
-     * @see NumberFormat#setMinimumIntegerDigits
-     * @stable ICU 2.0
-     */
-    public void setMinimumIntegerDigits(int newValue) {
-        super.setMinimumIntegerDigits(newValue);
-    }
-
-    /**
-     * {@icu} Returns the minimum number of significant digits that will be
-     * displayed. This value has no effect unless {@link #areSignificantDigitsUsed()}
-     * returns true.
-     *
-     * @return the fewest significant digits that will be shown
-     * @stable ICU 3.0
-     */
-    public int getMinimumSignificantDigits() {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Returns the maximum number of significant digits that will be
-     * displayed. This value has no effect unless {@link #areSignificantDigitsUsed()}
-     * returns true.
-     *
-     * @return the most significant digits that will be shown
-     * @stable ICU 3.0
-     */
-    public int getMaximumSignificantDigits() {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Sets the minimum number of significant digits that will be displayed. If
-     * <code>min</code> is less than one then it is set to one. If the maximum significant
-     * digits count is less than <code>min</code>, then it is set to
-     * <code>min</code>. This value has no effect unless {@link #areSignificantDigitsUsed()}
-     * returns true.
-     *
-     * @param min the fewest significant digits to be shown
-     * @stable ICU 3.0
-     */
-    public void setMinimumSignificantDigits(int min) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Sets the maximum number of significant digits that will be displayed. If
-     * <code>max</code> is less than one then it is set to one. If the minimum significant
-     * digits count is greater than <code>max</code>, then it is set to
-     * <code>max</code>. This value has no effect unless {@link #areSignificantDigitsUsed()}
-     * returns true.
-     *
-     * @param max the most significant digits to be shown
-     * @stable ICU 3.0
-     */
-    public void setMaximumSignificantDigits(int max) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Returns true if significant digits are in use or false if integer and
-     * fraction digit counts are in use.
-     *
-     * @return true if significant digits are in use
-     * @stable ICU 3.0
-     */
-    public boolean areSignificantDigitsUsed() {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Sets whether significant digits are in use, or integer and fraction digit
-     * counts are in use.
-     *
-     * @param useSignificantDigits true to use significant digits, or false to use integer
-     * and fraction digit counts
-     * @stable ICU 3.0
-     */
-    public void setSignificantDigitsUsed(boolean useSignificantDigits) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Sets the <tt>Currency</tt> object used to display currency amounts. This takes
-     * effect immediately, if this format is a currency format. If this format is not a
-     * currency format, then the currency object is used if and when this object becomes a
-     * currency format through the application of a new pattern.
-     *
-     * @param theCurrency new currency object to use. Must not be null.
-     * @stable ICU 2.2
-     */
-    public void setCurrency(Currency theCurrency) {
-        super.setCurrency(theCurrency);
-    }
-
-    /**
-     * Sets the maximum number of digits allowed in the fraction portion of a number. This
-     * override limits the fraction digit count to 340.
-     *
-     * @see NumberFormat#setMaximumFractionDigits
-     * @stable ICU 2.0
-     */
-    public void setMaximumFractionDigits(int newValue) {
-        super.setMaximumFractionDigits(newValue);
-    }
-
-    /**
-     * Sets the minimum number of digits allowed in the fraction portion of a number. This
-     * override limits the fraction digit count to 340.
-     *
-     * @see NumberFormat#setMinimumFractionDigits
-     * @stable ICU 2.0
-     */
-    public void setMinimumFractionDigits(int newValue) {
-        super.setMinimumFractionDigits(newValue);
-    }
-
-    /**
-     * Sets whether {@link #parse(String, ParsePosition)} returns BigDecimal. The
-     * default value is false.
-     *
-     * @param value true if {@link #parse(String, ParsePosition)}
-     * returns BigDecimal.
-     * @stable ICU 3.6
-     */
-    public void setParseBigDecimal(boolean value) {
-        ((java.text.DecimalFormat)numberFormat).setParseBigDecimal(value);
-    }
-
-    /**
-     * Returns whether {@link #parse(String, ParsePosition)} returns BigDecimal.
-     *
-     * @return true if {@link #parse(String, ParsePosition)} returns BigDecimal.
-     * @stable ICU 3.6
-     */
-    public boolean isParseBigDecimal() {
-        return ((java.text.DecimalFormat)numberFormat).isParseBigDecimal();
-    }
-
-    // ----------------------------------------------------------------------
-    // CONSTANTS
-    // ----------------------------------------------------------------------
-
-    /**
-     * {@icu} Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to
-     * specify pad characters inserted before the prefix.
-     *
-     * @see #setPadPosition
-     * @see #getPadPosition
-     * @see #PAD_AFTER_PREFIX
-     * @see #PAD_BEFORE_SUFFIX
-     * @see #PAD_AFTER_SUFFIX
-     * @stable ICU 2.0
-     */
-    public static final int PAD_BEFORE_PREFIX = 0;
-
-    /**
-     * {@icu} Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to
-     * specify pad characters inserted after the prefix.
-     *
-     * @see #setPadPosition
-     * @see #getPadPosition
-     * @see #PAD_BEFORE_PREFIX
-     * @see #PAD_BEFORE_SUFFIX
-     * @see #PAD_AFTER_SUFFIX
-     * @stable ICU 2.0
-     */
-    public static final int PAD_AFTER_PREFIX = 1;
-
-    /**
-     * {@icu} Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to
-     * specify pad characters inserted before the suffix.
-     *
-     * @see #setPadPosition
-     * @see #getPadPosition
-     * @see #PAD_BEFORE_PREFIX
-     * @see #PAD_AFTER_PREFIX
-     * @see #PAD_AFTER_SUFFIX
-     * @stable ICU 2.0
-     */
-    public static final int PAD_BEFORE_SUFFIX = 2;
-
-    /**
-     * {@icu} Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to
-     * specify pad characters inserted after the suffix.
-     *
-     * @see #setPadPosition
-     * @see #getPadPosition
-     * @see #PAD_BEFORE_PREFIX
-     * @see #PAD_AFTER_PREFIX
-     * @see #PAD_BEFORE_SUFFIX
-     * @stable ICU 2.0
-     */
-    public static final int PAD_AFTER_SUFFIX = 3;
-}
-
-// eof
+/*
+ *******************************************************************************
+ * Copyright (C) 1996-2011, International Business Machines Corporation and    *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+package com.ibm.icu.text;
+
+import java.math.BigInteger;
+import java.text.AttributedCharacterIterator;
+import java.text.AttributedCharacterIterator.Attribute;
+import java.text.AttributedString;
+import java.text.CharacterIterator;
+import java.text.FieldPosition;
+import java.text.ParsePosition;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import com.ibm.icu.math.BigDecimal;
+import com.ibm.icu.math.MathContext;
+import com.ibm.icu.util.Currency;
+import com.ibm.icu.util.CurrencyAmount;
+
+/**
+ * {@icuenhanced java.text.DecimalFormat}.{@icu _usage_}
+ *
+ * <code>DecimalFormat</code> is a concrete subclass of {@link NumberFormat} that formats
+ * decimal numbers. It has a variety of features designed to make it possible to parse and
+ * format numbers in any locale, including support for Western, Arabic, or Indic digits.
+ * It also supports different flavors of numbers, including integers ("123"), fixed-point
+ * numbers ("123.4"), scientific notation ("1.23E4"), percentages ("12%"), and currency
+ * amounts ("$123.00", "USD123.00", "123.00 US dollars").  All of these flavors can be
+ * easily localized.
+ *
+ * <p>To obtain a {@link NumberFormat} for a specific locale (including the default
+ * locale) call one of <code>NumberFormat</code>'s factory methods such as {@link
+ * NumberFormat#getInstance}. Do not call the <code>DecimalFormat</code> constructors
+ * directly, unless you know what you are doing, since the {@link NumberFormat} factory
+ * methods may return subclasses other than <code>DecimalFormat</code>. If you need to
+ * customize the format object, do something like this:
+ *
+ * <blockquote><pre>
+ * NumberFormat f = NumberFormat.getInstance(loc);
+ * if (f instanceof DecimalFormat) {
+ *     ((DecimalFormat) f).setDecimalSeparatorAlwaysShown(true);
+ * }</pre></blockquote>
+ *
+ * <p><strong>Example Usage</strong>
+ *
+ * Print out a number using the localized number, currency, and percent
+ * format for each locale.
+ *
+ * <blockquote><pre>
+ * Locale[] locales = NumberFormat.getAvailableLocales();
+ * double myNumber = -1234.56;
+ * NumberFormat format;
+ * for (int j=0; j<3; ++j) {
+ *     System.out.println("FORMAT");
+ *     for (int i = 0; i < locales.length; ++i) {
+ *         if (locales[i].getCountry().length() == 0) {
+ *            // Skip language-only locales
+ *            continue;
+ *         }
+ *         System.out.print(locales[i].getDisplayName());
+ *         switch (j) {
+ *         case 0:
+ *             format = NumberFormat.getInstance(locales[i]); break;
+ *         case 1:
+ *             format = NumberFormat.getCurrencyInstance(locales[i]); break;
+ *         default:
+ *             format = NumberFormat.getPercentInstance(locales[i]); break;
+ *         }
+ *         try {
+ *             // Assume format is a DecimalFormat
+ *             System.out.print(": " + ((DecimalFormat) format).toPattern()
+ *                              + " -> " + form.format(myNumber));
+ *         } catch (Exception e) {}
+ *         try {
+ *             System.out.println(" -> " + format.parse(form.format(myNumber)));
+ *         } catch (ParseException e) {}
+ *     }
+ * }</pre></blockquote>
+ *
+ * <p>Another example use getInstance(style).<br/>
+ * Print out a number using the localized number, currency, percent,
+ * scientific, integer, iso currency, and plural currency format for each locale.
+ *
+ * <blockquote><pre>
+ * ULocale locale = new ULocale("en_US");
+ * double myNumber = 1234.56;
+ * for (int j=NumberFormat.NUMBERSTYLE; j<=NumberFormat.PLURALCURRENCYSTYLE; ++j) {
+ *     NumberFormat format = NumberFormat.getInstance(locale, j);
+ *     try {
+ *         // Assume format is a DecimalFormat
+ *         System.out.print(": " + ((DecimalFormat) format).toPattern()
+ *                          + " -> " + form.format(myNumber));
+ *     } catch (Exception e) {}
+ *     try {
+ *         System.out.println(" -> " + format.parse(form.format(myNumber)));
+ *     } catch (ParseException e) {}
+ * }</pre></blockquote>
+ *
+ * <h4>Patterns</h4>
+ *
+ * <p>A <code>DecimalFormat</code> consists of a <em>pattern</em> and a set of
+ * <em>symbols</em>.  The pattern may be set directly using {@link #applyPattern}, or
+ * indirectly using other API methods which manipulate aspects of the pattern, such as the
+ * minimum number of integer digits.  The symbols are stored in a {@link
+ * DecimalFormatSymbols} object.  When using the {@link NumberFormat} factory methods, the
+ * pattern and symbols are read from ICU's locale data.
+ *
+ * <h4>Special Pattern Characters</h4>
+ *
+ * <p>Many characters in a pattern are taken literally; they are matched during parsing
+ * and output unchanged during formatting.  Special characters, on the other hand, stand
+ * for other characters, strings, or classes of characters.  For example, the '#'
+ * character is replaced by a localized digit.  Often the replacement character is the
+ * same as the pattern character; in the U.S. locale, the ',' grouping character is
+ * replaced by ','.  However, the replacement is still happening, and if the symbols are
+ * modified, the grouping character changes.  Some special characters affect the behavior
+ * of the formatter by their presence; for example, if the percent character is seen, then
+ * the value is multiplied by 100 before being displayed.
+ *
+ * <p>To insert a special character in a pattern as a literal, that is, without any
+ * special meaning, the character must be quoted.  There are some exceptions to this which
+ * are noted below.
+ *
+ * <p>The characters listed here are used in non-localized patterns.  Localized patterns
+ * use the corresponding characters taken from this formatter's {@link
+ * DecimalFormatSymbols} object instead, and these characters lose their special status.
+ * Two exceptions are the currency sign and quote, which are not localized.
+ *
+ * <blockquote>
+ * <table border=0 cellspacing=3 cellpadding=0 summary="Chart showing symbol,
+ *  location, localized, and meaning.">
+ *   <tr bgcolor="#ccccff">
+ *     <th align=left>Symbol
+ *     <th align=left>Location
+ *     <th align=left>Localized?
+ *     <th align=left>Meaning
+ *   <tr valign=top>
+ *     <td><code>0</code>
+ *     <td>Number
+ *     <td>Yes
+ *     <td>Digit
+ *   <tr valign=top bgcolor="#eeeeff">
+ *     <td><code>1-9</code>
+ *     <td>Number
+ *     <td>Yes
+ *     <td>'1' through '9' indicate rounding.
+ *   <tr valign=top>
+ *     <td><code>@</code>
+ *     <td>Number
+ *     <td>No
+ *     <td>Significant digit
+ *   <tr valign=top bgcolor="#eeeeff">
+ *     <td><code>#</code>
+ *     <td>Number
+ *     <td>Yes
+ *     <td>Digit, zero shows as absent
+ *   <tr valign=top>
+ *     <td><code>.</code>
+ *     <td>Number
+ *     <td>Yes
+ *     <td>Decimal separator or monetary decimal separator
+ *   <tr valign=top bgcolor="#eeeeff">
+ *     <td><code>-</code>
+ *     <td>Number
+ *     <td>Yes
+ *     <td>Minus sign
+ *   <tr valign=top>
+ *     <td><code>,</code>
+ *     <td>Number
+ *     <td>Yes
+ *     <td>Grouping separator
+ *   <tr valign=top bgcolor="#eeeeff">
+ *     <td><code>E</code>
+ *     <td>Number
+ *     <td>Yes
+ *     <td>Separates mantissa and exponent in scientific notation.
+ *         <em>Need not be quoted in prefix or suffix.</em>
+ *   <tr valign=top>
+ *     <td><code>+</code>
+ *     <td>Exponent
+ *     <td>Yes
+ *     <td>Prefix positive exponents with localized plus sign.
+ *         <em>Need not be quoted in prefix or suffix.</em>
+ *   <tr valign=top bgcolor="#eeeeff">
+ *     <td><code>;</code>
+ *     <td>Subpattern boundary
+ *     <td>Yes
+ *     <td>Separates positive and negative subpatterns
+ *   <tr valign=top>
+ *     <td><code>%</code>
+ *     <td>Prefix or suffix
+ *     <td>Yes
+ *     <td>Multiply by 100 and show as percentage
+ *   <tr valign=top bgcolor="#eeeeff">
+ *     <td><code>&#92;u2030</code>
+ *     <td>Prefix or suffix
+ *     <td>Yes
+ *     <td>Multiply by 1000 and show as per mille
+ *   <tr valign=top>
+ *     <td><code>&#164;</code> (<code>&#92;u00A4</code>)
+ *     <td>Prefix or suffix
+ *     <td>No
+ *     <td>Currency sign, replaced by currency symbol.  If
+ *         doubled, replaced by international currency symbol.
+ *         If tripled, replaced by currency plural names, for example,
+ *         "US dollar" or "US dollars" for America.
+ *         If present in a pattern, the monetary decimal separator
+ *         is used instead of the decimal separator.
+ *   <tr valign=top bgcolor="#eeeeff">
+ *     <td><code>'</code>
+ *     <td>Prefix or suffix
+ *     <td>No
+ *     <td>Used to quote special characters in a prefix or suffix,
+ *         for example, <code>"'#'#"</code> formats 123 to
+ *         <code>"#123"</code>.  To create a single quote
+ *         itself, use two in a row: <code>"# o''clock"</code>.
+ *   <tr valign=top>
+ *     <td><code>*</code>
+ *     <td>Prefix or suffix boundary
+ *     <td>Yes
+ *     <td>Pad escape, precedes pad character
+ * </table>
+ * </blockquote>
+ *
+ * <p>A <code>DecimalFormat</code> pattern contains a postive and negative subpattern, for
+ * example, "#,##0.00;(#,##0.00)".  Each subpattern has a prefix, a numeric part, and a
+ * suffix.  If there is no explicit negative subpattern, the negative subpattern is the
+ * localized minus sign prefixed to the positive subpattern. That is, "0.00" alone is
+ * equivalent to "0.00;-0.00".  If there is an explicit negative subpattern, it serves
+ * only to specify the negative prefix and suffix; the number of digits, minimal digits,
+ * and other characteristics are ignored in the negative subpattern. That means that
+ * "#,##0.0#;(#)" has precisely the same result as "#,##0.0#;(#,##0.0#)".
+ *
+ * <p>The prefixes, suffixes, and various symbols used for infinity, digits, thousands
+ * separators, decimal separators, etc. may be set to arbitrary values, and they will
+ * appear properly during formatting.  However, care must be taken that the symbols and
+ * strings do not conflict, or parsing will be unreliable.  For example, either the
+ * positive and negative prefixes or the suffixes must be distinct for {@link #parse} to
+ * be able to distinguish positive from negative values.  Another example is that the
+ * decimal separator and thousands separator should be distinct characters, or parsing
+ * will be impossible.
+ *
+ * <p>The <em>grouping separator</em> is a character that separates clusters of integer
+ * digits to make large numbers more legible.  It commonly used for thousands, but in some
+ * locales it separates ten-thousands.  The <em>grouping size</em> is the number of digits
+ * between the grouping separators, such as 3 for "100,000,000" or 4 for "1 0000
+ * 0000". There are actually two different grouping sizes: One used for the least
+ * significant integer digits, the <em>primary grouping size</em>, and one used for all
+ * others, the <em>secondary grouping size</em>.  In most locales these are the same, but
+ * sometimes they are different. For example, if the primary grouping interval is 3, and
+ * the secondary is 2, then this corresponds to the pattern "#,##,##0", and the number
+ * 123456789 is formatted as "12,34,56,789".  If a pattern contains multiple grouping
+ * separators, the interval between the last one and the end of the integer defines the
+ * primary grouping size, and the interval between the last two defines the secondary
+ * grouping size. All others are ignored, so "#,##,###,####" == "###,###,####" ==
+ * "##,#,###,####".
+ *
+ * <p>Illegal patterns, such as "#.#.#" or "#.###,###", will cause
+ * <code>DecimalFormat</code> to throw an {@link IllegalArgumentException} with a message
+ * that describes the problem.
+ *
+ * <h4>Pattern BNF</h4>
+ *
+ * <pre>
+ * pattern    := subpattern (';' subpattern)?
+ * subpattern := prefix? number exponent? suffix?
+ * number     := (integer ('.' fraction)?) | sigDigits
+ * prefix     := '&#92;u0000'..'&#92;uFFFD' - specialCharacters
+ * suffix     := '&#92;u0000'..'&#92;uFFFD' - specialCharacters
+ * integer    := '#'* '0'* '0'
+ * fraction   := '0'* '#'*
+ * sigDigits  := '#'* '@' '@'* '#'*
+ * exponent   := 'E' '+'? '0'* '0'
+ * padSpec    := '*' padChar
+ * padChar    := '&#92;u0000'..'&#92;uFFFD' - quote
+ * &#32;
+ * Notation:
+ *   X*       0 or more instances of X
+ *   X?       0 or 1 instances of X
+ *   X|Y      either X or Y
+ *   C..D     any character from C up to D, inclusive
+ *   S-T      characters in S, except those in T
+ * </pre>
+ * The first subpattern is for positive numbers. The second (optional)
+ * subpattern is for negative numbers.
+ *
+ * <p>Not indicated in the BNF syntax above:
+ *
+ * <ul>
+ *
+ * <li>The grouping separator ',' can occur inside the integer and sigDigits
+ * elements, between any two pattern characters of that element, as long as the integer or
+ * sigDigits element is not followed by the exponent element.
+ *
+ * <li>Two grouping intervals are recognized: That between the decimal point and the first
+ * grouping symbol, and that between the first and second grouping symbols. These
+ * intervals are identical in most locales, but in some locales they differ. For example,
+ * the pattern &quot;#,##,###&quot; formats the number 123456789 as
+ * &quot;12,34,56,789&quot;.
+ *
+ * <li>The pad specifier <code>padSpec</code> may appear before the prefix, after the
+ * prefix, before the suffix, after the suffix, or not at all.
+ *
+ * <li>In place of '0', the digits '1' through '9' may be used to indicate a rounding
+ * increment.
+ *
+ * </ul>
+ *
+ * <h4>Parsing</h4>
+ *
+ * <p><code>DecimalFormat</code> parses all Unicode characters that represent decimal
+ * digits, as defined by {@link UCharacter#digit}.  In addition,
+ * <code>DecimalFormat</code> also recognizes as digits the ten consecutive characters
+ * starting with the localized zero digit defined in the {@link DecimalFormatSymbols}
+ * object.  During formatting, the {@link DecimalFormatSymbols}-based digits are output.
+ *
+ * <p>During parsing, grouping separators are ignored.
+ *
+ * <p>For currency parsing, the formatter is able to parse every currency style formats no
+ * matter which style the formatter is constructed with.  For example, a formatter
+ * instance gotten from NumberFormat.getInstance(ULocale, NumberFormat.CURRENCYSTYLE) can
+ * parse formats such as "USD1.00" and "3.00 US dollars".
+ *
+ * <p>If {@link #parse(String, ParsePosition)} fails to parse a string, it returns
+ * <code>null</code> and leaves the parse position unchanged.  The convenience method
+ * {@link #parse(String)} indicates parse failure by throwing a {@link
+ * java.text.ParseException}.
+ *
+ * <h4>Formatting</h4>
+ *
+ * <p>Formatting is guided by several parameters, all of which can be specified either
+ * using a pattern or using the API.  The following description applies to formats that do
+ * not use <a href="#sci">scientific notation</a> or <a href="#sigdig">significant
+ * digits</a>.
+ *
+ * <ul><li>If the number of actual integer digits exceeds the <em>maximum integer
+ * digits</em>, then only the least significant digits are shown.  For example, 1997 is
+ * formatted as "97" if the maximum integer digits is set to 2.
+ *
+ * <li>If the number of actual integer digits is less than the <em>minimum integer
+ * digits</em>, then leading zeros are added.  For example, 1997 is formatted as "01997"
+ * if the minimum integer digits is set to 5.
+ *
+ * <li>If the number of actual fraction digits exceeds the <em>maximum fraction
+ * digits</em>, then half-even rounding it performed to the maximum fraction digits.  For
+ * example, 0.125 is formatted as "0.12" if the maximum fraction digits is 2.  This
+ * behavior can be changed by specifying a rounding increment and a rounding mode.
+ *
+ * <li>If the number of actual fraction digits is less than the <em>minimum fraction
+ * digits</em>, then trailing zeros are added.  For example, 0.125 is formatted as
+ * "0.1250" if the mimimum fraction digits is set to 4.
+ *
+ * <li>Trailing fractional zeros are not displayed if they occur <em>j</em> positions
+ * after the decimal, where <em>j</em> is less than the maximum fraction digits. For
+ * example, 0.10004 is formatted as "0.1" if the maximum fraction digits is four or less.
+ * </ul>
+ *
+ * <p><strong>Special Values</strong>
+ *
+ * <p><code>NaN</code> is represented as a single character, typically
+ * <code>&#92;uFFFD</code>.  This character is determined by the {@link
+ * DecimalFormatSymbols} object.  This is the only value for which the prefixes and
+ * suffixes are not used.
+ *
+ * <p>Infinity is represented as a single character, typically <code>&#92;u221E</code>,
+ * with the positive or negative prefixes and suffixes applied.  The infinity character is
+ * determined by the {@link DecimalFormatSymbols} object.
+ *
+ * <a name="sci"><h4>Scientific Notation</h4></a>
+ *
+ * <p>Numbers in scientific notation are expressed as the product of a mantissa and a
+ * power of ten, for example, 1234 can be expressed as 1.234 x 10<sup>3</sup>. The
+ * mantissa is typically in the half-open interval [1.0, 10.0) or sometimes [0.0, 1.0),
+ * but it need not be.  <code>DecimalFormat</code> supports arbitrary mantissas.
+ * <code>DecimalFormat</code> can be instructed to use scientific notation through the API
+ * or through the pattern.  In a pattern, the exponent character immediately followed by
+ * one or more digit characters indicates scientific notation.  Example: "0.###E0" formats
+ * the number 1234 as "1.234E3".
+ *
+ * <ul>
+ *
+ * <li>The number of digit characters after the exponent character gives the minimum
+ * exponent digit count.  There is no maximum.  Negative exponents are formatted using the
+ * localized minus sign, <em>not</em> the prefix and suffix from the pattern.  This allows
+ * patterns such as "0.###E0 m/s".  To prefix positive exponents with a localized plus
+ * sign, specify '+' between the exponent and the digits: "0.###E+0" will produce formats
+ * "1E+1", "1E+0", "1E-1", etc.  (In localized patterns, use the localized plus sign
+ * rather than '+'.)
+ *
+ * <li>The minimum number of integer digits is achieved by adjusting the exponent.
+ * Example: 0.00123 formatted with "00.###E0" yields "12.3E-4".  This only happens if
+ * there is no maximum number of integer digits.  If there is a maximum, then the minimum
+ * number of integer digits is fixed at one.
+ *
+ * <li>The maximum number of integer digits, if present, specifies the exponent grouping.
+ * The most common use of this is to generate <em>engineering notation</em>, in which the
+ * exponent is a multiple of three, e.g., "##0.###E0".  The number 12345 is formatted
+ * using "##0.####E0" as "12.345E3".
+ *
+ * <li>When using scientific notation, the formatter controls the digit counts using
+ * significant digits logic.  The maximum number of significant digits limits the total
+ * number of integer and fraction digits that will be shown in the mantissa; it does not
+ * affect parsing.  For example, 12345 formatted with "##0.##E0" is "12.3E3".  See the
+ * section on significant digits for more details.
+ *
+ * <li>The number of significant digits shown is determined as follows: If
+ * areSignificantDigitsUsed() returns false, then the minimum number of significant digits
+ * shown is one, and the maximum number of significant digits shown is the sum of the
+ * <em>minimum integer</em> and <em>maximum fraction</em> digits, and is unaffected by the
+ * maximum integer digits.  If this sum is zero, then all significant digits are shown.
+ * If areSignificantDigitsUsed() returns true, then the significant digit counts are
+ * specified by getMinimumSignificantDigits() and getMaximumSignificantDigits().  In this
+ * case, the number of integer digits is fixed at one, and there is no exponent grouping.
+ *
+ * <li>Exponential patterns may not contain grouping separators.
+ *
+ * </ul>
+ *
+ * <a name="sigdig"><h4>Significant Digits</h4></a>
+ *
+ * <code>DecimalFormat</code> has two ways of controlling how many digits are shows: (a)
+ * significant digits counts, or (b) integer and fraction digit counts.  Integer and
+ * fraction digit counts are described above.  When a formatter is using significant
+ * digits counts, the number of integer and fraction digits is not specified directly, and
+ * the formatter settings for these counts are ignored.  Instead, the formatter uses
+ * however many integer and fraction digits are required to display the specified number
+ * of significant digits.  Examples:
+ *
+ * <blockquote>
+ * <table border=0 cellspacing=3 cellpadding=0>
+ *   <tr bgcolor="#ccccff">
+ *     <th align=left>Pattern
+ *     <th align=left>Minimum significant digits
+ *     <th align=left>Maximum significant digits
+ *     <th align=left>Number
+ *     <th align=left>Output of format()
+ *   <tr valign=top>
+ *     <td><code>@@@</code>
+ *     <td>3
+ *     <td>3
+ *     <td>12345
+ *     <td><code>12300</code>
+ *   <tr valign=top bgcolor="#eeeeff">
+ *     <td><code>@@@</code>
+ *     <td>3
+ *     <td>3
+ *     <td>0.12345
+ *     <td><code>0.123</code>
+ *   <tr valign=top>
+ *     <td><code>@@##</code>
+ *     <td>2
+ *     <td>4
+ *     <td>3.14159
+ *     <td><code>3.142</code>
+ *   <tr valign=top bgcolor="#eeeeff">
+ *     <td><code>@@##</code>
+ *     <td>2
+ *     <td>4
+ *     <td>1.23004
+ *     <td><code>1.23</code>
+ * </table>
+ * </blockquote>
+ *
+ * <ul>
+ *
+ * <li>Significant digit counts may be expressed using patterns that specify a minimum and
+ * maximum number of significant digits.  These are indicated by the <code>'@'</code> and
+ * <code>'#'</code> characters.  The minimum number of significant digits is the number of
+ * <code>'@'</code> characters.  The maximum number of significant digits is the number of
+ * <code>'@'</code> characters plus the number of <code>'#'</code> characters following on
+ * the right.  For example, the pattern <code>"@@@"</code> indicates exactly 3 significant
+ * digits.  The pattern <code>"@##"</code> indicates from 1 to 3 significant digits.
+ * Trailing zero digits to the right of the decimal separator are suppressed after the
+ * minimum number of significant digits have been shown.  For example, the pattern
+ * <code>"@##"</code> formats the number 0.1203 as <code>"0.12"</code>.
+ *
+ * <li>If a pattern uses significant digits, it may not contain a decimal separator, nor
+ * the <code>'0'</code> pattern character.  Patterns such as <code>"@00"</code> or
+ * <code>"@.###"</code> are disallowed.
+ *
+ * <li>Any number of <code>'#'</code> characters may be prepended to the left of the
+ * leftmost <code>'@'</code> character.  These have no effect on the minimum and maximum
+ * significant digits counts, but may be used to position grouping separators.  For
+ * example, <code>"#,#@#"</code> indicates a minimum of one significant digits, a maximum
+ * of two significant digits, and a grouping size of three.
+ *
+ * <li>In order to enable significant digits formatting, use a pattern containing the
+ * <code>'@'</code> pattern character.  Alternatively, call {@link
+ * #setSignificantDigitsUsed setSignificantDigitsUsed(true)}.
+ *
+ * <li>In order to disable significant digits formatting, use a pattern that does not
+ * contain the <code>'@'</code> pattern character. Alternatively, call {@link
+ * #setSignificantDigitsUsed setSignificantDigitsUsed(false)}.
+ *
+ * <li>The number of significant digits has no effect on parsing.
+ *
+ * <li>Significant digits may be used together with exponential notation. Such patterns
+ * are equivalent to a normal exponential pattern with a minimum and maximum integer digit
+ * count of one, a minimum fraction digit count of <code>getMinimumSignificantDigits() -
+ * 1</code>, and a maximum fraction digit count of <code>getMaximumSignificantDigits() -
+ * 1</code>. For example, the pattern <code>"@@###E0"</code> is equivalent to
+ * <code>"0.0###E0"</code>.
+ *
+ * <li>If signficant digits are in use, then the integer and fraction digit counts, as set
+ * via the API, are ignored.  If significant digits are not in use, then the signficant
+ * digit counts, as set via the API, are ignored.
+ *
+ * </ul>
+ *
+ * <h4>Padding</h4>
+ *
+ * <p><code>DecimalFormat</code> supports padding the result of {@link #format} to a
+ * specific width.  Padding may be specified either through the API or through the pattern
+ * syntax.  In a pattern the pad escape character, followed by a single pad character,
+ * causes padding to be parsed and formatted.  The pad escape character is '*' in
+ * unlocalized patterns, and can be localized using {@link
+ * DecimalFormatSymbols#setPadEscape}.  For example, <code>"$*x#,##0.00"</code> formats
+ * 123 to <code>"$xx123.00"</code>, and 1234 to <code>"$1,234.00"</code>.
+ *
+ * <ul>
+ *
+ * <li>When padding is in effect, the width of the positive subpattern, including prefix
+ * and suffix, determines the format width.  For example, in the pattern <code>"* #0
+ * o''clock"</code>, the format width is 10.
+ *
+ * <li>The width is counted in 16-bit code units (Java <code>char</code>s).
+ *
+ * <li>Some parameters which usually do not matter have meaning when padding is used,
+ * because the pattern width is significant with padding.  In the pattern "*
+ * ##,##,#,##0.##", the format width is 14.  The initial characters "##,##," do not affect
+ * the grouping size or maximum integer digits, but they do affect the format width.
+ *
+ * <li>Padding may be inserted at one of four locations: before the prefix, after the
+ * prefix, before the suffix, or after the suffix.  If padding is specified in any other
+ * location, {@link #applyPattern} throws an {@link IllegalArgumentException}.  If there
+ * is no prefix, before the prefix and after the prefix are equivalent, likewise for the
+ * suffix.
+ *
+ * <li>When specified in a pattern, the 16-bit <code>char</code> immediately following the
+ * pad escape is the pad character. This may be any character, including a special pattern
+ * character. That is, the pad escape <em>escapes</em> the following character. If there
+ * is no character after the pad escape, then the pattern is illegal.
+ *
+ * </ul>
+ *
+ * <p>
+ * <strong>Rounding</strong>
+ *
+ * <p><code>DecimalFormat</code> supports rounding to a specific increment.  For example,
+ * 1230 rounded to the nearest 50 is 1250.  1.234 rounded to the nearest 0.65 is 1.3.  The
+ * rounding increment may be specified through the API or in a pattern.  To specify a
+ * rounding increment in a pattern, include the increment in the pattern itself.  "#,#50"
+ * specifies a rounding increment of 50.  "#,##0.05" specifies a rounding increment of
+ * 0.05.
+ *
+ * <ul>
+ *
+ * <li>Rounding only affects the string produced by formatting.  It does not affect
+ * parsing or change any numerical values.
+ *
+ * <li>A <em>rounding mode</em> determines how values are rounded; see the {@link
+ * com.ibm.icu.math.BigDecimal} documentation for a description of the modes.  Rounding
+ * increments specified in patterns use the default mode, {@link
+ * com.ibm.icu.math.BigDecimal#ROUND_HALF_EVEN}.
+ *
+ * <li>Some locales use rounding in their currency formats to reflect the smallest
+ * currency denomination.
+ *
+ * <li>In a pattern, digits '1' through '9' specify rounding, but otherwise behave
+ * identically to digit '0'.
+ *
+ * </ul>
+ *
+ * <h4>Synchronization</h4>
+ *
+ * <p><code>DecimalFormat</code> objects are not synchronized.  Multiple threads should
+ * not access one formatter concurrently.
+ *
+ * @see          java.text.Format
+ * @see          NumberFormat
+ * @author       Mark Davis
+ * @author       Alan Liu
+ * @stable ICU 2.0
+ */
+public class DecimalFormat extends NumberFormat {
+
+    private static final long serialVersionUID = 1L;
+    /**
+     * @internal
+     * @param delegate the NumberFormat to which to delegate
+     */
+    public DecimalFormat(java.text.DecimalFormat delegate) {
+        super(delegate);
+    }
+
+    /**
+     * Creates a DecimalFormat using the default pattern and symbols for the default
+     * locale. This is a convenient way to obtain a DecimalFormat when
+     * internationalization is not the main concern.
+     *
+     * <p>To obtain standard formats for a given locale, use the factory methods on
+     * NumberFormat such as getNumberInstance.  These factories will return the most
+     * appropriate sub-class of NumberFormat for a given locale.
+     *
+     * @see NumberFormat#getInstance
+     * @see NumberFormat#getNumberInstance
+     * @see NumberFormat#getCurrencyInstance
+     * @see NumberFormat#getPercentInstance
+     * @stable ICU 2.0
+     */
+    public DecimalFormat() {
+        this(new java.text.DecimalFormat());
+    }
+
+    /**
+     * Creates a DecimalFormat from the given pattern and the symbols for the default
+     * locale. This is a convenient way to obtain a DecimalFormat when
+     * internationalization is not the main concern.
+     *
+     * <p>To obtain standard formats for a given locale, use the factory methods on
+     * NumberFormat such as getNumberInstance.  These factories will return the most
+     * appropriate sub-class of NumberFormat for a given locale.
+     *
+     * @param pattern A non-localized pattern string.
+     * @throws IllegalArgumentException if the given pattern is invalid.
+     * @see NumberFormat#getInstance
+     * @see NumberFormat#getNumberInstance
+     * @see NumberFormat#getCurrencyInstance
+     * @see NumberFormat#getPercentInstance
+     * @stable ICU 2.0
+     */
+    public DecimalFormat(String pattern) {
+        this(new java.text.DecimalFormat(pattern));
+    }
+
+    /**
+     * Creates a DecimalFormat from the given pattern and symbols. Use this constructor
+     * when you need to completely customize the behavior of the format.
+     *
+     * <p>To obtain standard formats for a given locale, use the factory methods on
+     * NumberFormat such as getInstance or getCurrencyInstance. If you need only minor
+     * adjustments to a standard format, you can modify the format returned by a
+     * NumberFormat factory method.
+     *
+     * @param pattern a non-localized pattern string
+     * @param symbols the set of symbols to be used
+     * @exception IllegalArgumentException if the given pattern is invalid
+     * @see NumberFormat#getInstance
+     * @see NumberFormat#getNumberInstance
+     * @see NumberFormat#getCurrencyInstance
+     * @see NumberFormat#getPercentInstance
+     * @see DecimalFormatSymbols
+     * @stable ICU 2.0
+     */
+    public DecimalFormat(String pattern, DecimalFormatSymbols symbols) {
+        this(new java.text.DecimalFormat(pattern, symbols.dfs));
+    }
+
+    /**
+     * Creates a DecimalFormat from the given pattern, symbols, information used for
+     * currency plural format, and format style. Use this constructor when you need to
+     * completely customize the behavior of the format.
+     *
+     * <p>To obtain standard formats for a given locale, use the factory methods on
+     * NumberFormat such as getInstance or getCurrencyInstance.
+     *
+     * <p>If you need only minor adjustments to a standard format, you can modify the
+     * format returned by a NumberFormat factory method using the setters.
+     *
+     * <p>If you want to completely customize a decimal format, using your own
+     * DecimalFormatSymbols (such as group separators) and your own information for
+     * currency plural formatting (such as plural rule and currency plural patterns), you
+     * can use this constructor.
+     *
+     * @param pattern a non-localized pattern string
+     * @param symbols the set of symbols to be used
+     * @param infoInput the information used for currency plural format, including
+     * currency plural patterns and plural rules.
+     * @param style the decimal formatting style, it is one of the following values:
+     * NumberFormat.NUMBERSTYLE; NumberFormat.CURRENCYSTYLE; NumberFormat.PERCENTSTYLE;
+     * NumberFormat.SCIENTIFICSTYLE; NumberFormat.INTEGERSTYLE;
+     * NumberFormat.ISOCURRENCYSTYLE; NumberFormat.PLURALCURRENCYSTYLE;
+     * @stable ICU 4.2
+     */
+    public DecimalFormat(String pattern, DecimalFormatSymbols symbols, CurrencyPluralInfo infoInput,
+                         int style) {
+        throw new UnsupportedOperationException("Constructor not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@inheritDoc}
+     * @stable ICU 2.0
+     */
+    public StringBuffer format(double number, StringBuffer result, FieldPosition fieldPosition) {
+        return super.format(number, result, fieldPosition);
+    }
+
+    /**
+     * @stable ICU 2.0
+     */
+    // [Spark/CDL] Delegate to format_long_StringBuffer_FieldPosition_boolean
+    public StringBuffer format(long number, StringBuffer result, FieldPosition fieldPosition) {
+        return super.format(number, result, fieldPosition);
+    }
+
+    /**
+     * Formats a BigInteger number.
+     *
+     * @stable ICU 2.0
+     */
+    public StringBuffer format(BigInteger number, StringBuffer result,
+                               FieldPosition fieldPosition) {
+        return super.format(number, result, fieldPosition);
+    }
+
+    /**
+     * Formats a BigDecimal number.
+     *
+     * @stable ICU 2.0
+     */
+    public StringBuffer format(java.math.BigDecimal number, StringBuffer result,
+                               FieldPosition fieldPosition) {
+        return super.format(number, result, fieldPosition);
+    }
+
+    /**
+     * Formats a BigDecimal number.
+     *
+     * @stable ICU 2.0
+     */
+    public StringBuffer format(BigDecimal number, StringBuffer result,
+                               FieldPosition fieldPosition) {
+        return super.format(number, result, fieldPosition);
+    }
+
+    /**
+     * Parses the given string, returning a <code>Number</code> object to represent the
+     * parsed value. <code>Double</code> objects are returned to represent non-integral
+     * values which cannot be stored in a <code>BigDecimal</code>. These are
+     * <code>NaN</code>, infinity, -infinity, and -0.0. If {@link #isParseBigDecimal()} is
+     * false (the default), all other values are returned as <code>Long</code>,
+     * <code>BigInteger</code>, or <code>BigDecimal</code> values, in that order of
+     * preference. If {@link #isParseBigDecimal()} is true, all other values are returned
+     * as <code>BigDecimal</code> valuse. If the parse fails, null is returned.
+     *
+     * @param text the string to be parsed
+     * @param parsePosition defines the position where parsing is to begin, and upon
+     * return, the position where parsing left off. If the position has not changed upon
+     * return, then parsing failed.
+     * @return a <code>Number</code> object with the parsed value or
+     * <code>null</code> if the parse failed
+     * @stable ICU 2.0
+     */
+    public Number parse(String text, ParsePosition parsePosition) {
+        return super.parse(text, parsePosition);
+    }
+
+    /**
+     * Parses text from the given string as a CurrencyAmount. Unlike the parse() method,
+     * this method will attempt to parse a generic currency name, searching for a match of
+     * this object's locale's currency display names, or for a 3-letter ISO currency
+     * code. This method will fail if this format is not a currency format, that is, if it
+     * does not contain the currency pattern symbol (U+00A4) in its prefix or suffix.
+     *
+     * @param text the string to parse
+     * @param pos input-output position; on input, the position within text to match; must
+     *  have 0 <= pos.getIndex() < text.length(); on output, the position after the last
+     *  matched character. If the parse fails, the position in unchanged upon output.
+     * @return a CurrencyAmount, or null upon failure
+     */
+    CurrencyAmount parseCurrency(String text, ParsePosition pos) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Returns a copy of the decimal format symbols used by this format.
+     *
+     * @return desired DecimalFormatSymbols
+     * @see DecimalFormatSymbols
+     * @stable ICU 2.0
+     */
+    public DecimalFormatSymbols getDecimalFormatSymbols() {
+        return new DecimalFormatSymbols(((java.text.DecimalFormat)numberFormat).getDecimalFormatSymbols());
+    }
+
+    /**
+     * Sets the decimal format symbols used by this format. The format uses a copy of the
+     * provided symbols.
+     *
+     * @param newSymbols desired DecimalFormatSymbols
+     * @see DecimalFormatSymbols
+     * @stable ICU 2.0
+     */
+    public void setDecimalFormatSymbols(DecimalFormatSymbols newSymbols) {
+        ((java.text.DecimalFormat)numberFormat).setDecimalFormatSymbols(newSymbols.dfs);
+    }
+
+    /**
+     * Returns the positive prefix.
+     *
+     * <p>Examples: +123, $123, sFr123
+     * @return the prefix
+     * @stable ICU 2.0
+     */
+    public String getPositivePrefix() {
+        return ((java.text.DecimalFormat)numberFormat).getPositivePrefix();
+    }
+
+    /**
+     * Sets the positive prefix.
+     *
+     * <p>Examples: +123, $123, sFr123
+     * @param newValue the prefix
+     * @stable ICU 2.0
+     */
+    public void setPositivePrefix(String newValue) {
+        ((java.text.DecimalFormat)numberFormat).setPositivePrefix(newValue);
+    }
+
+    /**
+     * Returns the negative prefix.
+     *
+     * <p>Examples: -123, ($123) (with negative suffix), sFr-123
+     *
+     * @return the prefix
+     * @stable ICU 2.0
+     */
+    public String getNegativePrefix() {
+        return ((java.text.DecimalFormat)numberFormat).getNegativePrefix();
+    }
+
+    /**
+     * Sets the negative prefix.
+     *
+     * <p>Examples: -123, ($123) (with negative suffix), sFr-123
+     * @param newValue the prefix
+     * @stable ICU 2.0
+     */
+    public void setNegativePrefix(String newValue) {
+        ((java.text.DecimalFormat)numberFormat).setNegativePrefix(newValue);
+    }
+
+    /**
+     * Returns the positive suffix.
+     *
+     * <p>Example: 123%
+     *
+     * @return the suffix
+     * @stable ICU 2.0
+     */
+    public String getPositiveSuffix() {
+        return ((java.text.DecimalFormat)numberFormat).getPositiveSuffix();
+    }
+
+    /**
+     * Sets the positive suffix.
+     *
+     * <p>Example: 123%
+     * @param newValue the suffix
+     * @stable ICU 2.0
+     */
+    public void setPositiveSuffix(String newValue) {
+        ((java.text.DecimalFormat)numberFormat).setPositiveSuffix(newValue);
+    }
+
+    /**
+     * Returns the negative suffix.
+     *
+     * <p>Examples: -123%, ($123) (with positive suffixes)
+     *
+     * @return the suffix
+     * @stable ICU 2.0
+     */
+    public String getNegativeSuffix() {
+        return ((java.text.DecimalFormat)numberFormat).getNegativeSuffix();
+    }
+
+    /**
+     * Sets the positive suffix.
+     *
+     * <p>Examples: 123%
+     * @param newValue the suffix
+     * @stable ICU 2.0
+     */
+    public void setNegativeSuffix(String newValue) {
+        ((java.text.DecimalFormat)numberFormat).setNegativeSuffix(newValue);
+    }
+
+    /**
+     * Returns the multiplier for use in percent, permill, etc. For a percentage, set the
+     * suffixes to have "%" and the multiplier to be 100. (For Arabic, use arabic percent
+     * symbol). For a permill, set the suffixes to have "\u2031" and the multiplier to be
+     * 1000.
+     *
+     * <p>Examples: with 100, 1.23 -> "123", and "123" -> 1.23
+     *
+     * @return the multiplier
+     * @stable ICU 2.0
+     */
+    public int getMultiplier() {
+        return ((java.text.DecimalFormat)numberFormat).getMultiplier();
+    }
+
+    /**
+     * Sets the multiplier for use in percent, permill, etc. For a percentage, set the
+     * suffixes to have "%" and the multiplier to be 100. (For Arabic, use arabic percent
+     * symbol). For a permill, set the suffixes to have "\u2031" and the multiplier to be
+     * 1000.
+     *
+     * <p>Examples: with 100, 1.23 -> "123", and "123" -> 1.23
+     *
+     * @param newValue the multiplier
+     * @stable ICU 2.0
+     */
+    public void setMultiplier(int newValue) {
+        ((java.text.DecimalFormat)numberFormat).setMultiplier(newValue);
+    }
+
+    /**
+     * {@icu} Returns the rounding increment.
+     *
+     * @return A positive rounding increment, or <code>null</code> if rounding is not in
+     * effect.
+     * @see #setRoundingIncrement
+     * @see #getRoundingMode
+     * @see #setRoundingMode
+     * @stable ICU 2.0
+     */
+    public BigDecimal getRoundingIncrement() {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Sets the rounding increment. This method also controls whether rounding is
+     * enabled.
+     *
+     * @param newValue A positive rounding increment, or <code>null</code> or
+     * <code>BigDecimal(0.0)</code> to disable rounding.
+     * @throws IllegalArgumentException if <code>newValue</code> is < 0.0
+     * @see #getRoundingIncrement
+     * @see #getRoundingMode
+     * @see #setRoundingMode
+     * @stable ICU 2.0
+     */
+    public void setRoundingIncrement(java.math.BigDecimal newValue) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Sets the rounding increment. This method also controls whether rounding is
+     * enabled.
+     *
+     * @param newValue A positive rounding increment, or <code>null</code> or
+     * <code>BigDecimal(0.0)</code> to disable rounding.
+     * @throws IllegalArgumentException if <code>newValue</code> is < 0.0
+     * @see #getRoundingIncrement
+     * @see #getRoundingMode
+     * @see #setRoundingMode
+     * @stable ICU 3.6
+     */
+    public void setRoundingIncrement(BigDecimal newValue) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Sets the rounding increment. This method also controls whether rounding is
+     * enabled.
+     *
+     * @param newValue A positive rounding increment, or 0.0 to disable rounding.
+     * @throws IllegalArgumentException if <code>newValue</code> is < 0.0
+     * @see #getRoundingIncrement
+     * @see #getRoundingMode
+     * @see #setRoundingMode
+     * @stable ICU 2.0
+     */
+    public void setRoundingIncrement(double newValue) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Returns the rounding mode.
+     *
+     * @return A rounding mode, between <code>BigDecimal.ROUND_UP</code> and
+     * <code>BigDecimal.ROUND_UNNECESSARY</code>.
+     * @see #setRoundingIncrement
+     * @see #getRoundingIncrement
+     * @see #setRoundingMode
+     * @see java.math.BigDecimal
+     * @stable ICU 2.0
+     */
+    public int getRoundingMode() {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Sets the rounding mode. This has no effect unless the rounding increment is greater
+     * than zero.
+     *
+     * @param roundingMode A rounding mode, between <code>BigDecimal.ROUND_UP</code> and
+     * <code>BigDecimal.ROUND_UNNECESSARY</code>.
+     * @exception IllegalArgumentException if <code>roundingMode</code> is unrecognized.
+     * @see #setRoundingIncrement
+     * @see #getRoundingIncrement
+     * @see #getRoundingMode
+     * @see java.math.BigDecimal
+     * @stable ICU 2.0
+     */
+    public void setRoundingMode(int roundingMode) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Returns the width to which the output of <code>format()</code> is padded. The width is
+     * counted in 16-bit code units.
+     *
+     * @return the format width, or zero if no padding is in effect
+     * @see #setFormatWidth
+     * @see #getPadCharacter
+     * @see #setPadCharacter
+     * @see #getPadPosition
+     * @see #setPadPosition
+     * @stable ICU 2.0
+     */
+    public int getFormatWidth() {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Sets the width to which the output of <code>format()</code> is
+     * padded. The width is counted in 16-bit code units.  This method
+     * also controls whether padding is enabled.
+     *
+     * @param width the width to which to pad the result of
+     * <code>format()</code>, or zero to disable padding
+     * @exception IllegalArgumentException if <code>width</code> is < 0
+     * @see #getFormatWidth
+     * @see #getPadCharacter
+     * @see #setPadCharacter
+     * @see #getPadPosition
+     * @see #setPadPosition
+     * @stable ICU 2.0
+     */
+    public void setFormatWidth(int width) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Returns the character used to pad to the format width. The default is ' '.
+     *
+     * @return the pad character
+     * @see #setFormatWidth
+     * @see #getFormatWidth
+     * @see #setPadCharacter
+     * @see #getPadPosition
+     * @see #setPadPosition
+     * @stable ICU 2.0
+     */
+    public char getPadCharacter() {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Sets the character used to pad to the format width. If padding is not
+     * enabled, then this will take effect if padding is later enabled.
+     *
+     * @param padChar the pad character
+     * @see #setFormatWidth
+     * @see #getFormatWidth
+     * @see #getPadCharacter
+     * @see #getPadPosition
+     * @see #setPadPosition
+     * @stable ICU 2.0
+     */
+    public void setPadCharacter(char padChar) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Returns the position at which padding will take place. This is the location at
+     * which padding will be inserted if the result of <code>format()</code> is shorter
+     * than the format width.
+     *
+     * @return the pad position, one of <code>PAD_BEFORE_PREFIX</code>,
+     *         <code>PAD_AFTER_PREFIX</code>, <code>PAD_BEFORE_SUFFIX</code>, or
+     *         <code>PAD_AFTER_SUFFIX</code>.
+     * @see #setFormatWidth
+     * @see #getFormatWidth
+     * @see #setPadCharacter
+     * @see #getPadCharacter
+     * @see #setPadPosition
+     * @see #PAD_BEFORE_PREFIX
+     * @see #PAD_AFTER_PREFIX
+     * @see #PAD_BEFORE_SUFFIX
+     * @see #PAD_AFTER_SUFFIX
+     * @stable ICU 2.0
+     */
+    public int getPadPosition() {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Sets the position at which padding will take place. This is the location at
+     * which padding will be inserted if the result of <code>format()</code> is shorter
+     * than the format width. This has no effect unless padding is enabled.
+     *
+     * @param padPos the pad position, one of <code>PAD_BEFORE_PREFIX</code>,
+     * <code>PAD_AFTER_PREFIX</code>, <code>PAD_BEFORE_SUFFIX</code>, or
+     * <code>PAD_AFTER_SUFFIX</code>.
+     * @exception IllegalArgumentException if the pad position in unrecognized
+     * @see #setFormatWidth
+     * @see #getFormatWidth
+     * @see #setPadCharacter
+     * @see #getPadCharacter
+     * @see #getPadPosition
+     * @see #PAD_BEFORE_PREFIX
+     * @see #PAD_AFTER_PREFIX
+     * @see #PAD_BEFORE_SUFFIX
+     * @see #PAD_AFTER_SUFFIX
+     * @stable ICU 2.0
+     */
+    public void setPadPosition(int padPos) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Returns whether or not scientific notation is used.
+     *
+     * @return true if this object formats and parses scientific notation
+     * @see #setScientificNotation
+     * @see #getMinimumExponentDigits
+     * @see #setMinimumExponentDigits
+     * @see #isExponentSignAlwaysShown
+     * @see #setExponentSignAlwaysShown
+     * @stable ICU 2.0
+     */
+    public boolean isScientificNotation() {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Sets whether or not scientific notation is used. When scientific notation is
+     * used, the effective maximum number of integer digits is <= 8. If the maximum number
+     * of integer digits is set to more than 8, the effective maximum will be 1. This
+     * allows this call to generate a 'default' scientific number format without
+     * additional changes.
+     *
+     * @param useScientific true if this object formats and parses scientific notation
+     * @see #isScientificNotation
+     * @see #getMinimumExponentDigits
+     * @see #setMinimumExponentDigits
+     * @see #isExponentSignAlwaysShown
+     * @see #setExponentSignAlwaysShown
+     * @stable ICU 2.0
+     */
+    public void setScientificNotation(boolean useScientific) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Returns the minimum exponent digits that will be shown.
+     *
+     * @return the minimum exponent digits that will be shown
+     * @see #setScientificNotation
+     * @see #isScientificNotation
+     * @see #setMinimumExponentDigits
+     * @see #isExponentSignAlwaysShown
+     * @see #setExponentSignAlwaysShown
+     * @stable ICU 2.0
+     */
+    public byte getMinimumExponentDigits() {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Sets the minimum exponent digits that will be shown. This has no effect
+     * unless scientific notation is in use.
+     *
+     * @param minExpDig a value >= 1 indicating the fewest exponent
+     * digits that will be shown
+     * @exception IllegalArgumentException if <code>minExpDig</code> < 1
+     * @see #setScientificNotation
+     * @see #isScientificNotation
+     * @see #getMinimumExponentDigits
+     * @see #isExponentSignAlwaysShown
+     * @see #setExponentSignAlwaysShown
+     * @stable ICU 2.0
+     */
+    public void setMinimumExponentDigits(byte minExpDig) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Returns whether the exponent sign is always shown.
+     *
+     * @return true if the exponent is always prefixed with either the localized minus
+     * sign or the localized plus sign, false if only negative exponents are prefixed with
+     * the localized minus sign.
+     * @see #setScientificNotation
+     * @see #isScientificNotation
+     * @see #setMinimumExponentDigits
+     * @see #getMinimumExponentDigits
+     * @see #setExponentSignAlwaysShown
+     * @stable ICU 2.0
+     */
+    public boolean isExponentSignAlwaysShown() {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Sets whether the exponent sign is always shown. This has no effect unless
+     * scientific notation is in use.
+     *
+     * @param expSignAlways true if the exponent is always prefixed with either the
+     * localized minus sign or the localized plus sign, false if only negative exponents
+     * are prefixed with the localized minus sign.
+     * @see #setScientificNotation
+     * @see #isScientificNotation
+     * @see #setMinimumExponentDigits
+     * @see #getMinimumExponentDigits
+     * @see #isExponentSignAlwaysShown
+     * @stable ICU 2.0
+     */
+    public void setExponentSignAlwaysShown(boolean expSignAlways) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Returns the grouping size. Grouping size is the number of digits between grouping
+     * separators in the integer portion of a number. For example, in the number
+     * "123,456.78", the grouping size is 3.
+     *
+     * @see #setGroupingSize
+     * @see NumberFormat#isGroupingUsed
+     * @see DecimalFormatSymbols#getGroupingSeparator
+     * @stable ICU 2.0
+     */
+    public int getGroupingSize() {
+        return ((java.text.DecimalFormat)numberFormat).getGroupingSize();
+    }
+
+    /**
+     * Sets the grouping size. Grouping size is the number of digits between grouping
+     * separators in the integer portion of a number. For example, in the number
+     * "123,456.78", the grouping size is 3.
+     *
+     * @see #getGroupingSize
+     * @see NumberFormat#setGroupingUsed
+     * @see DecimalFormatSymbols#setGroupingSeparator
+     * @stable ICU 2.0
+     */
+    public void setGroupingSize(int newValue) {
+        ((java.text.DecimalFormat)numberFormat).setGroupingSize(newValue);
+    }
+
+    /**
+     * {@icu} Returns the secondary grouping size. In some locales one grouping interval
+     * is used for the least significant integer digits (the primary grouping size), and
+     * another is used for all others (the secondary grouping size). A formatter
+     * supporting a secondary grouping size will return a positive integer unequal to the
+     * primary grouping size returned by <code>getGroupingSize()</code>. For example, if
+     * the primary grouping size is 4, and the secondary grouping size is 2, then the
+     * number 123456789 formats as "1,23,45,6789", and the pattern appears as "#,##,###0".
+     *
+     * @return the secondary grouping size, or a value less than one if there is none
+     * @see #setSecondaryGroupingSize
+     * @see NumberFormat#isGroupingUsed
+     * @see DecimalFormatSymbols#getGroupingSeparator
+     * @stable ICU 2.0
+     */
+    public int getSecondaryGroupingSize() {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Sets the secondary grouping size. If set to a value less than 1, then
+     * secondary grouping is turned off, and the primary grouping size is used for all
+     * intervals, not just the least significant.
+     *
+     * @see #getSecondaryGroupingSize
+     * @see NumberFormat#setGroupingUsed
+     * @see DecimalFormatSymbols#setGroupingSeparator
+     * @stable ICU 2.0
+     */
+    public void setSecondaryGroupingSize(int newValue) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Returns the MathContext used by this format.
+     *
+     * @return desired MathContext
+     * @see #getMathContext
+     * @stable ICU 4.2
+     */
+    public MathContext getMathContextICU() {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Returns the MathContext used by this format.
+     *
+     * @return desired MathContext
+     * @see #getMathContext
+     * @stable ICU 4.2
+     */
+    public java.math.MathContext getMathContext() {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Sets the MathContext used by this format.
+     *
+     * @param newValue desired MathContext
+     * @see #getMathContext
+     * @stable ICU 4.2
+     */
+    public void setMathContextICU(MathContext newValue) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Sets the MathContext used by this format.
+     *
+     * @param newValue desired MathContext
+     * @see #getMathContext
+     * @stable ICU 4.2
+     */
+    public void setMathContext(java.math.MathContext newValue) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Returns the behavior of the decimal separator with integers. (The decimal
+     * separator will always appear with decimals.)  <p> Example: Decimal ON: 12345 ->
+     * 12345.; OFF: 12345 -> 12345
+     *
+     * @stable ICU 2.0
+     */
+    public boolean isDecimalSeparatorAlwaysShown() {
+        return ((java.text.DecimalFormat)numberFormat).isDecimalSeparatorAlwaysShown();
+    }
+
+    /**
+     * Sets the behavior of the decimal separator with integers. (The decimal separator
+     * will always appear with decimals.)
+     *
+     * <p>This only affects formatting, and only where there might be no digits after the
+     * decimal point, e.g., if true, 3456.00 -> "3,456." if false, 3456.00 -> "3456" This
+     * is independent of parsing. If you want parsing to stop at the decimal point, use
+     * setParseIntegerOnly.
+     *
+     * <p>
+     * Example: Decimal ON: 12345 -> 12345.; OFF: 12345 -> 12345
+     *
+     * @stable ICU 2.0
+     */
+    public void setDecimalSeparatorAlwaysShown(boolean newValue) {
+        ((java.text.DecimalFormat)numberFormat).setDecimalSeparatorAlwaysShown(newValue);
+    }
+
+    /**
+     * {@icu} Returns a copy of the CurrencyPluralInfo used by this format. It might
+     * return null if the decimal format is not a plural type currency decimal
+     * format. Plural type currency decimal format means either the pattern in the decimal
+     * format contains 3 currency signs, or the decimal format is initialized with
+     * PLURALCURRENCYSTYLE.
+     *
+     * @return desired CurrencyPluralInfo
+     * @see CurrencyPluralInfo
+     * @stable ICU 4.2
+     */
+    public CurrencyPluralInfo getCurrencyPluralInfo() {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Sets the CurrencyPluralInfo used by this format. The format uses a copy of
+     * the provided information.
+     *
+     * @param newInfo desired CurrencyPluralInfo
+     * @see CurrencyPluralInfo
+     * @stable ICU 4.2
+     */
+    public void setCurrencyPluralInfo(CurrencyPluralInfo newInfo) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Overrides clone.
+     * @stable ICU 2.0
+     */
+    public Object clone() {
+        return new DecimalFormatSymbols((java.text.DecimalFormatSymbols)numberFormat.clone());
+    }
+
+    /**
+     * Overrides equals.
+     * @stable ICU 2.0
+     */
+    public boolean equals(Object obj) {
+        return super.equals(obj);
+    }
+
+    /**
+     * Overrides hashCode.
+     * @stable ICU 2.0
+     */
+    public int hashCode() {
+        return super.hashCode();
+    }
+
+    /**
+     * Synthesizes a pattern string that represents the current state of this Format
+     * object.
+     *
+     * @see #applyPattern
+     * @stable ICU 2.0
+     */
+    public String toPattern() {
+        return ((java.text.DecimalFormat)numberFormat).toPattern();
+    }
+
+    /**
+     * Synthesizes a localized pattern string that represents the current state of this
+     * Format object.
+     *
+     * @see #applyPattern
+     * @stable ICU 2.0
+     */
+    public String toLocalizedPattern() {
+        return ((java.text.DecimalFormat)numberFormat).toLocalizedPattern();
+    }
+
+    /**
+     * Formats the object to an attributed string, and return the corresponding iterator.
+     *
+     * @stable ICU 3.6
+     */
+    public AttributedCharacterIterator formatToCharacterIterator(Object obj) {
+        AttributedCharacterIterator it = numberFormat.formatToCharacterIterator(obj);
+
+        // Extract formatted String first
+        StringBuilder sb = new StringBuilder();
+        for (char c = it.first(); c != CharacterIterator.DONE; c = it.next()) {
+            sb.append(c);
+        }
+
+        // Create AttributedString
+        AttributedString attrstr = new AttributedString(sb.toString());
+
+        // Map JDK Field to ICU Field
+        int idx = 0;
+        it.first();
+        while (idx < it.getEndIndex()) {
+            int end = it.getRunLimit();
+            Map<Attribute, Object> attributes = it.getAttributes();
+            if (attributes != null) {
+                for (Entry<Attribute, Object> entry : attributes.entrySet()) {
+                    Attribute attr = entry.getKey();
+                    Object val = entry.getValue();
+                    if (attr.equals(java.text.NumberFormat.Field.CURRENCY)) {
+                        val = attr = Field.CURRENCY;
+                    } else if (attr.equals(java.text.NumberFormat.Field.DECIMAL_SEPARATOR)) {
+                        val = attr = Field.DECIMAL_SEPARATOR;
+                    } else if (attr.equals(java.text.NumberFormat.Field.EXPONENT)) {
+                        val = attr = Field.EXPONENT;
+                    } else if (attr.equals(java.text.NumberFormat.Field.EXPONENT_SIGN)) {
+                        val = attr = Field.EXPONENT_SIGN;
+                    } else if (attr.equals(java.text.NumberFormat.Field.EXPONENT_SYMBOL)) {
+                        val = attr = Field.EXPONENT_SYMBOL;
+                    } else if (attr.equals(java.text.NumberFormat.Field.FRACTION)) {
+                        val = attr = Field.FRACTION;
+                    } else if (attr.equals(java.text.NumberFormat.Field.GROUPING_SEPARATOR)) {
+                        val = attr = Field.GROUPING_SEPARATOR;
+                    } else if (attr.equals(java.text.NumberFormat.Field.INTEGER)) {
+                        val = attr = Field.INTEGER;
+                    } else if (attr.equals(java.text.NumberFormat.Field.PERCENT)) {
+                        val = attr = Field.PERCENT;
+                    } else if (attr.equals(java.text.NumberFormat.Field.PERMILLE)) {
+                        val = attr = Field.PERMILLE;
+                    } else if (attr.equals(java.text.NumberFormat.Field.SIGN)) {
+                        val = attr = Field.SIGN;
+                    }
+                    attrstr.addAttribute(attr, val, idx, end);
+                }
+            }
+            idx = end;
+            while (it.getIndex() < idx) {
+                it.next();
+            }
+        }
+
+        return attrstr.getIterator();
+    }
+
+    /**
+     * Applies the given pattern to this Format object. A pattern is a short-hand
+     * specification for the various formatting properties. These properties can also be
+     * changed individually through the various setter methods.
+     *
+     * <p>There is no limit to integer digits are set by this routine, since that is the
+     * typical end-user desire; use setMaximumInteger if you want to set a real value. For
+     * negative numbers, use a second pattern, separated by a semicolon
+     *
+     * <p>Example "#,#00.0#" -> 1,234.56
+     *
+     * <p>This means a minimum of 2 integer digits, 1 fraction digit, and a maximum of 2
+     * fraction digits.
+     *
+     * <p>Example: "#,#00.0#;(#,#00.0#)" for negatives in parentheses.
+     *
+     * <p>In negative patterns, the minimum and maximum counts are ignored; these are
+     * presumed to be set in the positive pattern.
+     *
+     * @stable ICU 2.0
+     */
+    public void applyPattern(String pattern) {
+        ((java.text.DecimalFormat)numberFormat).applyPattern(pattern);
+    }
+
+    /**
+     * Applies the given pattern to this Format object. The pattern is assumed to be in a
+     * localized notation. A pattern is a short-hand specification for the various
+     * formatting properties. These properties can also be changed individually through
+     * the various setter methods.
+     *
+     * <p>There is no limit to integer digits are set by this routine, since that is the
+     * typical end-user desire; use setMaximumInteger if you want to set a real value. For
+     * negative numbers, use a second pattern, separated by a semicolon
+     *
+     * <p>Example "#,#00.0#" -> 1,234.56
+     *
+     * <p>This means a minimum of 2 integer digits, 1 fraction digit, and a maximum of 2
+     * fraction digits.
+     *
+     * <p>Example: "#,#00.0#;(#,#00.0#)" for negatives in parantheses.
+     *
+     * <p>In negative patterns, the minimum and maximum counts are ignored; these are
+     * presumed to be set in the positive pattern.
+     *
+     * @stable ICU 2.0
+     */
+    public void applyLocalizedPattern(String pattern) {
+        ((java.text.DecimalFormat)numberFormat).applyLocalizedPattern(pattern);
+    }
+
+    /**
+     * Sets the maximum number of digits allowed in the integer portion of a number. This
+     * override limits the integer digit count to 309.
+     *
+     * @see NumberFormat#setMaximumIntegerDigits
+     * @stable ICU 2.0
+     */
+    public void setMaximumIntegerDigits(int newValue) {
+        super.setMaximumIntegerDigits(newValue);
+    }
+
+    /**
+     * Sets the minimum number of digits allowed in the integer portion of a number. This
+     * override limits the integer digit count to 309.
+     *
+     * @see NumberFormat#setMinimumIntegerDigits
+     * @stable ICU 2.0
+     */
+    public void setMinimumIntegerDigits(int newValue) {
+        super.setMinimumIntegerDigits(newValue);
+    }
+
+    /**
+     * {@icu} Returns the minimum number of significant digits that will be
+     * displayed. This value has no effect unless {@link #areSignificantDigitsUsed()}
+     * returns true.
+     *
+     * @return the fewest significant digits that will be shown
+     * @stable ICU 3.0
+     */
+    public int getMinimumSignificantDigits() {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Returns the maximum number of significant digits that will be
+     * displayed. This value has no effect unless {@link #areSignificantDigitsUsed()}
+     * returns true.
+     *
+     * @return the most significant digits that will be shown
+     * @stable ICU 3.0
+     */
+    public int getMaximumSignificantDigits() {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Sets the minimum number of significant digits that will be displayed. If
+     * <code>min</code> is less than one then it is set to one. If the maximum significant
+     * digits count is less than <code>min</code>, then it is set to
+     * <code>min</code>. This value has no effect unless {@link #areSignificantDigitsUsed()}
+     * returns true.
+     *
+     * @param min the fewest significant digits to be shown
+     * @stable ICU 3.0
+     */
+    public void setMinimumSignificantDigits(int min) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Sets the maximum number of significant digits that will be displayed. If
+     * <code>max</code> is less than one then it is set to one. If the minimum significant
+     * digits count is greater than <code>max</code>, then it is set to
+     * <code>max</code>. This value has no effect unless {@link #areSignificantDigitsUsed()}
+     * returns true.
+     *
+     * @param max the most significant digits to be shown
+     * @stable ICU 3.0
+     */
+    public void setMaximumSignificantDigits(int max) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Returns true if significant digits are in use or false if integer and
+     * fraction digit counts are in use.
+     *
+     * @return true if significant digits are in use
+     * @stable ICU 3.0
+     */
+    public boolean areSignificantDigitsUsed() {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Sets whether significant digits are in use, or integer and fraction digit
+     * counts are in use.
+     *
+     * @param useSignificantDigits true to use significant digits, or false to use integer
+     * and fraction digit counts
+     * @stable ICU 3.0
+     */
+    public void setSignificantDigitsUsed(boolean useSignificantDigits) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Sets the <tt>Currency</tt> object used to display currency amounts. This takes
+     * effect immediately, if this format is a currency format. If this format is not a
+     * currency format, then the currency object is used if and when this object becomes a
+     * currency format through the application of a new pattern.
+     *
+     * @param theCurrency new currency object to use. Must not be null.
+     * @stable ICU 2.2
+     */
+    public void setCurrency(Currency theCurrency) {
+        super.setCurrency(theCurrency);
+    }
+
+    /**
+     * Sets the maximum number of digits allowed in the fraction portion of a number. This
+     * override limits the fraction digit count to 340.
+     *
+     * @see NumberFormat#setMaximumFractionDigits
+     * @stable ICU 2.0
+     */
+    public void setMaximumFractionDigits(int newValue) {
+        super.setMaximumFractionDigits(newValue);
+    }
+
+    /**
+     * Sets the minimum number of digits allowed in the fraction portion of a number. This
+     * override limits the fraction digit count to 340.
+     *
+     * @see NumberFormat#setMinimumFractionDigits
+     * @stable ICU 2.0
+     */
+    public void setMinimumFractionDigits(int newValue) {
+        super.setMinimumFractionDigits(newValue);
+    }
+
+    /**
+     * Sets whether {@link #parse(String, ParsePosition)} returns BigDecimal. The
+     * default value is false.
+     *
+     * @param value true if {@link #parse(String, ParsePosition)}
+     * returns BigDecimal.
+     * @stable ICU 3.6
+     */
+    public void setParseBigDecimal(boolean value) {
+        ((java.text.DecimalFormat)numberFormat).setParseBigDecimal(value);
+    }
+
+    /**
+     * Returns whether {@link #parse(String, ParsePosition)} returns BigDecimal.
+     *
+     * @return true if {@link #parse(String, ParsePosition)} returns BigDecimal.
+     * @stable ICU 3.6
+     */
+    public boolean isParseBigDecimal() {
+        return ((java.text.DecimalFormat)numberFormat).isParseBigDecimal();
+    }
+
+    // ----------------------------------------------------------------------
+    // CONSTANTS
+    // ----------------------------------------------------------------------
+
+    /**
+     * {@icu} Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to
+     * specify pad characters inserted before the prefix.
+     *
+     * @see #setPadPosition
+     * @see #getPadPosition
+     * @see #PAD_AFTER_PREFIX
+     * @see #PAD_BEFORE_SUFFIX
+     * @see #PAD_AFTER_SUFFIX
+     * @stable ICU 2.0
+     */
+    public static final int PAD_BEFORE_PREFIX = 0;
+
+    /**
+     * {@icu} Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to
+     * specify pad characters inserted after the prefix.
+     *
+     * @see #setPadPosition
+     * @see #getPadPosition
+     * @see #PAD_BEFORE_PREFIX
+     * @see #PAD_BEFORE_SUFFIX
+     * @see #PAD_AFTER_SUFFIX
+     * @stable ICU 2.0
+     */
+    public static final int PAD_AFTER_PREFIX = 1;
+
+    /**
+     * {@icu} Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to
+     * specify pad characters inserted before the suffix.
+     *
+     * @see #setPadPosition
+     * @see #getPadPosition
+     * @see #PAD_BEFORE_PREFIX
+     * @see #PAD_AFTER_PREFIX
+     * @see #PAD_AFTER_SUFFIX
+     * @stable ICU 2.0
+     */
+    public static final int PAD_BEFORE_SUFFIX = 2;
+
+    /**
+     * {@icu} Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to
+     * specify pad characters inserted after the suffix.
+     *
+     * @see #setPadPosition
+     * @see #getPadPosition
+     * @see #PAD_BEFORE_PREFIX
+     * @see #PAD_AFTER_PREFIX
+     * @see #PAD_BEFORE_SUFFIX
+     * @stable ICU 2.0
+     */
+    public static final int PAD_AFTER_SUFFIX = 3;
+}
+
+// eof
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/DecimalFormatSymbols.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/DecimalFormatSymbols.java
index 9436fa6..51fc72a 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/DecimalFormatSymbols.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/DecimalFormatSymbols.java
@@ -1,350 +1,350 @@
-/*
- *******************************************************************************
- * Copyright (C) 1996-2011, International Business Machines Corporation and    *
- * others. All Rights Reserved.                                                *
- *******************************************************************************
- */
-
-package com.ibm.icu.text;
-
-
-import java.io.Serializable;
-import java.util.Locale;
-
-import com.ibm.icu.util.ULocale;
-
-/**
- * This class represents the set of symbols (such as the decimal separator, the
- * grouping separator, and so on) needed by <code>DecimalFormat</code> to format
- * numbers. <code>DecimalFormat</code> creates for itself an instance of
- * <code>DecimalFormatSymbols</code> from its locale data.  If you need to
- * change any of these symbols, you can get the
- * <code>DecimalFormatSymbols</code> object from your <code>DecimalFormat</code>
- * and modify it.
- *
- * <p><strong>This is an enhanced version of <code>DecimalFormatSymbols</code> that
- * is based on the standard version in the JDK.  New or changed functionality
- * is labeled
- * <strong><font face=helvetica color=red>NEW</font></strong>.</strong>
- *
- * @see          java.util.Locale
- * @see          DecimalFormat
- * @author       Mark Davis
- * @author       Alan Liu
- * @stable ICU 2.0
- */
-final public class DecimalFormatSymbols implements Cloneable, Serializable {
-
-    private static final long serialVersionUID =1L;
-
-    /**
-     * @internal
-     */
-    public final java.text.DecimalFormatSymbols dfs;
-
-    /**
-     * @internal
-     */
-    public DecimalFormatSymbols(java.text.DecimalFormatSymbols delegate) {
-        this.dfs = delegate;
-    }
-        
-    /**
-     * Create a DecimalFormatSymbols object for the default locale.
-     * @stable ICU 2.0
-     */
-    public DecimalFormatSymbols() {
-        this(new java.text.DecimalFormatSymbols());
-    }
-        
-    /**
-     * Create a DecimalFormatSymbols object for the given locale.
-     * @param locale the locale
-     * @stable ICU 2.0
-     */
-    public DecimalFormatSymbols(Locale locale) {
-        this(new java.text.DecimalFormatSymbols(locale));
-    }
-        
-    /**
-     * Create a DecimalFormatSymbols object for the given locale.
-     * @param locale the locale
-     * @stable ICU 3.2
-     */
-    public DecimalFormatSymbols(ULocale locale) {
-        this(new java.text.DecimalFormatSymbols(locale.toLocale()));
-    }
-        
-    /**
-     * Return the character used for zero. Different for Arabic, etc.
-     * @return the character
-     * @stable ICU 2.0
-     */
-    public char getZeroDigit() {
-        return dfs.getZeroDigit();
-    }
-        
-    /**
-     * Set the character used for zero.
-     * @param zeroDigit the zero character.
-     * @stable ICU 2.0
-     */
-    public void setZeroDigit(char zeroDigit) {
-        dfs.setZeroDigit(zeroDigit);
-    }
-        
-    /**
-     * Return the character used for thousands separator. Different for French, etc.
-     * @return the thousands character
-     * @stable ICU 2.0
-     */
-    public char getGroupingSeparator() {
-        return dfs.getGroupingSeparator();
-    }
-        
-    /**
-     * Set the character used for thousands separator. Different for French, etc.
-     * @param groupingSeparator the thousands character
-     * @stable ICU 2.0
-     */
-    public void setGroupingSeparator(char groupingSeparator) {
-        dfs.setGroupingSeparator(groupingSeparator);
-    }
-        
-    /**
-     * Return the character used for decimal sign. Different for French, etc.
-     * @return the decimal character
-     * @stable ICU 2.0
-     */
-    public char getDecimalSeparator() {
-        return dfs.getDecimalSeparator();
-    }
-        
-    /**
-     * Set the character used for decimal sign. Different for French, etc.
-     * @param decimalSeparator the decimal character
-     * @stable ICU 2.0
-     */
-    public void setDecimalSeparator(char decimalSeparator) {
-        dfs.setDecimalSeparator(decimalSeparator);
-    }
-        
-    /**
-     * Return the character used for mille percent sign. Different for Arabic, etc.
-     * @return the mille percent character
-     * @stable ICU 2.0
-     */
-    public char getPerMill() {
-        return dfs.getPerMill();
-    }
-        
-    /**
-     * Set the character used for mille percent sign. Different for Arabic, etc.
-     * @param perMill the mille percent character
-     * @stable ICU 2.0
-     */
-    public void setPerMill(char perMill) {
-        dfs.setPerMill(perMill);
-    }
-        
-    /**
-     * Return the character used for percent sign. Different for Arabic, etc.
-     * @return the percent character
-     * @stable ICU 2.0
-     */
-    public char getPercent() {
-        return dfs.getPercent();
-    }
-        
-    /**
-     * Set the character used for percent sign. Different for Arabic, etc.
-     * @param percent the percent character
-     * @stable ICU 2.0
-     */
-    public void setPercent(char percent) {
-        dfs.setPercent(percent);
-    }
-        
-    /**
-     * Return the character used for a digit in a pattern.
-     * @return the digit pattern character
-     * @stable ICU 2.0
-     */
-    public char getDigit() {
-        return dfs.getDigit();
-    }
-        
-    /**
-     * Set the character used for a digit in a pattern.
-     * @param digit the digit pattern character
-     * @stable ICU 2.0
-     */
-    public void setDigit(char digit) {
-        dfs.setDigit(digit);
-    }
-        
-    /**
-     * Return the character used to separate positive and negative subpatterns
-     * in a pattern.
-     * @return the pattern separator character
-     * @stable ICU 2.0
-     */
-    public char getPatternSeparator() {
-        return dfs.getPatternSeparator();
-    }
-        
-    /**
-     * Set the character used to separate positive and negative subpatterns
-     * in a pattern.
-     * @param patternSeparator the pattern separator character
-     * @stable ICU 2.0
-     */
-    public void setPatternSeparator(char patternSeparator) {
-        dfs.setPatternSeparator(patternSeparator);
-    }
-        
-    /**
-     * Return the String used to represent infinity. Almost always left
-     * unchanged.
-     * @return the Infinity string
-     * @stable ICU 2.0
-     */
-    public String getInfinity() {
-        return dfs.getInfinity();
-    }
-        
-    /**
-     * Set the String used to represent infinity. Almost always left
-     * unchanged.
-     * @param infinity the Infinity String
-     * @stable ICU 2.0
-     */
-    public void setInfinity(String infinity) {
-        dfs.setInfinity(infinity);
-    }
-        
-    /**
-     * Return the String used to represent NaN. Almost always left
-     * unchanged.
-     * @return the NaN String
-     * @stable ICU 2.0
-     */
-    public String getNaN() {
-        return dfs.getNaN();
-    }
-        
-    /**
-     * Set the String used to represent NaN. Almost always left
-     * unchanged.
-     * @param NaN the NaN String
-     * @stable ICU 2.0
-     */
-    public void setNaN(String NaN) {
-        dfs.setNaN(NaN);
-    }
-        
-    /**
-     * Return the character used to represent minus sign. If no explicit
-     * negative format is specified, one is formed by prefixing
-     * minusSign to the positive format.
-     * @return the minus sign character
-     * @stable ICU 2.0
-     */
-    public char getMinusSign() {
-        return dfs.getMinusSign();
-    }
-        
-    /**
-     * Set the character used to represent minus sign. If no explicit
-     * negative format is specified, one is formed by prefixing
-     * minusSign to the positive format.
-     * @param minusSign the minus sign character
-     * @stable ICU 2.0
-     */
-    public void setMinusSign(char minusSign) {
-        dfs.setMinusSign(minusSign);
-    }
-        
-    /**
-     * Return the string denoting the local currency.
-     * @return the local currency String.
-     * @stable ICU 2.0
-     */
-    public String getCurrencySymbol() {
-        return dfs.getCurrencySymbol();
-    }
-        
-    /**
-     * Set the string denoting the local currency.
-     * @param currency the local currency String.
-     * @stable ICU 2.0
-     */
-    public void setCurrencySymbol(String currency) {
-        dfs.setCurrencySymbol(currency);
-    }
-        
-    /**
-     * Return the international string denoting the local currency.
-     * @return the international string denoting the local currency
-     * @stable ICU 2.0
-     */
-    public String getInternationalCurrencySymbol() {
-        return dfs.getInternationalCurrencySymbol();
-    }
-        
-    /**
-     * Set the international string denoting the local currency.
-     * @param currency the international string denoting the local currency.
-     * @stable ICU 2.0
-     */
-    public void setInternationalCurrencySymbol(String currency) {
-        dfs.setInternationalCurrencySymbol(currency);
-    }
-        
-    /**
-     * Return the monetary decimal separator.
-     * @return the monetary decimal separator character
-     * @stable ICU 2.0
-     */
-    public char getMonetaryDecimalSeparator() {
-        return dfs.getMonetaryDecimalSeparator();
-    }
-        
-    /**
-     * Set the monetary decimal separator.
-     * @param sep the monetary decimal separator character
-     * @stable ICU 2.0
-     */
-    public void setMonetaryDecimalSeparator(char sep) {
-        dfs.setMonetaryDecimalSeparator(sep);
-    }
-        
-    /**
-     * Standard override.
-     * @stable ICU 2.0
-     */
-    public Object clone() {
-        return new DecimalFormatSymbols((java.text.DecimalFormatSymbols)dfs.clone());
-    }
-        
-    /**
-     * Override equals.
-     * @stable ICU 2.0
-     */
-    public boolean equals(Object obj) {
-        try {
-            return dfs.equals(((DecimalFormatSymbols)obj).dfs);
-        }
-        catch (Exception e) {
-            return false;
-        }
-    }
-        
-    /**
-     * Override hashCode
-     * @stable ICU 2.0
-     */
-    public int hashCode() {
-        return dfs.hashCode();
-    }
-}
+/*
+ *******************************************************************************
+ * Copyright (C) 1996-2011, International Business Machines Corporation and    *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+
+package com.ibm.icu.text;
+
+
+import java.io.Serializable;
+import java.util.Locale;
+
+import com.ibm.icu.util.ULocale;
+
+/**
+ * This class represents the set of symbols (such as the decimal separator, the
+ * grouping separator, and so on) needed by <code>DecimalFormat</code> to format
+ * numbers. <code>DecimalFormat</code> creates for itself an instance of
+ * <code>DecimalFormatSymbols</code> from its locale data.  If you need to
+ * change any of these symbols, you can get the
+ * <code>DecimalFormatSymbols</code> object from your <code>DecimalFormat</code>
+ * and modify it.
+ *
+ * <p><strong>This is an enhanced version of <code>DecimalFormatSymbols</code> that
+ * is based on the standard version in the JDK.  New or changed functionality
+ * is labeled
+ * <strong><font face=helvetica color=red>NEW</font></strong>.</strong>
+ *
+ * @see          java.util.Locale
+ * @see          DecimalFormat
+ * @author       Mark Davis
+ * @author       Alan Liu
+ * @stable ICU 2.0
+ */
+final public class DecimalFormatSymbols implements Cloneable, Serializable {
+
+    private static final long serialVersionUID =1L;
+
+    /**
+     * @internal
+     */
+    public final java.text.DecimalFormatSymbols dfs;
+
+    /**
+     * @internal
+     */
+    public DecimalFormatSymbols(java.text.DecimalFormatSymbols delegate) {
+        this.dfs = delegate;
+    }
+        
+    /**
+     * Create a DecimalFormatSymbols object for the default locale.
+     * @stable ICU 2.0
+     */
+    public DecimalFormatSymbols() {
+        this(new java.text.DecimalFormatSymbols());
+    }
+        
+    /**
+     * Create a DecimalFormatSymbols object for the given locale.
+     * @param locale the locale
+     * @stable ICU 2.0
+     */
+    public DecimalFormatSymbols(Locale locale) {
+        this(new java.text.DecimalFormatSymbols(locale));
+    }
+        
+    /**
+     * Create a DecimalFormatSymbols object for the given locale.
+     * @param locale the locale
+     * @stable ICU 3.2
+     */
+    public DecimalFormatSymbols(ULocale locale) {
+        this(new java.text.DecimalFormatSymbols(locale.toLocale()));
+    }
+        
+    /**
+     * Return the character used for zero. Different for Arabic, etc.
+     * @return the character
+     * @stable ICU 2.0
+     */
+    public char getZeroDigit() {
+        return dfs.getZeroDigit();
+    }
+        
+    /**
+     * Set the character used for zero.
+     * @param zeroDigit the zero character.
+     * @stable ICU 2.0
+     */
+    public void setZeroDigit(char zeroDigit) {
+        dfs.setZeroDigit(zeroDigit);
+    }
+        
+    /**
+     * Return the character used for thousands separator. Different for French, etc.
+     * @return the thousands character
+     * @stable ICU 2.0
+     */
+    public char getGroupingSeparator() {
+        return dfs.getGroupingSeparator();
+    }
+        
+    /**
+     * Set the character used for thousands separator. Different for French, etc.
+     * @param groupingSeparator the thousands character
+     * @stable ICU 2.0
+     */
+    public void setGroupingSeparator(char groupingSeparator) {
+        dfs.setGroupingSeparator(groupingSeparator);
+    }
+        
+    /**
+     * Return the character used for decimal sign. Different for French, etc.
+     * @return the decimal character
+     * @stable ICU 2.0
+     */
+    public char getDecimalSeparator() {
+        return dfs.getDecimalSeparator();
+    }
+        
+    /**
+     * Set the character used for decimal sign. Different for French, etc.
+     * @param decimalSeparator the decimal character
+     * @stable ICU 2.0
+     */
+    public void setDecimalSeparator(char decimalSeparator) {
+        dfs.setDecimalSeparator(decimalSeparator);
+    }
+        
+    /**
+     * Return the character used for mille percent sign. Different for Arabic, etc.
+     * @return the mille percent character
+     * @stable ICU 2.0
+     */
+    public char getPerMill() {
+        return dfs.getPerMill();
+    }
+        
+    /**
+     * Set the character used for mille percent sign. Different for Arabic, etc.
+     * @param perMill the mille percent character
+     * @stable ICU 2.0
+     */
+    public void setPerMill(char perMill) {
+        dfs.setPerMill(perMill);
+    }
+        
+    /**
+     * Return the character used for percent sign. Different for Arabic, etc.
+     * @return the percent character
+     * @stable ICU 2.0
+     */
+    public char getPercent() {
+        return dfs.getPercent();
+    }
+        
+    /**
+     * Set the character used for percent sign. Different for Arabic, etc.
+     * @param percent the percent character
+     * @stable ICU 2.0
+     */
+    public void setPercent(char percent) {
+        dfs.setPercent(percent);
+    }
+        
+    /**
+     * Return the character used for a digit in a pattern.
+     * @return the digit pattern character
+     * @stable ICU 2.0
+     */
+    public char getDigit() {
+        return dfs.getDigit();
+    }
+        
+    /**
+     * Set the character used for a digit in a pattern.
+     * @param digit the digit pattern character
+     * @stable ICU 2.0
+     */
+    public void setDigit(char digit) {
+        dfs.setDigit(digit);
+    }
+        
+    /**
+     * Return the character used to separate positive and negative subpatterns
+     * in a pattern.
+     * @return the pattern separator character
+     * @stable ICU 2.0
+     */
+    public char getPatternSeparator() {
+        return dfs.getPatternSeparator();
+    }
+        
+    /**
+     * Set the character used to separate positive and negative subpatterns
+     * in a pattern.
+     * @param patternSeparator the pattern separator character
+     * @stable ICU 2.0
+     */
+    public void setPatternSeparator(char patternSeparator) {
+        dfs.setPatternSeparator(patternSeparator);
+    }
+        
+    /**
+     * Return the String used to represent infinity. Almost always left
+     * unchanged.
+     * @return the Infinity string
+     * @stable ICU 2.0
+     */
+    public String getInfinity() {
+        return dfs.getInfinity();
+    }
+        
+    /**
+     * Set the String used to represent infinity. Almost always left
+     * unchanged.
+     * @param infinity the Infinity String
+     * @stable ICU 2.0
+     */
+    public void setInfinity(String infinity) {
+        dfs.setInfinity(infinity);
+    }
+        
+    /**
+     * Return the String used to represent NaN. Almost always left
+     * unchanged.
+     * @return the NaN String
+     * @stable ICU 2.0
+     */
+    public String getNaN() {
+        return dfs.getNaN();
+    }
+        
+    /**
+     * Set the String used to represent NaN. Almost always left
+     * unchanged.
+     * @param NaN the NaN String
+     * @stable ICU 2.0
+     */
+    public void setNaN(String NaN) {
+        dfs.setNaN(NaN);
+    }
+        
+    /**
+     * Return the character used to represent minus sign. If no explicit
+     * negative format is specified, one is formed by prefixing
+     * minusSign to the positive format.
+     * @return the minus sign character
+     * @stable ICU 2.0
+     */
+    public char getMinusSign() {
+        return dfs.getMinusSign();
+    }
+        
+    /**
+     * Set the character used to represent minus sign. If no explicit
+     * negative format is specified, one is formed by prefixing
+     * minusSign to the positive format.
+     * @param minusSign the minus sign character
+     * @stable ICU 2.0
+     */
+    public void setMinusSign(char minusSign) {
+        dfs.setMinusSign(minusSign);
+    }
+        
+    /**
+     * Return the string denoting the local currency.
+     * @return the local currency String.
+     * @stable ICU 2.0
+     */
+    public String getCurrencySymbol() {
+        return dfs.getCurrencySymbol();
+    }
+        
+    /**
+     * Set the string denoting the local currency.
+     * @param currency the local currency String.
+     * @stable ICU 2.0
+     */
+    public void setCurrencySymbol(String currency) {
+        dfs.setCurrencySymbol(currency);
+    }
+        
+    /**
+     * Return the international string denoting the local currency.
+     * @return the international string denoting the local currency
+     * @stable ICU 2.0
+     */
+    public String getInternationalCurrencySymbol() {
+        return dfs.getInternationalCurrencySymbol();
+    }
+        
+    /**
+     * Set the international string denoting the local currency.
+     * @param currency the international string denoting the local currency.
+     * @stable ICU 2.0
+     */
+    public void setInternationalCurrencySymbol(String currency) {
+        dfs.setInternationalCurrencySymbol(currency);
+    }
+        
+    /**
+     * Return the monetary decimal separator.
+     * @return the monetary decimal separator character
+     * @stable ICU 2.0
+     */
+    public char getMonetaryDecimalSeparator() {
+        return dfs.getMonetaryDecimalSeparator();
+    }
+        
+    /**
+     * Set the monetary decimal separator.
+     * @param sep the monetary decimal separator character
+     * @stable ICU 2.0
+     */
+    public void setMonetaryDecimalSeparator(char sep) {
+        dfs.setMonetaryDecimalSeparator(sep);
+    }
+        
+    /**
+     * Standard override.
+     * @stable ICU 2.0
+     */
+    public Object clone() {
+        return new DecimalFormatSymbols((java.text.DecimalFormatSymbols)dfs.clone());
+    }
+        
+    /**
+     * Override equals.
+     * @stable ICU 2.0
+     */
+    public boolean equals(Object obj) {
+        try {
+            return dfs.equals(((DecimalFormatSymbols)obj).dfs);
+        }
+        catch (Exception e) {
+            return false;
+        }
+    }
+        
+    /**
+     * Override hashCode
+     * @stable ICU 2.0
+     */
+    public int hashCode() {
+        return dfs.hashCode();
+    }
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/MessageFormat.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/MessageFormat.java
index 91bec49..31c2713 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/MessageFormat.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/MessageFormat.java
@@ -1,1415 +1,1415 @@
-/*
-**********************************************************************
-* Copyright (c) 2004-2011, International Business Machines
-* Corporation and others.  All Rights Reserved.
-**********************************************************************
-* Author: Alan Liu
-* Created: April 6, 2004
-* Since: ICU 3.0
-**********************************************************************
-*/
-package com.ibm.icu.text;
-
-import java.io.InvalidObjectException;
-import java.text.AttributedCharacterIterator;
-import java.text.AttributedCharacterIterator.Attribute;
-import java.text.AttributedString;
-import java.text.CharacterIterator;
-import java.text.ChoiceFormat;
-import java.text.FieldPosition;
-import java.text.Format;
-import java.text.ParseException;
-import java.text.ParsePosition;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-
-import com.ibm.icu.util.ULocale;
-
-/**
- * {@icuenhanced java.text.MessageFormat}.{@icu _usage_}
- *
- * <p>MessageFormat produces concatenated messages in a language-neutral
- * way. Use this whenever concatenating strings that are displayed to
- * end users.
- *
- * <p>A MessageFormat contains an array of <em>subformats</em> arranged
- * within a <em>template string</em>.  Together, the subformats and
- * template string determine how the MessageFormat will operate during
- * formatting and parsing.
- *
- * <p>Typically, both the subformats and the template string are
- * specified at once in a <em>pattern</em>.  By using different
- * patterns for different locales, messages may be localized.
- *
- * <p>When formatting, MessageFormat takes a collection of arguments
- * and produces a user-readable string.  The arguments may be passed
- * as an array or as a Map.  Each argument is matched up with its
- * corresponding subformat, which then formats it into a string.  The
- * resulting strings are then assembled within the string template of
- * the MessageFormat to produce the final output string.
- *
- * <p><strong>Note:</strong>
- * <code>MessageFormat</code> differs from the other <code>Format</code>
- * classes in that you create a <code>MessageFormat</code> object with one
- * of its constructors (not with a <code>getInstance</code> style factory
- * method). The factory methods aren't necessary because <code>MessageFormat</code>
- * itself doesn't implement locale-specific behavior. Any locale-specific
- * behavior is defined by the pattern that you provide and the
- * subformats used for inserted arguments.
- *
- * <p><strong>Note:</strong>
- * In ICU 3.8 MessageFormat supports named arguments.  If a named argument
- * is used, all arguments must be named.  Names start with a character in
- * <code>:ID_START:</code> and continue with characters in <code>:ID_CONTINUE:</code>,
- * in particular they do not start with a digit.  If named arguments
- * are used, {@link #usesNamedArguments()} will return true.
- *
- * <p>The other new methods supporting named arguments are
- * {@link #setFormatsByArgumentName(Map)},
- * {@link #setFormatByArgumentName(String, Format)},
- * {@link #format(Map, StringBuffer, FieldPosition)},
- * {@link #format(String, Map)}, {@link #parseToMap(String, ParsePosition)},
- * and {@link #parseToMap(String)}.  These methods are all compatible
- * with patterns that do not used named arguments-- in these cases
- * the keys in the input or output <code>Map</code>s use
- * <code>String</code>s that name the argument indices, e.g. "0",
- * "1", "2"... etc.
- *
- * <p>When named arguments are used, certain methods on MessageFormat that take or
- * return arrays will throw an exception, since it is not possible to
- * identify positions in an array using a name.  These methods are
- * {@link #setFormatsByArgumentIndex(Format[])},
- * {@link #setFormatByArgumentIndex(int, Format)},
- * {@link #getFormatsByArgumentIndex()},
- * {@link #getFormats()},
- * {@link #format(Object[], StringBuffer, FieldPosition)},
- * {@link #format(String, Object[])},
- * {@link #parse(String, ParsePosition)}, and
- * {@link #parse(String)}.
- * These APIs all have corresponding new versions as listed above.
- *
- * <p>The API {@link #format(Object, StringBuffer, FieldPosition)} has
- * been modified so that the <code>Object</code> argument can be
- * either an <code>Object</code> array or a <code>Map</code>.  If this
- * format uses named arguments, this argument must not be an
- * <code>Object</code> array otherwise an exception will be thrown.
- * If the argument is a <code>Map</code> it can be used with Strings that
- * represent indices as described above.
- *
- * <h4><a name="patterns">Patterns and Their Interpretation</a></h4>
- *
- * <code>MessageFormat</code> uses patterns of the following form:
- * <blockquote><pre>
- * <i>MessageFormatPattern:</i>
- *         <i>String</i>
- *         <i>MessageFormatPattern</i> <i>FormatElement</i> <i>String</i>
- *
- * <i>FormatElement:</i>
- *         { <i>ArgumentIndexOrName</i> }
- *         { <i>ArgumentIndexOrName</i> , <i>FormatType</i> }
- *         { <i>ArgumentIndexOrName</i> , <i>FormatType</i> , <i>FormatStyle</i> }
- *
- * <i>ArgumentIndexOrName: one of </i>
- *         ['0'-'9']+
- *         [:ID_START:][:ID_CONTINUE:]*
- *
- * <i>FormatType: one of </i>
- *         number date time choice spellout ordinal duration plural
- *
- * <i>FormatStyle:</i>
- *         short
- *         medium
- *         long
- *         full
- *         integer
- *         currency
- *         percent
- *         <i>SubformatPattern</i>
- *         <i>RulesetName</i>
- *
- * <i>String:</i>
- *         <i>StringPart<sub>opt</sub></i>
- *         <i>String</i> <i>StringPart</i>
- *
- * <i>StringPart:</i>
- *         ''
- *         ' <i>QuotedString</i> '
- *         <i>UnquotedString</i>
- *
- * <i>SubformatPattern:</i>
- *         <i>SubformatPatternPart<sub>opt</sub></i>
- *         <i>SubformatPattern</i> <i>SubformatPatternPart</i>
- *
- * <i>SubFormatPatternPart:</i>
- *         ' <i>QuotedPattern</i> '
- *         <i>UnquotedPattern</i>
- * </pre></blockquote>
- *
- * <i>RulesetName:</i>
- *         <i>UnquotedString</i>
- *
- * <p>Within a <i>String</i>, <code>"''"</code> represents a single
- * quote. A <i>QuotedString</i> can contain arbitrary characters
- * except single quotes; the surrounding single quotes are removed.
- * An <i>UnquotedString</i> can contain arbitrary characters
- * except single quotes and left curly brackets. Thus, a string that
- * should result in the formatted message "'{0}'" can be written as
- * <code>"'''{'0}''"</code> or <code>"'''{0}'''"</code>.
- *
- * <p>Within a <i>SubformatPattern</i>, different rules apply.
- * A <i>QuotedPattern</i> can contain arbitrary characters
- * except single quotes; but the surrounding single quotes are
- * <strong>not</strong> removed, so they may be interpreted by the
- * subformat. For example, <code>"{1,number,$'#',##}"</code> will
- * produce a number format with the pound-sign quoted, with a result
- * such as: "$#31,45".
- * An <i>UnquotedPattern</i> can contain arbitrary characters
- * except single quotes, but curly braces within it must be balanced.
- * For example, <code>"ab {0} de"</code> and <code>"ab '}' de"</code>
- * are valid subformat patterns, but <code>"ab {0'}' de"</code> and
- * <code>"ab } de"</code> are not.
- *
- * <p><dl><dt><b>Warning:</b><dd>The rules for using quotes within message
- * format patterns unfortunately have shown to be somewhat confusing.
- * In particular, it isn't always obvious to localizers whether single
- * quotes need to be doubled or not. Make sure to inform localizers about
- * the rules, and tell them (for example, by using comments in resource
- * bundle source files) which strings will be processed by MessageFormat.
- * Note that localizers may need to use single quotes in translated
- * strings where the original version doesn't have them.
- *
- * <br>Note also that the simplest way to avoid the problem is to
- * use the real apostrophe (single quote) character \u2019 (') for
- * human-readable text, and to use the ASCII apostrophe (\u0027 ' )
- * only in program syntax, like quoting in MessageFormat.
- * See the annotations for U+0027 Apostrophe in The Unicode Standard.</p>
- * </dl>
- *
- * <p>The <i>ArgumentIndex</i> value is a non-negative integer written
- * using the digits '0' through '9', and represents an index into the
- * <code>arguments</code> array passed to the <code>format</code> methods
- * or the result array returned by the <code>parse</code> methods.
- *
- * <p>The <i>FormatType</i> and <i>FormatStyle</i> values are used to create
- * a <code>Format</code> instance for the format element. The following
- * table shows how the values map to Format instances. Combinations not
- * shown in the table are illegal. A <i>SubformatPattern</i> must
- * be a valid pattern string for the Format subclass used.
- *
- * <p><table border=1>
- *    <tr>
- *       <th>Format Type
- *       <th>Format Style
- *       <th>Subformat Created
- *    <tr>
- *       <td colspan=2><i>(none)</i>
- *       <td><code>null</code>
- *    <tr>
- *       <td rowspan=5><code>number</code>
- *       <td><i>(none)</i>
- *       <td><code>NumberFormat.getInstance(getLocale())</code>
- *    <tr>
- *       <td><code>integer</code>
- *       <td><code>NumberFormat.getIntegerInstance(getLocale())</code>
- *    <tr>
- *       <td><code>currency</code>
- *       <td><code>NumberFormat.getCurrencyInstance(getLocale())</code>
- *    <tr>
- *       <td><code>percent</code>
- *       <td><code>NumberFormat.getPercentInstance(getLocale())</code>
- *    <tr>
- *       <td><i>SubformatPattern</i>
- *       <td><code>new DecimalFormat(subformatPattern, new DecimalFormatSymbols(getLocale()))</code>
- *    <tr>
- *       <td rowspan=6><code>date</code>
- *       <td><i>(none)</i>
- *       <td><code>DateFormat.getDateInstance(DateFormat.DEFAULT, getLocale())</code>
- *    <tr>
- *       <td><code>short</code>
- *       <td><code>DateFormat.getDateInstance(DateFormat.SHORT, getLocale())</code>
- *    <tr>
- *       <td><code>medium</code>
- *       <td><code>DateFormat.getDateInstance(DateFormat.DEFAULT, getLocale())</code>
- *    <tr>
- *       <td><code>long</code>
- *       <td><code>DateFormat.getDateInstance(DateFormat.LONG, getLocale())</code>
- *    <tr>
- *       <td><code>full</code>
- *       <td><code>DateFormat.getDateInstance(DateFormat.FULL, getLocale())</code>
- *    <tr>
- *       <td><i>SubformatPattern</i>
- *       <td><code>new SimpleDateFormat(subformatPattern, getLocale())
- *    <tr>
- *       <td rowspan=6><code>time</code>
- *       <td><i>(none)</i>
- *       <td><code>DateFormat.getTimeInstance(DateFormat.DEFAULT, getLocale())</code>
- *    <tr>
- *       <td><code>short</code>
- *       <td><code>DateFormat.getTimeInstance(DateFormat.SHORT, getLocale())</code>
- *    <tr>
- *       <td><code>medium</code>
- *       <td><code>DateFormat.getTimeInstance(DateFormat.DEFAULT, getLocale())</code>
- *    <tr>
- *       <td><code>long</code>
- *       <td><code>DateFormat.getTimeInstance(DateFormat.LONG, getLocale())</code>
- *    <tr>
- *       <td><code>full</code>
- *       <td><code>DateFormat.getTimeInstance(DateFormat.FULL, getLocale())</code>
- *    <tr>
- *       <td><i>SubformatPattern</i>
- *       <td><code>new SimpleDateFormat(subformatPattern, getLocale())
- *    <tr>
- *       <td><code>choice</code>
- *       <td><i>SubformatPattern</i>
- *       <td><code>new ChoiceFormat(subformatPattern)</code>
- *    <tr>
- *       <td><code>spellout</code>
- *       <td><i>RulesetName (optional)</i>
- *       <td><code>new RuleBasedNumberFormat(getLocale(), RuleBasedNumberFormat.SPELLOUT)
- *           <br/>&nbsp;&nbsp;&nbsp;&nbsp;.setDefaultRuleset(ruleset);</code>
- *    <tr>
- *       <td><code>ordinal</code>
- *       <td><i>RulesetName (optional)</i>
- *       <td><code>new RuleBasedNumberFormat(getLocale(), RuleBasedNumberFormat.ORDINAL)
- *           <br/>&nbsp;&nbsp;&nbsp;&nbsp;.setDefaultRuleset(ruleset);</code>
- *    <tr>
- *       <td><code>duration</code>
- *       <td><i>RulesetName (optional)</i>
- *       <td><code>new RuleBasedNumberFormat(getLocale(), RuleBasedNumberFormat.DURATION)
- *           <br/>&nbsp;&nbsp;&nbsp;&nbsp;.setDefaultRuleset(ruleset);</code>
- *    <tr>
- *       <td><code>plural</code>
- *       <td><i>SubformatPattern</i>
- *       <td><code>new PluralFormat(subformatPattern)</code>
- *    <tr>
- *       <td><code>select</code>
- *       <td><i>SubformatPattern</i>
- *       <td><code>new SelectFormat(subformatPattern)</code>
- * </table>
- * <p>
- *
- * <h4>Usage Information</h4>
- *
- * <p>Here are some examples of usage:
- * <blockquote>
- * <pre>
- * Object[] arguments = {
- *     new Integer(7),
- *     new Date(System.currentTimeMillis()),
- *     "a disturbance in the Force"
- * };
- *
- * String result = MessageFormat.format(
- *     "At {1,time} on {1,date}, there was {2} on planet {0,number,integer}.",
- *     arguments);
- *
- * <em>output</em>: At 12:30 PM on Jul 3, 2053, there was a disturbance
- *           in the Force on planet 7.
- *
- * </pre>
- * </blockquote>
- * Typically, the message format will come from resources, and the
- * arguments will be dynamically set at runtime.
- *
- * <p>Example 2:
- * <blockquote>
- * <pre>
- * Object[] testArgs = {new Long(3), "MyDisk"};
- *
- * MessageFormat form = new MessageFormat(
- *     "The disk \"{1}\" contains {0} file(s).");
- *
- * System.out.println(form.format(testArgs));
- *
- * // output, with different testArgs
- * <em>output</em>: The disk "MyDisk" contains 0 file(s).
- * <em>output</em>: The disk "MyDisk" contains 1 file(s).
- * <em>output</em>: The disk "MyDisk" contains 1,273 file(s).
- * </pre>
- * </blockquote>
- *
- * <p>For more sophisticated patterns, you can use a <code>ChoiceFormat</code> to get
- * output such as:
- * <blockquote>
- * <pre>
- * MessageFormat form = new MessageFormat("The disk \"{1}\" contains {0}.");
- * double[] filelimits = {0,1,2};
- * String[] filepart = {"no files","one file","{0,number} files"};
- * ChoiceFormat fileform = new ChoiceFormat(filelimits, filepart);
- * form.setFormatByArgumentIndex(0, fileform);
- *
- * Object[] testArgs = {new Long(12373), "MyDisk"};
- *
- * System.out.println(form.format(testArgs));
- *
- * // output, with different testArgs
- * output: The disk "MyDisk" contains no files.
- * output: The disk "MyDisk" contains one file.
- * output: The disk "MyDisk" contains 1,273 files.
- * </pre>
- * </blockquote>
- * You can either do this programmatically, as in the above example,
- * or by using a pattern (see
- * {@link ChoiceFormat}
- * for more information) as in:
- * <blockquote>
- * <pre>
- * form.applyPattern(
- *    "There {0,choice,0#are no files|1#is one file|1&lt;are {0,number,integer} files}.");
- * </pre>
- * </blockquote>
- *
- * <p><strong>Note:</strong> As we see above, the string produced
- * by a <code>ChoiceFormat</code> in <code>MessageFormat</code> is treated specially;
- * occurances of '{' are used to indicated subformats, and cause recursion.
- * If you create both a <code>MessageFormat</code> and <code>ChoiceFormat</code>
- * programmatically (instead of using the string patterns), then be careful not to
- * produce a format that recurses on itself, which will cause an infinite loop.
- *
- * <p>When a single argument is parsed more than once in the string, the last match
- * will be the final result of the parsing.  For example,
- * <pre>
- * MessageFormat mf = new MessageFormat("{0,number,#.##}, {0,number,#.#}");
- * Object[] objs = {new Double(3.1415)};
- * String result = mf.format( objs );
- * // result now equals "3.14, 3.1"
- * objs = null;
- * objs = mf.parse(result, new ParsePosition(0));
- * // objs now equals {new Double(3.1)}
- * </pre>
- *
- * <p>Likewise, parsing with a MessageFormat object using patterns containing
- * multiple occurances of the same argument would return the last match.  For
- * example,
- * <pre>
- * MessageFormat mf = new MessageFormat("{0}, {0}, {0}");
- * String forParsing = "x, y, z";
- * Object[] objs = mf.parse(forParsing, new ParsePosition(0));
- * // result now equals {new String("z")}
- * </pre>
- *
- * <h4><a name="synchronization">Synchronization</a></h4>
- *
- * <p>Message formats are not synchronized.
- * It is recommended to create separate format instances for each thread.
- * If multiple threads access a format concurrently, it must be synchronized
- * externally.
- *
- * @see          java.util.Locale
- * @see          Format
- * @see          NumberFormat
- * @see          DecimalFormat
- * @see          ChoiceFormat
- * @see          PluralFormat
- * @see          SelectFormat
- * @author       Mark Davis
- * @stable ICU 3.0
- */
-public class MessageFormat extends UFormat {
-    static final long serialVersionUID = 1L;
-
-    /**
-     * @internal
-     */
-    public final java.text.MessageFormat messageFormat;
-        
-    /**
-     * @internal
-     * @param delegate the DateFormat to which to delegate
-     */
-    public MessageFormat(java.text.MessageFormat delegate) {
-        wrapNestedFormatters(delegate);
-        this.messageFormat = delegate;
-    }
-
-    /**
-     * Constructs a MessageFormat for the default locale and the
-     * specified pattern.
-     * The constructor first sets the locale, then parses the pattern and
-     * creates a list of subformats for the format elements contained in it.
-     * Patterns and their interpretation are specified in the
-     * <a href="#patterns">class description</a>.
-     *
-     * @param pattern the pattern for this message format
-     * @exception IllegalArgumentException if the pattern is invalid
-     * @stable ICU 3.0
-     */
-    public MessageFormat(String pattern) {
-        this(new java.text.MessageFormat(pattern));
-    }
-
-    /**
-     * Constructs a MessageFormat for the specified locale and
-     * pattern.
-     * The constructor first sets the locale, then parses the pattern and
-     * creates a list of subformats for the format elements contained in it.
-     * Patterns and their interpretation are specified in the
-     * <a href="#patterns">class description</a>.
-     *
-     * @param pattern the pattern for this message format
-     * @param locale the locale for this message format
-     * @exception IllegalArgumentException if the pattern is invalid
-     * @stable ICU 3.0
-     */
-    public MessageFormat(String pattern, Locale locale) {
-        this(new java.text.MessageFormat(pattern, locale));
-    }
-
-    /**
-     * Constructs a MessageFormat for the specified locale and
-     * pattern.
-     * The constructor first sets the locale, then parses the pattern and
-     * creates a list of subformats for the format elements contained in it.
-     * Patterns and their interpretation are specified in the
-     * <a href="#patterns">class description</a>.
-     *
-     * @param pattern the pattern for this message format
-     * @param locale the locale for this message format
-     * @exception IllegalArgumentException if the pattern is invalid
-     * @stable ICU 3.2
-     */
-    public MessageFormat(String pattern, ULocale locale) {
-        this(new java.text.MessageFormat(pattern, locale.toLocale()));
-    }
-
-    /**
-     * Sets the locale to be used when creating or comparing subformats.
-     * This affects subsequent calls to the {@link #applyPattern applyPattern}
-     * and {@link #toPattern toPattern} methods as well as to the
-     * <code>format</code> and
-     * {@link #formatToCharacterIterator formatToCharacterIterator} methods.
-     *
-     * @param locale the locale to be used when creating or comparing subformats
-     * @stable ICU 3.0
-     */
-    public void setLocale(Locale locale) {
-        messageFormat.setLocale(locale);
-    }
-
-    /**
-     * Sets the locale to be used when creating or comparing subformats.
-     * This affects subsequent calls to the {@link #applyPattern applyPattern}
-     * and {@link #toPattern toPattern} methods as well as to the
-     * <code>format</code> and
-     * {@link #formatToCharacterIterator formatToCharacterIterator} methods.
-     *
-     * @param locale the locale to be used when creating or comparing subformats
-     * @stable ICU 3.2
-     */
-    public void setLocale(ULocale locale) {
-        messageFormat.setLocale(locale.toLocale());
-    }
-
-    /**
-     * Returns the locale that's used when creating or comparing subformats.
-     *
-     * @return the locale used when creating or comparing subformats
-     * @stable ICU 3.0
-     */
-    public Locale getLocale() {
-        return messageFormat.getLocale();
-    }
-
-    /**
-     * {@icu} Returns the locale that's used when creating or comparing subformats.
-     *
-     * @return the locale used when creating or comparing subformats
-     * @stable ICU 3.2
-     */
-    public ULocale getULocale() {
-        return ULocale.forLocale(messageFormat.getLocale());
-    }
-
-    /**
-     * Sets the pattern used by this message format.
-     * The method parses the pattern and creates a list of subformats
-     * for the format elements contained in it.
-     * Patterns and their interpretation are specified in the
-     * <a href="#patterns">class description</a>.
-     * <p>
-     * The pattern must contain only named or only numeric arguments,
-     * mixing them is not allowed.
-     *
-     * @param pttrn the pattern for this message format
-     * @throws IllegalArgumentException if the pattern is invalid
-     * @stable ICU 3.0
-     */
-    public void applyPattern(String pttrn) {
-        messageFormat.applyPattern(pttrn);
-        wrapNestedFormatters(messageFormat);
-    }
-
-    /**
-     * Returns a pattern representing the current state of the message format.
-     * The string is constructed from internal information and therefore
-     * does not necessarily equal the previously applied pattern.
-     *
-     * @return a pattern representing the current state of the message format
-     * @stable ICU 3.0
-     */
-    public String toPattern() {
-        String pattern = savedPattern == null ? messageFormat.toPattern() : savedPattern;
-        return pattern;
-    }
-
-    /**
-     * Sets the formats to use for the values passed into
-     * <code>format</code> methods or returned from <code>parse</code>
-     * methods. The indices of elements in <code>newFormats</code>
-     * correspond to the argument indices used in the previously set
-     * pattern string.
-     * The order of formats in <code>newFormats</code> thus corresponds to
-     * the order of elements in the <code>arguments</code> array passed
-     * to the <code>format</code> methods or the result array returned
-     * by the <code>parse</code> methods.
-     * <p>
-     * If an argument index is used for more than one format element
-     * in the pattern string, then the corresponding new format is used
-     * for all such format elements. If an argument index is not used
-     * for any format element in the pattern string, then the
-     * corresponding new format is ignored. If fewer formats are provided
-     * than needed, then only the formats for argument indices less
-     * than <code>newFormats.length</code> are replaced.
-     *
-     * This method is only supported if the format does not use
-     * named arguments, otherwise an IllegalArgumentException is thrown.
-     *
-     * @param newFormats the new formats to use
-     * @throws NullPointerException if <code>newFormats</code> is null
-     * @throws IllegalArgumentException if this formatter uses named arguments
-     * @stable ICU 3.0
-     */
-    public void setFormatsByArgumentIndex(Format[] newFormats) {
-        messageFormat.setFormatsByArgumentIndex(newFormats);
-        savedPattern = null;
-    }
-
-    /**
-     * {@icu} Sets the formats to use for the values passed into
-     * <code>format</code> methods or returned from <code>parse</code>
-     * methods. The keys in <code>newFormats</code> are the argument
-     * names in the previously set pattern string, and the values
-     * are the formats.
-     * <p>
-     * Only argument names from the pattern string are considered.
-     * Extra keys in <code>newFormats</code> that do not correspond
-     * to an argument name are ignored.  Similarly, if there is no
-     * format in newFormats for an argument name, the formatter
-     * for that argument remains unchanged.
-     * <p>
-     * This may be called on formats that do not use named arguments.
-     * In this case the map will be queried for key Strings that
-     * represent argument indices, e.g. "0", "1", "2" etc.
-     *
-     * @param newFormats a map from String to Format providing new
-     *        formats for named arguments.
-     * @stable ICU 3.8
-     */
-    public void setFormatsByArgumentName(Map<String, Format> newFormats) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Sets the formats to use for the format elements in the
-     * previously set pattern string.
-     * The order of formats in <code>newFormats</code> corresponds to
-     * the order of format elements in the pattern string.
-     * <p>
-     * If more formats are provided than needed by the pattern string,
-     * the remaining ones are ignored. If fewer formats are provided
-     * than needed, then only the first <code>newFormats.length</code>
-     * formats are replaced.
-     * <p>
-     * Since the order of format elements in a pattern string often
-     * changes during localization, it is generally better to use the
-     * {@link #setFormatsByArgumentIndex setFormatsByArgumentIndex}
-     * method, which assumes an order of formats corresponding to the
-     * order of elements in the <code>arguments</code> array passed to
-     * the <code>format</code> methods or the result array returned by
-     * the <code>parse</code> methods.
-     *
-     * @param newFormats the new formats to use
-     * @exception NullPointerException if <code>newFormats</code> is null
-     * @stable ICU 3.0
-     */
-    public void setFormats(Format[] newFormats) {
-        messageFormat.setFormats(newFormats);
-        savedPattern = null;
-    }
-
-    /**
-     * Sets the format to use for the format elements within the
-     * previously set pattern string that use the given argument
-     * index.
-     * The argument index is part of the format element definition and
-     * represents an index into the <code>arguments</code> array passed
-     * to the <code>format</code> methods or the result array returned
-     * by the <code>parse</code> methods.
-     * <p>
-     * If the argument index is used for more than one format element
-     * in the pattern string, then the new format is used for all such
-     * format elements. If the argument index is not used for any format
-     * element in the pattern string, then the new format is ignored.
-     *
-     * This method is only supported when exclusively numbers are used for
-     * argument names. Otherwise an IllegalArgumentException is thrown.
-     *
-     * @param argumentIndex the argument index for which to use the new format
-     * @param newFormat the new format to use
-     * @throws IllegalArgumentException if this format uses named arguments
-     * @stable ICU 3.0
-     */
-    public void setFormatByArgumentIndex(int argumentIndex, Format newFormat) {
-        messageFormat.setFormatByArgumentIndex(argumentIndex, newFormat);
-        savedPattern = null;
-    }
-
-    /**
-     * {@icu} Sets the format to use for the format elements within the
-     * previously set pattern string that use the given argument
-     * name.
-     * <p>
-     * If the argument name is used for more than one format element
-     * in the pattern string, then the new format is used for all such
-     * format elements. If the argument name is not used for any format
-     * element in the pattern string, then the new format is ignored.
-     * <p>
-     * This API may be used on formats that do not use named arguments.
-     * In this case <code>argumentName</code> should be a String that names
-     * an argument index, e.g. "0", "1", "2"... etc.  If it does not name
-     * a valid index, the format will be ignored.  No error is thrown.
-     *
-     * @param argumentName the name of the argument to change
-     * @param newFormat the new format to use
-     * @stable ICU 3.8
-     */
-    public void setFormatByArgumentName(String argumentName, Format newFormat) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Sets the format to use for the format element with the given
-     * format element index within the previously set pattern string.
-     * The format element index is the zero-based number of the format
-     * element counting from the start of the pattern string.
-     * <p>
-     * Since the order of format elements in a pattern string often
-     * changes during localization, it is generally better to use the
-     * {@link #setFormatByArgumentIndex setFormatByArgumentIndex}
-     * method, which accesses format elements based on the argument
-     * index they specify.
-     *
-     * @param formatElementIndex the index of a format element within the pattern
-     * @param newFormat the format to use for the specified format element
-     * @exception ArrayIndexOutOfBoundsException if formatElementIndex is equal to or
-     *            larger than the number of format elements in the pattern string
-     * @stable ICU 3.0
-     */
-    public void setFormat(int formatElementIndex, Format newFormat) {
-        messageFormat.setFormat(formatElementIndex, newFormat);
-        savedPattern = null;
-    }
-
-    /**
-     * Returns the formats used for the values passed into
-     * <code>format</code> methods or returned from <code>parse</code>
-     * methods. The indices of elements in the returned array
-     * correspond to the argument indices used in the previously set
-     * pattern string.
-     * The order of formats in the returned array thus corresponds to
-     * the order of elements in the <code>arguments</code> array passed
-     * to the <code>format</code> methods or the result array returned
-     * by the <code>parse</code> methods.
-     * <p>
-     * If an argument index is used for more than one format element
-     * in the pattern string, then the format used for the last such
-     * format element is returned in the array. If an argument index
-     * is not used for any format element in the pattern string, then
-     * null is returned in the array.
-     *
-     * This method is only supported when exclusively numbers are used for
-     * argument names. Otherwise an IllegalArgumentException is thrown.
-     *
-     * @return the formats used for the arguments within the pattern
-     * @throws IllegalArgumentException if this format uses named arguments
-     * @stable ICU 3.0
-     */
-    public Format[] getFormatsByArgumentIndex() {
-        return messageFormat.getFormatsByArgumentIndex();
-    }
-
-    /**
-     * Returns the formats used for the format elements in the
-     * previously set pattern string.
-     * The order of formats in the returned array corresponds to
-     * the order of format elements in the pattern string.
-     * <p>
-     * Since the order of format elements in a pattern string often
-     * changes during localization, it's generally better to use the
-     * {@link #getFormatsByArgumentIndex()}
-     * method, which assumes an order of formats corresponding to the
-     * order of elements in the <code>arguments</code> array passed to
-     * the <code>format</code> methods or the result array returned by
-     * the <code>parse</code> methods.
-     *
-     * This method is only supported when exclusively numbers are used for
-     * argument names. Otherwise an IllegalArgumentException is thrown.
-     *
-     * @return the formats used for the format elements in the pattern
-     * @throws IllegalArgumentException if this format uses named arguments
-     * @stable ICU 3.0
-     */
-    public Format[] getFormats() {
-        return messageFormat.getFormats();
-    }
-
-    /**
-     * {@icu} Returns the format argument names. For more details, see
-     * {@link #setFormatByArgumentName(String, Format)}.
-     * @return List of names
-     * @internal
-     * @deprecated This API is ICU internal only.
-     */
-    public Set<String> getFormatArgumentNames() {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Returns the formats according to their argument names. For more details, see
-     * {@link #setFormatByArgumentName(String, Format)}.
-     * @return format associated with the name, or null if there isn't one.
-     * @internal
-     * @deprecated This API is ICU internal only.
-     */
-    public Format getFormatByArgumentName(String argumentName) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Formats an array of objects and appends the <code>MessageFormat</code>'s
-     * pattern, with format elements replaced by the formatted objects, to the
-     * provided <code>StringBuffer</code>.
-     * <p>
-     * The text substituted for the individual format elements is derived from
-     * the current subformat of the format element and the
-     * <code>arguments</code> element at the format element's argument index
-     * as indicated by the first matching line of the following table. An
-     * argument is <i>unavailable</i> if <code>arguments</code> is
-     * <code>null</code> or has fewer than argumentIndex+1 elements.  When
-     * an argument is unavailable no substitution is performed.
-     * <p>
-     * <table border=1>
-     *    <tr>
-     *       <th>Subformat
-     *       <th>Argument
-     *       <th>Formatted Text
-     *    <tr>
-     *       <td><i>any</i>
-     *       <td><i>unavailable</i>
-     *       <td><code>"{" + argumentIndex + "}"</code>
-     *    <tr>
-     *       <td><i>any</i>
-     *       <td><code>null</code>
-     *       <td><code>"null"</code>
-     *    <tr>
-     *       <td><code>instanceof ChoiceFormat</code>
-     *       <td><i>any</i>
-     *       <td><code>subformat.format(argument).indexOf('{') >= 0 ?<br>
-     *           (new MessageFormat(subformat.format(argument), getLocale())).format(argument) :
-     *           subformat.format(argument)</code>
-     *    <tr>
-     *       <td><code>!= null</code>
-     *       <td><i>any</i>
-     *       <td><code>subformat.format(argument)</code>
-     *    <tr>
-     *       <td><code>null</code>
-     *       <td><code>instanceof Number</code>
-     *       <td><code>NumberFormat.getInstance(getLocale()).format(argument)</code>
-     *    <tr>
-     *       <td><code>null</code>
-     *       <td><code>instanceof Date</code>
-     *       <td><code>DateFormat.getDateTimeInstance(DateFormat.SHORT,
-     *           DateFormat.SHORT, getLocale()).format(argument)</code>
-     *    <tr>
-     *       <td><code>null</code>
-     *       <td><code>instanceof String</code>
-     *       <td><code>argument</code>
-     *    <tr>
-     *       <td><code>null</code>
-     *       <td><i>any</i>
-     *       <td><code>argument.toString()</code>
-     * </table>
-     * <p>
-     * If <code>pos</code> is non-null, and refers to
-     * <code>Field.ARGUMENT</code>, the location of the first formatted
-     * string will be returned.
-     *
-     * This method is only supported when the format does not use named
-     * arguments, otherwise an IllegalArgumentException is thrown.
-     *
-     * @param arguments an array of objects to be formatted and substituted.
-     * @param result where text is appended.
-     * @param pos On input: an alignment field, if desired.
-     *            On output: the offsets of the alignment field.
-     * @throws IllegalArgumentException if an argument in the
-     *            <code>arguments</code> array is not of the type
-     *            expected by the format element(s) that use it.
-     * @throws IllegalArgumentException if this format uses named arguments
-     * @stable ICU 3.0
-     */
-    public final StringBuffer format(Object[] arguments, StringBuffer result,
-                                     FieldPosition pos) {
-        FieldPosition jdkPos = toJDKFieldPosition(pos);
-        StringBuffer buf = messageFormat.format(arguments, result, jdkPos);
-        if (jdkPos != null) {
-            pos.setBeginIndex(jdkPos.getBeginIndex());
-            pos.setEndIndex(jdkPos.getEndIndex());
-        }
-        return buf;
-    }
-
-    /**
-     * Formats a map of objects and appends the <code>MessageFormat</code>'s
-     * pattern, with format elements replaced by the formatted objects, to the
-     * provided <code>StringBuffer</code>.
-     * <p>
-     * The text substituted for the individual format elements is derived from
-     * the current subformat of the format element and the
-     * <code>arguments</code> value corresopnding to the format element's
-     * argument name.
-     * <p>
-     * This API may be called on formats that do not use named arguments.
-     * In this case the the keys in <code>arguments</code> must be numeric
-     * strings (e.g. "0", "1", "2"...).
-     * <p>
-     * An argument is <i>unavailable</i> if <code>arguments</code> is
-     * <code>null</code> or does not have a value corresponding to an argument
-     * name in the pattern.  When an argument is unavailable no substitution
-     * is performed.
-     *
-     * @param arguments a map of objects to be formatted and substituted.
-     * @param result where text is appended.
-     * @param pos On input: an alignment field, if desired.
-     *            On output: the offsets of the alignment field.
-     * @throws IllegalArgumentException if an argument in the
-     *         <code>arguments</code> array is not of the type
-     *         expected by the format element(s) that use it.
-     * @return the passed-in StringBuffer
-     * @stable ICU 3.8
-     */
-    public final StringBuffer format(Map<String, Object> arguments, StringBuffer result,
-                                     FieldPosition pos) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Creates a MessageFormat with the given pattern and uses it
-     * to format the given arguments. This is equivalent to
-     * <blockquote>
-     *     <code>(new {@link #MessageFormat(String) MessageFormat}(pattern)).{@link
-     *     #format(java.lang.Object[], java.lang.StringBuffer, java.text.FieldPosition)
-     *     format}(arguments, new StringBuffer(), null).toString()</code>
-     * </blockquote>
-     *
-     * @throws IllegalArgumentException if the pattern is invalid,
-     *            or if an argument in the <code>arguments</code> array
-     *            is not of the type expected by the format element(s)
-     *            that use it.
-     * @throws IllegalArgumentException if this format uses named arguments
-     * @stable ICU 3.0
-     */
-    public static String format(String pattern, Object... arguments) {
-        return java.text.MessageFormat.format(pattern, arguments);
-    }
-
-    /**
-     * Creates a MessageFormat with the given pattern and uses it to
-     * format the given arguments.  The pattern must identifyarguments
-     * by name instead of by number.
-     * <p>
-     * @throws IllegalArgumentException if the pattern is invalid,
-     *         or if an argument in the <code>arguments</code> map
-     *         is not of the type expected by the format element(s)
-     *         that use it.
-     * @see #format(Map, StringBuffer, FieldPosition)
-     * @see #format(String, Object[])
-     * @stable ICU 3.8
-     */
-    public static String format(String pattern, Map<String, Object> arguments) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Returns true if this MessageFormat uses named arguments,
-     * and false otherwise.  See class description.
-     *
-     * @return true if named arguments are used.
-     * @stable ICU 3.8
-     */
-    public boolean usesNamedArguments() {
-        // always false with com.ibm.icu.base
-        return false;
-    }
-
-    // Overrides
-    /**
-     * Formats a map or array of objects and appends the <code>MessageFormat</code>'s
-     * pattern, with format elements replaced by the formatted objects, to the
-     * provided <code>StringBuffer</code>.
-     * This is equivalent to either of
-     * <blockquote>
-     *     <code>{@link #format(java.lang.Object[], java.lang.StringBuffer,
-     *     java.text.FieldPosition) format}((Object[]) arguments, result, pos)</code>
-     *     <code>{@link #format(java.util.Map, java.lang.StringBuffer,
-     *     java.text.FieldPosition) format}((Map) arguments, result, pos)</code>
-     * </blockquote>
-     * A map must be provided if this format uses named arguments, otherwise
-     * an IllegalArgumentException will be thrown.
-     * @param arguments a map or array of objects to be formatted
-     * @param result where text is appended
-     * @param pos On input: an alignment field, if desired
-     *            On output: the offsets of the alignment field
-     * @throws IllegalArgumentException if an argument in
-     *         <code>arguments</code> is not of the type
-     *         expected by the format element(s) that use it
-     * @throws IllegalArgumentException if <code>arguments<code> is
-     *         an array of Object and this format uses named arguments
-     * @stable ICU 3.0
-     */
-    public final StringBuffer format(Object arguments, StringBuffer result,
-                                     FieldPosition pos) {
-        FieldPosition jdkPos = toJDKFieldPosition(pos);
-        StringBuffer buf = messageFormat.format(arguments, result, jdkPos);
-        if (jdkPos != null) {
-            pos.setBeginIndex(jdkPos.getBeginIndex());
-            pos.setEndIndex(jdkPos.getEndIndex());
-        }
-        return buf;
-    }
-
-    /**
-     * Formats an array of objects and inserts them into the
-     * <code>MessageFormat</code>'s pattern, producing an
-     * <code>AttributedCharacterIterator</code>.
-     * You can use the returned <code>AttributedCharacterIterator</code>
-     * to build the resulting String, as well as to determine information
-     * about the resulting String.
-     * <p>
-     * The text of the returned <code>AttributedCharacterIterator</code> is
-     * the same that would be returned by
-     * <blockquote>
-     *     <code>{@link #format(java.lang.Object[], java.lang.StringBuffer,
-     *     java.text.FieldPosition) format}(arguments, new StringBuffer(), null).toString()</code>
-     * </blockquote>
-     * <p>
-     * In addition, the <code>AttributedCharacterIterator</code> contains at
-     * least attributes indicating where text was generated from an
-     * argument in the <code>arguments</code> array. The keys of these attributes are of
-     * type <code>MessageFormat.Field</code>, their values are
-     * <code>Integer</code> objects indicating the index in the <code>arguments</code>
-     * array of the argument from which the text was generated.
-     * <p>
-     * The attributes/value from the underlying <code>Format</code>
-     * instances that <code>MessageFormat</code> uses will also be
-     * placed in the resulting <code>AttributedCharacterIterator</code>.
-     * This allows you to not only find where an argument is placed in the
-     * resulting String, but also which fields it contains in turn.
-     *
-     * @param arguments an array of objects to be formatted and substituted.
-     * @return AttributedCharacterIterator describing the formatted value.
-     * @exception NullPointerException if <code>arguments</code> is null.
-     * @exception IllegalArgumentException if an argument in the
-     *            <code>arguments</code> array is not of the type
-     *            expected by the format element(s) that use it.
-     * @stable ICU 3.8
-     */
-    public AttributedCharacterIterator formatToCharacterIterator(Object arguments) {
-        AttributedCharacterIterator it = messageFormat.formatToCharacterIterator(arguments);
-
-        // Extract formatted String first
-        StringBuilder sb = new StringBuilder();
-        for (char c = it.first(); c != CharacterIterator.DONE; c = it.next()) {
-            sb.append(c);
-        }
-
-        // Create AttributedString
-        AttributedString attrstr = new AttributedString(sb.toString());
-
-        // Map JDK Field to ICU Field
-        int idx = 0;
-        it.first();
-        while (idx < it.getEndIndex()) {
-            int end = it.getRunLimit();
-            Map<Attribute, Object> attributes = it.getAttributes();
-            if (attributes != null) {
-                for (Entry<Attribute, Object> entry : attributes.entrySet()) {
-                    Attribute attr = entry.getKey();
-                    Object val = entry.getValue();
-                    if (attr.equals(java.text.MessageFormat.Field.ARGUMENT)) {
-                        val = attr = Field.ARGUMENT;
-                    }
-                    attrstr.addAttribute(attr, val, idx, end);
-                }
-            }
-            idx = end;
-            while (it.getIndex() < idx) {
-                it.next();
-            }
-        }
-
-        return attrstr.getIterator();
-    }
-
-    /**
-     * Parses the string.
-     *
-     * <p>Caveats: The parse may fail in a number of circumstances.
-     * For example:
-     * <ul>
-     * <li>If one of the arguments does not occur in the pattern.
-     * <li>If the format of an argument loses information, such as
-     *     with a choice format where a large number formats to "many".
-     * <li>Does not yet handle recursion (where
-     *     the substituted strings contain {n} references.)
-     * <li>Will not always find a match (or the correct match)
-     *     if some part of the parse is ambiguous.
-     *     For example, if the pattern "{1},{2}" is used with the
-     *     string arguments {"a,b", "c"}, it will format as "a,b,c".
-     *     When the result is parsed, it will return {"a", "b,c"}.
-     * <li>If a single argument is parsed more than once in the string,
-     *     then the later parse wins.
-     * </ul>
-     * When the parse fails, use ParsePosition.getErrorIndex() to find out
-     * where in the string did the parsing failed. The returned error
-     * index is the starting offset of the sub-patterns that the string
-     * is comparing with. For example, if the parsing string "AAA {0} BBB"
-     * is comparing against the pattern "AAD {0} BBB", the error index is
-     * 0. When an error occurs, the call to this method will return null.
-     * If the source is null, return an empty array.
-     * <p>
-     * This method is only supported with numbered arguments.  If
-     * the format pattern used named argument an
-     * IllegalArgumentException is thrown.
-     *
-     * @throws IllegalArgumentException if this format uses named arguments
-     * @stable ICU 3.0
-     */
-    public Object[] parse(String source, ParsePosition pos) {
-        return messageFormat.parse(source, pos);
-    }
-
-    /**
-     * {@icu} Parses the string, returning the results in a Map.
-     * This is similar to the version that returns an array
-     * of Object.  This supports both named and numbered
-     * arguments-- if numbered, the keys in the map are the
-     * corresponding Strings (e.g. "0", "1", "2"...).
-     *
-     * @param source the text to parse
-     * @param pos the position at which to start parsing.  on return,
-     *        contains the result of the parse.
-     * @return a Map containing key/value pairs for each parsed argument.
-     * @stable ICU 3.8
-     */
-    public Map<String, Object> parseToMap(String source, ParsePosition pos) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Parses text from the beginning of the given string to produce an object
-     * array.
-     * The method may not use the entire text of the given string.
-     * <p>
-     * See the {@link #parse(String, ParsePosition)} method for more information
-     * on message parsing.
-     *
-     * @param source A <code>String</code> whose beginning should be parsed.
-     * @return An <code>Object</code> array parsed from the string.
-     * @exception ParseException if the beginning of the specified string cannot be parsed.
-     * @exception IllegalArgumentException if this format uses named arguments
-     * @stable ICU 3.0
-     */
-    public Object[] parse(String source) throws ParseException {
-        return messageFormat.parse(source);
-    }
-
-    /**
-     * {@icu} Parses text from the beginning of the given string to produce a map from
-     * argument to values. The method may not use the entire text of the given string.
-     *
-     * <p>See the {@link #parse(String, ParsePosition)} method for more information on
-     * message parsing.
-     *
-     * @param source A <code>String</code> whose beginning should be parsed.
-     * @return A <code>Map</code> parsed from the string.
-     * @throws ParseException if the beginning of the specified string cannot
-     *         be parsed.
-     * @see #parseToMap(String, ParsePosition)
-     * @stable ICU 3.8
-     */
-    public Map<String, Object> parseToMap(String source) throws ParseException {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Parses text from a string to produce an object array or Map.
-     * <p>
-     * The method attempts to parse text starting at the index given by
-     * <code>pos</code>.
-     * If parsing succeeds, then the index of <code>pos</code> is updated
-     * to the index after the last character used (parsing does not necessarily
-     * use all characters up to the end of the string), and the parsed
-     * object array is returned. The updated <code>pos</code> can be used to
-     * indicate the starting point for the next call to this method.
-     * If an error occurs, then the index of <code>pos</code> is not
-     * changed, the error index of <code>pos</code> is set to the index of
-     * the character where the error occurred, and null is returned.
-     * <p>
-     * See the {@link #parse(String, ParsePosition)} method for more information
-     * on message parsing.
-     *
-     * @param source A <code>String</code>, part of which should be parsed.
-     * @param pos A <code>ParsePosition</code> object with index and error
-     *            index information as described above.
-     * @return An <code>Object</code> parsed from the string, either an
-     *         array of Object, or a Map, depending on whether named
-     *         arguments are used.  This can be queried using <code>usesNamedArguments</code>.
-     *         In case of error, returns null.
-     * @throws NullPointerException if <code>pos</code> is null.
-     * @stable ICU 3.0
-     */
-    public Object parseObject(String source, ParsePosition pos) {
-        return messageFormat.parse(source, pos);
-    }
-
-    /**
-     * Overrides clone.
-     *
-     * @return a clone of this instance.
-     * @stable ICU 3.0
-     */
-    public Object clone() {
-        MessageFormat fmt = new MessageFormat((java.text.MessageFormat)messageFormat.clone());
-        fmt.savedPattern = savedPattern;
-        return fmt;
-    }
-
-    /**
-     * Overrides equals.
-     * @stable ICU 3.0
-     */
-    public boolean equals(Object obj) {
-        try {
-            return messageFormat.equals(((MessageFormat)obj).messageFormat);
-        }
-        catch (Exception e) {
-            return false;
-        }
-    }
-
-    /**
-     * Overrides hashCode.
-     * @stable ICU 3.0
-     */
-    public int hashCode() {
-        return messageFormat.hashCode();
-    }
-
-    /**
-     * Defines constants that are used as attribute keys in the
-     * <code>AttributedCharacterIterator</code> returned
-     * from <code>MessageFormat.formatToCharacterIterator</code>.
-     *
-     * @stable ICU 3.8
-     */
-    public static class Field extends Format.Field {
-
-        private static final long serialVersionUID = 7510380454602616157L;
-
-        /**
-         * Create a <code>Field</code> with the specified name.
-         *
-         * @param name The name of the attribute
-         *
-         * @stable ICU 3.8
-         */
-        protected Field(String name) {
-            super(name);
-        }
-
-        /**
-         * Resolves instances being deserialized to the predefined constants.
-         *
-         * @return resolved MessageFormat.Field constant
-         * @throws InvalidObjectException if the constant could not be resolved.
-         *
-         * @stable ICU 3.8
-         */
-        protected Object readResolve() throws InvalidObjectException {
-            if (this.getClass() != MessageFormat.Field.class) {
-                throw new InvalidObjectException(
-                    "A subclass of MessageFormat.Field must implement readResolve.");
-            }
-            if (this.getName().equals(ARGUMENT.getName())) {
-                return ARGUMENT;
-            } else {
-                throw new InvalidObjectException("Unknown attribute name.");
-            }
-        }
-
-        /**
-         * Constant identifying a portion of a message that was generated
-         * from an argument passed into <code>formatToCharacterIterator</code>.
-         * The value associated with the key will be an <code>Integer</code>
-         * indicating the index in the <code>arguments</code> array of the
-         * argument from which the text was generated.
-         *
-         * @stable ICU 3.8
-         */
-        public static final Field ARGUMENT = new Field("message argument field");
-
-    }
-
-    private static final char SINGLE_QUOTE = '\'';
-    private static final char CURLY_BRACE_LEFT = '{';
-    private static final char CURLY_BRACE_RIGHT = '}';
-
-    private static final int STATE_INITIAL = 0;
-    private static final int STATE_SINGLE_QUOTE = 1;
-    private static final int STATE_IN_QUOTE = 2;
-    private static final int STATE_MSG_ELEMENT = 3;
-
-    /**
-     * {@icu} Converts an 'apostrophe-friendly' pattern into a standard
-     * pattern.  Standard patterns treat all apostrophes as
-     * quotes, which is problematic in some languages, e.g.
-     * French, where apostrophe is commonly used.  This utility
-     * assumes that only an unpaired apostrophe immediately before
-     * a brace is a true quote.  Other unpaired apostrophes are paired,
-     * and the resulting standard pattern string is returned.
-     *
-     * <p><b>Note</b> it is not guaranteed that the returned pattern
-     * is indeed a valid pattern.  The only effect is to convert
-     * between patterns having different quoting semantics.
-     *
-     * @param pattern the 'apostrophe-friendly' patttern to convert
-     * @return the standard equivalent of the original pattern
-     * @stable ICU 3.4
-     */
-    public static String autoQuoteApostrophe(String pattern) {
-        StringBuilder buf = new StringBuilder(pattern.length() * 2);
-        int state = STATE_INITIAL;
-        int braceCount = 0;
-        for (int i = 0, j = pattern.length(); i < j; ++i) {
-            char c = pattern.charAt(i);
-            switch (state) {
-            case STATE_INITIAL:
-                switch (c) {
-                case SINGLE_QUOTE:
-                    state = STATE_SINGLE_QUOTE;
-                    break;
-                case CURLY_BRACE_LEFT:
-                    state = STATE_MSG_ELEMENT;
-                    ++braceCount;
-                    break;
-                }
-                break;
-            case STATE_SINGLE_QUOTE:
-                switch (c) {
-                case SINGLE_QUOTE:
-                    state = STATE_INITIAL;
-                    break;
-                case CURLY_BRACE_LEFT:
-                case CURLY_BRACE_RIGHT:
-                    state = STATE_IN_QUOTE;
-                    break;
-                default:
-                    buf.append(SINGLE_QUOTE);
-                    state = STATE_INITIAL;
-                    break;
-                }
-                break;
-            case STATE_IN_QUOTE:
-                switch (c) {
-                case SINGLE_QUOTE:
-                    state = STATE_INITIAL;
-                    break;
-                }
-                break;
-            case STATE_MSG_ELEMENT:
-                switch (c) {
-                case CURLY_BRACE_LEFT:
-                    ++braceCount;
-                    break;
-                case CURLY_BRACE_RIGHT:
-                    if (--braceCount == 0) {
-                        state = STATE_INITIAL;
-                    }
-                    break;
-                }
-                break;
-            ///CLOVER:OFF
-            default: // Never happens.
-                break;
-            ///CLOVER:ON
-            }
-            buf.append(c);
-        }
-        // End of scan
-        if (state == STATE_SINGLE_QUOTE || state == STATE_IN_QUOTE) {
-            buf.append(SINGLE_QUOTE);
-        }
-        return new String(buf);
-    }
-
-    private static FieldPosition toJDKFieldPosition(FieldPosition icuPos) {
-        if (icuPos == null) {
-            return null;
-        }
-
-        int fieldID = icuPos.getField();
-        Format.Field fieldAttribute = icuPos.getFieldAttribute();
-
-        FieldPosition jdkPos = null;
-        if (fieldAttribute != null) {
-            // map field
-            if (fieldAttribute.equals(Field.ARGUMENT)) {
-                fieldAttribute = java.text.MessageFormat.Field.ARGUMENT;
-            }
-            jdkPos = new FieldPosition(fieldAttribute, fieldID);
-        } else {
-            jdkPos = new FieldPosition(fieldID);
-        }
-
-        jdkPos.setBeginIndex(icuPos.getBeginIndex());
-        jdkPos.setEndIndex(icuPos.getEndIndex());
-
-        return jdkPos;
-
-    }
-
-    private void wrapNestedFormatters(java.text.MessageFormat mfmt) {
-        // Update nested formatters created by Java MessageFormat
-        // with ICU versions, so FieldPosition / AttributedText will
-        // use ICU formatter's definition, such as com.ibm.icu.text.NumberFormat.INTEGER_FIELD
-
-        // Replacing nested formatter may change the pattern string
-        // originally used. For example, "{0,integer} files" is replaced
-        // with "{0} files". We preserve the original pattern.
-        savedPattern = mfmt.toPattern();
-
-        Format[] subfmts = mfmt.getFormats();
-        for (int i = 0; i < subfmts.length; i++) {
-            if (subfmts[i] instanceof java.text.DateFormat) {
-                subfmts[i] = new DateFormat((java.text.DateFormat)subfmts[i]);
-            } else if (subfmts[i] instanceof java.text.NumberFormat) {
-                subfmts[i] = new NumberFormat((java.text.NumberFormat)subfmts[i]);
-            }
-        }
-        mfmt.setFormats(subfmts);
-    }
-
-    private String savedPattern;
-}
+/*
+**********************************************************************
+* Copyright (c) 2004-2011, International Business Machines
+* Corporation and others.  All Rights Reserved.
+**********************************************************************
+* Author: Alan Liu
+* Created: April 6, 2004
+* Since: ICU 3.0
+**********************************************************************
+*/
+package com.ibm.icu.text;
+
+import java.io.InvalidObjectException;
+import java.text.AttributedCharacterIterator;
+import java.text.AttributedCharacterIterator.Attribute;
+import java.text.AttributedString;
+import java.text.CharacterIterator;
+import java.text.ChoiceFormat;
+import java.text.FieldPosition;
+import java.text.Format;
+import java.text.ParseException;
+import java.text.ParsePosition;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import com.ibm.icu.util.ULocale;
+
+/**
+ * {@icuenhanced java.text.MessageFormat}.{@icu _usage_}
+ *
+ * <p>MessageFormat produces concatenated messages in a language-neutral
+ * way. Use this whenever concatenating strings that are displayed to
+ * end users.
+ *
+ * <p>A MessageFormat contains an array of <em>subformats</em> arranged
+ * within a <em>template string</em>.  Together, the subformats and
+ * template string determine how the MessageFormat will operate during
+ * formatting and parsing.
+ *
+ * <p>Typically, both the subformats and the template string are
+ * specified at once in a <em>pattern</em>.  By using different
+ * patterns for different locales, messages may be localized.
+ *
+ * <p>When formatting, MessageFormat takes a collection of arguments
+ * and produces a user-readable string.  The arguments may be passed
+ * as an array or as a Map.  Each argument is matched up with its
+ * corresponding subformat, which then formats it into a string.  The
+ * resulting strings are then assembled within the string template of
+ * the MessageFormat to produce the final output string.
+ *
+ * <p><strong>Note:</strong>
+ * <code>MessageFormat</code> differs from the other <code>Format</code>
+ * classes in that you create a <code>MessageFormat</code> object with one
+ * of its constructors (not with a <code>getInstance</code> style factory
+ * method). The factory methods aren't necessary because <code>MessageFormat</code>
+ * itself doesn't implement locale-specific behavior. Any locale-specific
+ * behavior is defined by the pattern that you provide and the
+ * subformats used for inserted arguments.
+ *
+ * <p><strong>Note:</strong>
+ * In ICU 3.8 MessageFormat supports named arguments.  If a named argument
+ * is used, all arguments must be named.  Names start with a character in
+ * <code>:ID_START:</code> and continue with characters in <code>:ID_CONTINUE:</code>,
+ * in particular they do not start with a digit.  If named arguments
+ * are used, {@link #usesNamedArguments()} will return true.
+ *
+ * <p>The other new methods supporting named arguments are
+ * {@link #setFormatsByArgumentName(Map)},
+ * {@link #setFormatByArgumentName(String, Format)},
+ * {@link #format(Map, StringBuffer, FieldPosition)},
+ * {@link #format(String, Map)}, {@link #parseToMap(String, ParsePosition)},
+ * and {@link #parseToMap(String)}.  These methods are all compatible
+ * with patterns that do not used named arguments-- in these cases
+ * the keys in the input or output <code>Map</code>s use
+ * <code>String</code>s that name the argument indices, e.g. "0",
+ * "1", "2"... etc.
+ *
+ * <p>When named arguments are used, certain methods on MessageFormat that take or
+ * return arrays will throw an exception, since it is not possible to
+ * identify positions in an array using a name.  These methods are
+ * {@link #setFormatsByArgumentIndex(Format[])},
+ * {@link #setFormatByArgumentIndex(int, Format)},
+ * {@link #getFormatsByArgumentIndex()},
+ * {@link #getFormats()},
+ * {@link #format(Object[], StringBuffer, FieldPosition)},
+ * {@link #format(String, Object[])},
+ * {@link #parse(String, ParsePosition)}, and
+ * {@link #parse(String)}.
+ * These APIs all have corresponding new versions as listed above.
+ *
+ * <p>The API {@link #format(Object, StringBuffer, FieldPosition)} has
+ * been modified so that the <code>Object</code> argument can be
+ * either an <code>Object</code> array or a <code>Map</code>.  If this
+ * format uses named arguments, this argument must not be an
+ * <code>Object</code> array otherwise an exception will be thrown.
+ * If the argument is a <code>Map</code> it can be used with Strings that
+ * represent indices as described above.
+ *
+ * <h4><a name="patterns">Patterns and Their Interpretation</a></h4>
+ *
+ * <code>MessageFormat</code> uses patterns of the following form:
+ * <blockquote><pre>
+ * <i>MessageFormatPattern:</i>
+ *         <i>String</i>
+ *         <i>MessageFormatPattern</i> <i>FormatElement</i> <i>String</i>
+ *
+ * <i>FormatElement:</i>
+ *         { <i>ArgumentIndexOrName</i> }
+ *         { <i>ArgumentIndexOrName</i> , <i>FormatType</i> }
+ *         { <i>ArgumentIndexOrName</i> , <i>FormatType</i> , <i>FormatStyle</i> }
+ *
+ * <i>ArgumentIndexOrName: one of </i>
+ *         ['0'-'9']+
+ *         [:ID_START:][:ID_CONTINUE:]*
+ *
+ * <i>FormatType: one of </i>
+ *         number date time choice spellout ordinal duration plural
+ *
+ * <i>FormatStyle:</i>
+ *         short
+ *         medium
+ *         long
+ *         full
+ *         integer
+ *         currency
+ *         percent
+ *         <i>SubformatPattern</i>
+ *         <i>RulesetName</i>
+ *
+ * <i>String:</i>
+ *         <i>StringPart<sub>opt</sub></i>
+ *         <i>String</i> <i>StringPart</i>
+ *
+ * <i>StringPart:</i>
+ *         ''
+ *         ' <i>QuotedString</i> '
+ *         <i>UnquotedString</i>
+ *
+ * <i>SubformatPattern:</i>
+ *         <i>SubformatPatternPart<sub>opt</sub></i>
+ *         <i>SubformatPattern</i> <i>SubformatPatternPart</i>
+ *
+ * <i>SubFormatPatternPart:</i>
+ *         ' <i>QuotedPattern</i> '
+ *         <i>UnquotedPattern</i>
+ * </pre></blockquote>
+ *
+ * <i>RulesetName:</i>
+ *         <i>UnquotedString</i>
+ *
+ * <p>Within a <i>String</i>, <code>"''"</code> represents a single
+ * quote. A <i>QuotedString</i> can contain arbitrary characters
+ * except single quotes; the surrounding single quotes are removed.
+ * An <i>UnquotedString</i> can contain arbitrary characters
+ * except single quotes and left curly brackets. Thus, a string that
+ * should result in the formatted message "'{0}'" can be written as
+ * <code>"'''{'0}''"</code> or <code>"'''{0}'''"</code>.
+ *
+ * <p>Within a <i>SubformatPattern</i>, different rules apply.
+ * A <i>QuotedPattern</i> can contain arbitrary characters
+ * except single quotes; but the surrounding single quotes are
+ * <strong>not</strong> removed, so they may be interpreted by the
+ * subformat. For example, <code>"{1,number,$'#',##}"</code> will
+ * produce a number format with the pound-sign quoted, with a result
+ * such as: "$#31,45".
+ * An <i>UnquotedPattern</i> can contain arbitrary characters
+ * except single quotes, but curly braces within it must be balanced.
+ * For example, <code>"ab {0} de"</code> and <code>"ab '}' de"</code>
+ * are valid subformat patterns, but <code>"ab {0'}' de"</code> and
+ * <code>"ab } de"</code> are not.
+ *
+ * <p><dl><dt><b>Warning:</b><dd>The rules for using quotes within message
+ * format patterns unfortunately have shown to be somewhat confusing.
+ * In particular, it isn't always obvious to localizers whether single
+ * quotes need to be doubled or not. Make sure to inform localizers about
+ * the rules, and tell them (for example, by using comments in resource
+ * bundle source files) which strings will be processed by MessageFormat.
+ * Note that localizers may need to use single quotes in translated
+ * strings where the original version doesn't have them.
+ *
+ * <br>Note also that the simplest way to avoid the problem is to
+ * use the real apostrophe (single quote) character \u2019 (') for
+ * human-readable text, and to use the ASCII apostrophe (\u0027 ' )
+ * only in program syntax, like quoting in MessageFormat.
+ * See the annotations for U+0027 Apostrophe in The Unicode Standard.</p>
+ * </dl>
+ *
+ * <p>The <i>ArgumentIndex</i> value is a non-negative integer written
+ * using the digits '0' through '9', and represents an index into the
+ * <code>arguments</code> array passed to the <code>format</code> methods
+ * or the result array returned by the <code>parse</code> methods.
+ *
+ * <p>The <i>FormatType</i> and <i>FormatStyle</i> values are used to create
+ * a <code>Format</code> instance for the format element. The following
+ * table shows how the values map to Format instances. Combinations not
+ * shown in the table are illegal. A <i>SubformatPattern</i> must
+ * be a valid pattern string for the Format subclass used.
+ *
+ * <p><table border=1>
+ *    <tr>
+ *       <th>Format Type
+ *       <th>Format Style
+ *       <th>Subformat Created
+ *    <tr>
+ *       <td colspan=2><i>(none)</i>
+ *       <td><code>null</code>
+ *    <tr>
+ *       <td rowspan=5><code>number</code>
+ *       <td><i>(none)</i>
+ *       <td><code>NumberFormat.getInstance(getLocale())</code>
+ *    <tr>
+ *       <td><code>integer</code>
+ *       <td><code>NumberFormat.getIntegerInstance(getLocale())</code>
+ *    <tr>
+ *       <td><code>currency</code>
+ *       <td><code>NumberFormat.getCurrencyInstance(getLocale())</code>
+ *    <tr>
+ *       <td><code>percent</code>
+ *       <td><code>NumberFormat.getPercentInstance(getLocale())</code>
+ *    <tr>
+ *       <td><i>SubformatPattern</i>
+ *       <td><code>new DecimalFormat(subformatPattern, new DecimalFormatSymbols(getLocale()))</code>
+ *    <tr>
+ *       <td rowspan=6><code>date</code>
+ *       <td><i>(none)</i>
+ *       <td><code>DateFormat.getDateInstance(DateFormat.DEFAULT, getLocale())</code>
+ *    <tr>
+ *       <td><code>short</code>
+ *       <td><code>DateFormat.getDateInstance(DateFormat.SHORT, getLocale())</code>
+ *    <tr>
+ *       <td><code>medium</code>
+ *       <td><code>DateFormat.getDateInstance(DateFormat.DEFAULT, getLocale())</code>
+ *    <tr>
+ *       <td><code>long</code>
+ *       <td><code>DateFormat.getDateInstance(DateFormat.LONG, getLocale())</code>
+ *    <tr>
+ *       <td><code>full</code>
+ *       <td><code>DateFormat.getDateInstance(DateFormat.FULL, getLocale())</code>
+ *    <tr>
+ *       <td><i>SubformatPattern</i>
+ *       <td><code>new SimpleDateFormat(subformatPattern, getLocale())
+ *    <tr>
+ *       <td rowspan=6><code>time</code>
+ *       <td><i>(none)</i>
+ *       <td><code>DateFormat.getTimeInstance(DateFormat.DEFAULT, getLocale())</code>
+ *    <tr>
+ *       <td><code>short</code>
+ *       <td><code>DateFormat.getTimeInstance(DateFormat.SHORT, getLocale())</code>
+ *    <tr>
+ *       <td><code>medium</code>
+ *       <td><code>DateFormat.getTimeInstance(DateFormat.DEFAULT, getLocale())</code>
+ *    <tr>
+ *       <td><code>long</code>
+ *       <td><code>DateFormat.getTimeInstance(DateFormat.LONG, getLocale())</code>
+ *    <tr>
+ *       <td><code>full</code>
+ *       <td><code>DateFormat.getTimeInstance(DateFormat.FULL, getLocale())</code>
+ *    <tr>
+ *       <td><i>SubformatPattern</i>
+ *       <td><code>new SimpleDateFormat(subformatPattern, getLocale())
+ *    <tr>
+ *       <td><code>choice</code>
+ *       <td><i>SubformatPattern</i>
+ *       <td><code>new ChoiceFormat(subformatPattern)</code>
+ *    <tr>
+ *       <td><code>spellout</code>
+ *       <td><i>RulesetName (optional)</i>
+ *       <td><code>new RuleBasedNumberFormat(getLocale(), RuleBasedNumberFormat.SPELLOUT)
+ *           <br/>&nbsp;&nbsp;&nbsp;&nbsp;.setDefaultRuleset(ruleset);</code>
+ *    <tr>
+ *       <td><code>ordinal</code>
+ *       <td><i>RulesetName (optional)</i>
+ *       <td><code>new RuleBasedNumberFormat(getLocale(), RuleBasedNumberFormat.ORDINAL)
+ *           <br/>&nbsp;&nbsp;&nbsp;&nbsp;.setDefaultRuleset(ruleset);</code>
+ *    <tr>
+ *       <td><code>duration</code>
+ *       <td><i>RulesetName (optional)</i>
+ *       <td><code>new RuleBasedNumberFormat(getLocale(), RuleBasedNumberFormat.DURATION)
+ *           <br/>&nbsp;&nbsp;&nbsp;&nbsp;.setDefaultRuleset(ruleset);</code>
+ *    <tr>
+ *       <td><code>plural</code>
+ *       <td><i>SubformatPattern</i>
+ *       <td><code>new PluralFormat(subformatPattern)</code>
+ *    <tr>
+ *       <td><code>select</code>
+ *       <td><i>SubformatPattern</i>
+ *       <td><code>new SelectFormat(subformatPattern)</code>
+ * </table>
+ * <p>
+ *
+ * <h4>Usage Information</h4>
+ *
+ * <p>Here are some examples of usage:
+ * <blockquote>
+ * <pre>
+ * Object[] arguments = {
+ *     new Integer(7),
+ *     new Date(System.currentTimeMillis()),
+ *     "a disturbance in the Force"
+ * };
+ *
+ * String result = MessageFormat.format(
+ *     "At {1,time} on {1,date}, there was {2} on planet {0,number,integer}.",
+ *     arguments);
+ *
+ * <em>output</em>: At 12:30 PM on Jul 3, 2053, there was a disturbance
+ *           in the Force on planet 7.
+ *
+ * </pre>
+ * </blockquote>
+ * Typically, the message format will come from resources, and the
+ * arguments will be dynamically set at runtime.
+ *
+ * <p>Example 2:
+ * <blockquote>
+ * <pre>
+ * Object[] testArgs = {new Long(3), "MyDisk"};
+ *
+ * MessageFormat form = new MessageFormat(
+ *     "The disk \"{1}\" contains {0} file(s).");
+ *
+ * System.out.println(form.format(testArgs));
+ *
+ * // output, with different testArgs
+ * <em>output</em>: The disk "MyDisk" contains 0 file(s).
+ * <em>output</em>: The disk "MyDisk" contains 1 file(s).
+ * <em>output</em>: The disk "MyDisk" contains 1,273 file(s).
+ * </pre>
+ * </blockquote>
+ *
+ * <p>For more sophisticated patterns, you can use a <code>ChoiceFormat</code> to get
+ * output such as:
+ * <blockquote>
+ * <pre>
+ * MessageFormat form = new MessageFormat("The disk \"{1}\" contains {0}.");
+ * double[] filelimits = {0,1,2};
+ * String[] filepart = {"no files","one file","{0,number} files"};
+ * ChoiceFormat fileform = new ChoiceFormat(filelimits, filepart);
+ * form.setFormatByArgumentIndex(0, fileform);
+ *
+ * Object[] testArgs = {new Long(12373), "MyDisk"};
+ *
+ * System.out.println(form.format(testArgs));
+ *
+ * // output, with different testArgs
+ * output: The disk "MyDisk" contains no files.
+ * output: The disk "MyDisk" contains one file.
+ * output: The disk "MyDisk" contains 1,273 files.
+ * </pre>
+ * </blockquote>
+ * You can either do this programmatically, as in the above example,
+ * or by using a pattern (see
+ * {@link ChoiceFormat}
+ * for more information) as in:
+ * <blockquote>
+ * <pre>
+ * form.applyPattern(
+ *    "There {0,choice,0#are no files|1#is one file|1&lt;are {0,number,integer} files}.");
+ * </pre>
+ * </blockquote>
+ *
+ * <p><strong>Note:</strong> As we see above, the string produced
+ * by a <code>ChoiceFormat</code> in <code>MessageFormat</code> is treated specially;
+ * occurances of '{' are used to indicated subformats, and cause recursion.
+ * If you create both a <code>MessageFormat</code> and <code>ChoiceFormat</code>
+ * programmatically (instead of using the string patterns), then be careful not to
+ * produce a format that recurses on itself, which will cause an infinite loop.
+ *
+ * <p>When a single argument is parsed more than once in the string, the last match
+ * will be the final result of the parsing.  For example,
+ * <pre>
+ * MessageFormat mf = new MessageFormat("{0,number,#.##}, {0,number,#.#}");
+ * Object[] objs = {new Double(3.1415)};
+ * String result = mf.format( objs );
+ * // result now equals "3.14, 3.1"
+ * objs = null;
+ * objs = mf.parse(result, new ParsePosition(0));
+ * // objs now equals {new Double(3.1)}
+ * </pre>
+ *
+ * <p>Likewise, parsing with a MessageFormat object using patterns containing
+ * multiple occurances of the same argument would return the last match.  For
+ * example,
+ * <pre>
+ * MessageFormat mf = new MessageFormat("{0}, {0}, {0}");
+ * String forParsing = "x, y, z";
+ * Object[] objs = mf.parse(forParsing, new ParsePosition(0));
+ * // result now equals {new String("z")}
+ * </pre>
+ *
+ * <h4><a name="synchronization">Synchronization</a></h4>
+ *
+ * <p>Message formats are not synchronized.
+ * It is recommended to create separate format instances for each thread.
+ * If multiple threads access a format concurrently, it must be synchronized
+ * externally.
+ *
+ * @see          java.util.Locale
+ * @see          Format
+ * @see          NumberFormat
+ * @see          DecimalFormat
+ * @see          ChoiceFormat
+ * @see          PluralFormat
+ * @see          SelectFormat
+ * @author       Mark Davis
+ * @stable ICU 3.0
+ */
+public class MessageFormat extends UFormat {
+    static final long serialVersionUID = 1L;
+
+    /**
+     * @internal
+     */
+    public final java.text.MessageFormat messageFormat;
+        
+    /**
+     * @internal
+     * @param delegate the DateFormat to which to delegate
+     */
+    public MessageFormat(java.text.MessageFormat delegate) {
+        wrapNestedFormatters(delegate);
+        this.messageFormat = delegate;
+    }
+
+    /**
+     * Constructs a MessageFormat for the default locale and the
+     * specified pattern.
+     * The constructor first sets the locale, then parses the pattern and
+     * creates a list of subformats for the format elements contained in it.
+     * Patterns and their interpretation are specified in the
+     * <a href="#patterns">class description</a>.
+     *
+     * @param pattern the pattern for this message format
+     * @exception IllegalArgumentException if the pattern is invalid
+     * @stable ICU 3.0
+     */
+    public MessageFormat(String pattern) {
+        this(new java.text.MessageFormat(pattern));
+    }
+
+    /**
+     * Constructs a MessageFormat for the specified locale and
+     * pattern.
+     * The constructor first sets the locale, then parses the pattern and
+     * creates a list of subformats for the format elements contained in it.
+     * Patterns and their interpretation are specified in the
+     * <a href="#patterns">class description</a>.
+     *
+     * @param pattern the pattern for this message format
+     * @param locale the locale for this message format
+     * @exception IllegalArgumentException if the pattern is invalid
+     * @stable ICU 3.0
+     */
+    public MessageFormat(String pattern, Locale locale) {
+        this(new java.text.MessageFormat(pattern, locale));
+    }
+
+    /**
+     * Constructs a MessageFormat for the specified locale and
+     * pattern.
+     * The constructor first sets the locale, then parses the pattern and
+     * creates a list of subformats for the format elements contained in it.
+     * Patterns and their interpretation are specified in the
+     * <a href="#patterns">class description</a>.
+     *
+     * @param pattern the pattern for this message format
+     * @param locale the locale for this message format
+     * @exception IllegalArgumentException if the pattern is invalid
+     * @stable ICU 3.2
+     */
+    public MessageFormat(String pattern, ULocale locale) {
+        this(new java.text.MessageFormat(pattern, locale.toLocale()));
+    }
+
+    /**
+     * Sets the locale to be used when creating or comparing subformats.
+     * This affects subsequent calls to the {@link #applyPattern applyPattern}
+     * and {@link #toPattern toPattern} methods as well as to the
+     * <code>format</code> and
+     * {@link #formatToCharacterIterator formatToCharacterIterator} methods.
+     *
+     * @param locale the locale to be used when creating or comparing subformats
+     * @stable ICU 3.0
+     */
+    public void setLocale(Locale locale) {
+        messageFormat.setLocale(locale);
+    }
+
+    /**
+     * Sets the locale to be used when creating or comparing subformats.
+     * This affects subsequent calls to the {@link #applyPattern applyPattern}
+     * and {@link #toPattern toPattern} methods as well as to the
+     * <code>format</code> and
+     * {@link #formatToCharacterIterator formatToCharacterIterator} methods.
+     *
+     * @param locale the locale to be used when creating or comparing subformats
+     * @stable ICU 3.2
+     */
+    public void setLocale(ULocale locale) {
+        messageFormat.setLocale(locale.toLocale());
+    }
+
+    /**
+     * Returns the locale that's used when creating or comparing subformats.
+     *
+     * @return the locale used when creating or comparing subformats
+     * @stable ICU 3.0
+     */
+    public Locale getLocale() {
+        return messageFormat.getLocale();
+    }
+
+    /**
+     * {@icu} Returns the locale that's used when creating or comparing subformats.
+     *
+     * @return the locale used when creating or comparing subformats
+     * @stable ICU 3.2
+     */
+    public ULocale getULocale() {
+        return ULocale.forLocale(messageFormat.getLocale());
+    }
+
+    /**
+     * Sets the pattern used by this message format.
+     * The method parses the pattern and creates a list of subformats
+     * for the format elements contained in it.
+     * Patterns and their interpretation are specified in the
+     * <a href="#patterns">class description</a>.
+     * <p>
+     * The pattern must contain only named or only numeric arguments,
+     * mixing them is not allowed.
+     *
+     * @param pttrn the pattern for this message format
+     * @throws IllegalArgumentException if the pattern is invalid
+     * @stable ICU 3.0
+     */
+    public void applyPattern(String pttrn) {
+        messageFormat.applyPattern(pttrn);
+        wrapNestedFormatters(messageFormat);
+    }
+
+    /**
+     * Returns a pattern representing the current state of the message format.
+     * The string is constructed from internal information and therefore
+     * does not necessarily equal the previously applied pattern.
+     *
+     * @return a pattern representing the current state of the message format
+     * @stable ICU 3.0
+     */
+    public String toPattern() {
+        String pattern = savedPattern == null ? messageFormat.toPattern() : savedPattern;
+        return pattern;
+    }
+
+    /**
+     * Sets the formats to use for the values passed into
+     * <code>format</code> methods or returned from <code>parse</code>
+     * methods. The indices of elements in <code>newFormats</code>
+     * correspond to the argument indices used in the previously set
+     * pattern string.
+     * The order of formats in <code>newFormats</code> thus corresponds to
+     * the order of elements in the <code>arguments</code> array passed
+     * to the <code>format</code> methods or the result array returned
+     * by the <code>parse</code> methods.
+     * <p>
+     * If an argument index is used for more than one format element
+     * in the pattern string, then the corresponding new format is used
+     * for all such format elements. If an argument index is not used
+     * for any format element in the pattern string, then the
+     * corresponding new format is ignored. If fewer formats are provided
+     * than needed, then only the formats for argument indices less
+     * than <code>newFormats.length</code> are replaced.
+     *
+     * This method is only supported if the format does not use
+     * named arguments, otherwise an IllegalArgumentException is thrown.
+     *
+     * @param newFormats the new formats to use
+     * @throws NullPointerException if <code>newFormats</code> is null
+     * @throws IllegalArgumentException if this formatter uses named arguments
+     * @stable ICU 3.0
+     */
+    public void setFormatsByArgumentIndex(Format[] newFormats) {
+        messageFormat.setFormatsByArgumentIndex(newFormats);
+        savedPattern = null;
+    }
+
+    /**
+     * {@icu} Sets the formats to use for the values passed into
+     * <code>format</code> methods or returned from <code>parse</code>
+     * methods. The keys in <code>newFormats</code> are the argument
+     * names in the previously set pattern string, and the values
+     * are the formats.
+     * <p>
+     * Only argument names from the pattern string are considered.
+     * Extra keys in <code>newFormats</code> that do not correspond
+     * to an argument name are ignored.  Similarly, if there is no
+     * format in newFormats for an argument name, the formatter
+     * for that argument remains unchanged.
+     * <p>
+     * This may be called on formats that do not use named arguments.
+     * In this case the map will be queried for key Strings that
+     * represent argument indices, e.g. "0", "1", "2" etc.
+     *
+     * @param newFormats a map from String to Format providing new
+     *        formats for named arguments.
+     * @stable ICU 3.8
+     */
+    public void setFormatsByArgumentName(Map<String, Format> newFormats) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Sets the formats to use for the format elements in the
+     * previously set pattern string.
+     * The order of formats in <code>newFormats</code> corresponds to
+     * the order of format elements in the pattern string.
+     * <p>
+     * If more formats are provided than needed by the pattern string,
+     * the remaining ones are ignored. If fewer formats are provided
+     * than needed, then only the first <code>newFormats.length</code>
+     * formats are replaced.
+     * <p>
+     * Since the order of format elements in a pattern string often
+     * changes during localization, it is generally better to use the
+     * {@link #setFormatsByArgumentIndex setFormatsByArgumentIndex}
+     * method, which assumes an order of formats corresponding to the
+     * order of elements in the <code>arguments</code> array passed to
+     * the <code>format</code> methods or the result array returned by
+     * the <code>parse</code> methods.
+     *
+     * @param newFormats the new formats to use
+     * @exception NullPointerException if <code>newFormats</code> is null
+     * @stable ICU 3.0
+     */
+    public void setFormats(Format[] newFormats) {
+        messageFormat.setFormats(newFormats);
+        savedPattern = null;
+    }
+
+    /**
+     * Sets the format to use for the format elements within the
+     * previously set pattern string that use the given argument
+     * index.
+     * The argument index is part of the format element definition and
+     * represents an index into the <code>arguments</code> array passed
+     * to the <code>format</code> methods or the result array returned
+     * by the <code>parse</code> methods.
+     * <p>
+     * If the argument index is used for more than one format element
+     * in the pattern string, then the new format is used for all such
+     * format elements. If the argument index is not used for any format
+     * element in the pattern string, then the new format is ignored.
+     *
+     * This method is only supported when exclusively numbers are used for
+     * argument names. Otherwise an IllegalArgumentException is thrown.
+     *
+     * @param argumentIndex the argument index for which to use the new format
+     * @param newFormat the new format to use
+     * @throws IllegalArgumentException if this format uses named arguments
+     * @stable ICU 3.0
+     */
+    public void setFormatByArgumentIndex(int argumentIndex, Format newFormat) {
+        messageFormat.setFormatByArgumentIndex(argumentIndex, newFormat);
+        savedPattern = null;
+    }
+
+    /**
+     * {@icu} Sets the format to use for the format elements within the
+     * previously set pattern string that use the given argument
+     * name.
+     * <p>
+     * If the argument name is used for more than one format element
+     * in the pattern string, then the new format is used for all such
+     * format elements. If the argument name is not used for any format
+     * element in the pattern string, then the new format is ignored.
+     * <p>
+     * This API may be used on formats that do not use named arguments.
+     * In this case <code>argumentName</code> should be a String that names
+     * an argument index, e.g. "0", "1", "2"... etc.  If it does not name
+     * a valid index, the format will be ignored.  No error is thrown.
+     *
+     * @param argumentName the name of the argument to change
+     * @param newFormat the new format to use
+     * @stable ICU 3.8
+     */
+    public void setFormatByArgumentName(String argumentName, Format newFormat) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Sets the format to use for the format element with the given
+     * format element index within the previously set pattern string.
+     * The format element index is the zero-based number of the format
+     * element counting from the start of the pattern string.
+     * <p>
+     * Since the order of format elements in a pattern string often
+     * changes during localization, it is generally better to use the
+     * {@link #setFormatByArgumentIndex setFormatByArgumentIndex}
+     * method, which accesses format elements based on the argument
+     * index they specify.
+     *
+     * @param formatElementIndex the index of a format element within the pattern
+     * @param newFormat the format to use for the specified format element
+     * @exception ArrayIndexOutOfBoundsException if formatElementIndex is equal to or
+     *            larger than the number of format elements in the pattern string
+     * @stable ICU 3.0
+     */
+    public void setFormat(int formatElementIndex, Format newFormat) {
+        messageFormat.setFormat(formatElementIndex, newFormat);
+        savedPattern = null;
+    }
+
+    /**
+     * Returns the formats used for the values passed into
+     * <code>format</code> methods or returned from <code>parse</code>
+     * methods. The indices of elements in the returned array
+     * correspond to the argument indices used in the previously set
+     * pattern string.
+     * The order of formats in the returned array thus corresponds to
+     * the order of elements in the <code>arguments</code> array passed
+     * to the <code>format</code> methods or the result array returned
+     * by the <code>parse</code> methods.
+     * <p>
+     * If an argument index is used for more than one format element
+     * in the pattern string, then the format used for the last such
+     * format element is returned in the array. If an argument index
+     * is not used for any format element in the pattern string, then
+     * null is returned in the array.
+     *
+     * This method is only supported when exclusively numbers are used for
+     * argument names. Otherwise an IllegalArgumentException is thrown.
+     *
+     * @return the formats used for the arguments within the pattern
+     * @throws IllegalArgumentException if this format uses named arguments
+     * @stable ICU 3.0
+     */
+    public Format[] getFormatsByArgumentIndex() {
+        return messageFormat.getFormatsByArgumentIndex();
+    }
+
+    /**
+     * Returns the formats used for the format elements in the
+     * previously set pattern string.
+     * The order of formats in the returned array corresponds to
+     * the order of format elements in the pattern string.
+     * <p>
+     * Since the order of format elements in a pattern string often
+     * changes during localization, it's generally better to use the
+     * {@link #getFormatsByArgumentIndex()}
+     * method, which assumes an order of formats corresponding to the
+     * order of elements in the <code>arguments</code> array passed to
+     * the <code>format</code> methods or the result array returned by
+     * the <code>parse</code> methods.
+     *
+     * This method is only supported when exclusively numbers are used for
+     * argument names. Otherwise an IllegalArgumentException is thrown.
+     *
+     * @return the formats used for the format elements in the pattern
+     * @throws IllegalArgumentException if this format uses named arguments
+     * @stable ICU 3.0
+     */
+    public Format[] getFormats() {
+        return messageFormat.getFormats();
+    }
+
+    /**
+     * {@icu} Returns the format argument names. For more details, see
+     * {@link #setFormatByArgumentName(String, Format)}.
+     * @return List of names
+     * @internal
+     * @deprecated This API is ICU internal only.
+     */
+    public Set<String> getFormatArgumentNames() {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Returns the formats according to their argument names. For more details, see
+     * {@link #setFormatByArgumentName(String, Format)}.
+     * @return format associated with the name, or null if there isn't one.
+     * @internal
+     * @deprecated This API is ICU internal only.
+     */
+    public Format getFormatByArgumentName(String argumentName) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Formats an array of objects and appends the <code>MessageFormat</code>'s
+     * pattern, with format elements replaced by the formatted objects, to the
+     * provided <code>StringBuffer</code>.
+     * <p>
+     * The text substituted for the individual format elements is derived from
+     * the current subformat of the format element and the
+     * <code>arguments</code> element at the format element's argument index
+     * as indicated by the first matching line of the following table. An
+     * argument is <i>unavailable</i> if <code>arguments</code> is
+     * <code>null</code> or has fewer than argumentIndex+1 elements.  When
+     * an argument is unavailable no substitution is performed.
+     * <p>
+     * <table border=1>
+     *    <tr>
+     *       <th>Subformat
+     *       <th>Argument
+     *       <th>Formatted Text
+     *    <tr>
+     *       <td><i>any</i>
+     *       <td><i>unavailable</i>
+     *       <td><code>"{" + argumentIndex + "}"</code>
+     *    <tr>
+     *       <td><i>any</i>
+     *       <td><code>null</code>
+     *       <td><code>"null"</code>
+     *    <tr>
+     *       <td><code>instanceof ChoiceFormat</code>
+     *       <td><i>any</i>
+     *       <td><code>subformat.format(argument).indexOf('{') >= 0 ?<br>
+     *           (new MessageFormat(subformat.format(argument), getLocale())).format(argument) :
+     *           subformat.format(argument)</code>
+     *    <tr>
+     *       <td><code>!= null</code>
+     *       <td><i>any</i>
+     *       <td><code>subformat.format(argument)</code>
+     *    <tr>
+     *       <td><code>null</code>
+     *       <td><code>instanceof Number</code>
+     *       <td><code>NumberFormat.getInstance(getLocale()).format(argument)</code>
+     *    <tr>
+     *       <td><code>null</code>
+     *       <td><code>instanceof Date</code>
+     *       <td><code>DateFormat.getDateTimeInstance(DateFormat.SHORT,
+     *           DateFormat.SHORT, getLocale()).format(argument)</code>
+     *    <tr>
+     *       <td><code>null</code>
+     *       <td><code>instanceof String</code>
+     *       <td><code>argument</code>
+     *    <tr>
+     *       <td><code>null</code>
+     *       <td><i>any</i>
+     *       <td><code>argument.toString()</code>
+     * </table>
+     * <p>
+     * If <code>pos</code> is non-null, and refers to
+     * <code>Field.ARGUMENT</code>, the location of the first formatted
+     * string will be returned.
+     *
+     * This method is only supported when the format does not use named
+     * arguments, otherwise an IllegalArgumentException is thrown.
+     *
+     * @param arguments an array of objects to be formatted and substituted.
+     * @param result where text is appended.
+     * @param pos On input: an alignment field, if desired.
+     *            On output: the offsets of the alignment field.
+     * @throws IllegalArgumentException if an argument in the
+     *            <code>arguments</code> array is not of the type
+     *            expected by the format element(s) that use it.
+     * @throws IllegalArgumentException if this format uses named arguments
+     * @stable ICU 3.0
+     */
+    public final StringBuffer format(Object[] arguments, StringBuffer result,
+                                     FieldPosition pos) {
+        FieldPosition jdkPos = toJDKFieldPosition(pos);
+        StringBuffer buf = messageFormat.format(arguments, result, jdkPos);
+        if (jdkPos != null) {
+            pos.setBeginIndex(jdkPos.getBeginIndex());
+            pos.setEndIndex(jdkPos.getEndIndex());
+        }
+        return buf;
+    }
+
+    /**
+     * Formats a map of objects and appends the <code>MessageFormat</code>'s
+     * pattern, with format elements replaced by the formatted objects, to the
+     * provided <code>StringBuffer</code>.
+     * <p>
+     * The text substituted for the individual format elements is derived from
+     * the current subformat of the format element and the
+     * <code>arguments</code> value corresopnding to the format element's
+     * argument name.
+     * <p>
+     * This API may be called on formats that do not use named arguments.
+     * In this case the the keys in <code>arguments</code> must be numeric
+     * strings (e.g. "0", "1", "2"...).
+     * <p>
+     * An argument is <i>unavailable</i> if <code>arguments</code> is
+     * <code>null</code> or does not have a value corresponding to an argument
+     * name in the pattern.  When an argument is unavailable no substitution
+     * is performed.
+     *
+     * @param arguments a map of objects to be formatted and substituted.
+     * @param result where text is appended.
+     * @param pos On input: an alignment field, if desired.
+     *            On output: the offsets of the alignment field.
+     * @throws IllegalArgumentException if an argument in the
+     *         <code>arguments</code> array is not of the type
+     *         expected by the format element(s) that use it.
+     * @return the passed-in StringBuffer
+     * @stable ICU 3.8
+     */
+    public final StringBuffer format(Map<String, Object> arguments, StringBuffer result,
+                                     FieldPosition pos) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Creates a MessageFormat with the given pattern and uses it
+     * to format the given arguments. This is equivalent to
+     * <blockquote>
+     *     <code>(new {@link #MessageFormat(String) MessageFormat}(pattern)).{@link
+     *     #format(java.lang.Object[], java.lang.StringBuffer, java.text.FieldPosition)
+     *     format}(arguments, new StringBuffer(), null).toString()</code>
+     * </blockquote>
+     *
+     * @throws IllegalArgumentException if the pattern is invalid,
+     *            or if an argument in the <code>arguments</code> array
+     *            is not of the type expected by the format element(s)
+     *            that use it.
+     * @throws IllegalArgumentException if this format uses named arguments
+     * @stable ICU 3.0
+     */
+    public static String format(String pattern, Object... arguments) {
+        return java.text.MessageFormat.format(pattern, arguments);
+    }
+
+    /**
+     * Creates a MessageFormat with the given pattern and uses it to
+     * format the given arguments.  The pattern must identifyarguments
+     * by name instead of by number.
+     * <p>
+     * @throws IllegalArgumentException if the pattern is invalid,
+     *         or if an argument in the <code>arguments</code> map
+     *         is not of the type expected by the format element(s)
+     *         that use it.
+     * @see #format(Map, StringBuffer, FieldPosition)
+     * @see #format(String, Object[])
+     * @stable ICU 3.8
+     */
+    public static String format(String pattern, Map<String, Object> arguments) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Returns true if this MessageFormat uses named arguments,
+     * and false otherwise.  See class description.
+     *
+     * @return true if named arguments are used.
+     * @stable ICU 3.8
+     */
+    public boolean usesNamedArguments() {
+        // always false with com.ibm.icu.base
+        return false;
+    }
+
+    // Overrides
+    /**
+     * Formats a map or array of objects and appends the <code>MessageFormat</code>'s
+     * pattern, with format elements replaced by the formatted objects, to the
+     * provided <code>StringBuffer</code>.
+     * This is equivalent to either of
+     * <blockquote>
+     *     <code>{@link #format(java.lang.Object[], java.lang.StringBuffer,
+     *     java.text.FieldPosition) format}((Object[]) arguments, result, pos)</code>
+     *     <code>{@link #format(java.util.Map, java.lang.StringBuffer,
+     *     java.text.FieldPosition) format}((Map) arguments, result, pos)</code>
+     * </blockquote>
+     * A map must be provided if this format uses named arguments, otherwise
+     * an IllegalArgumentException will be thrown.
+     * @param arguments a map or array of objects to be formatted
+     * @param result where text is appended
+     * @param pos On input: an alignment field, if desired
+     *            On output: the offsets of the alignment field
+     * @throws IllegalArgumentException if an argument in
+     *         <code>arguments</code> is not of the type
+     *         expected by the format element(s) that use it
+     * @throws IllegalArgumentException if <code>arguments<code> is
+     *         an array of Object and this format uses named arguments
+     * @stable ICU 3.0
+     */
+    public final StringBuffer format(Object arguments, StringBuffer result,
+                                     FieldPosition pos) {
+        FieldPosition jdkPos = toJDKFieldPosition(pos);
+        StringBuffer buf = messageFormat.format(arguments, result, jdkPos);
+        if (jdkPos != null) {
+            pos.setBeginIndex(jdkPos.getBeginIndex());
+            pos.setEndIndex(jdkPos.getEndIndex());
+        }
+        return buf;
+    }
+
+    /**
+     * Formats an array of objects and inserts them into the
+     * <code>MessageFormat</code>'s pattern, producing an
+     * <code>AttributedCharacterIterator</code>.
+     * You can use the returned <code>AttributedCharacterIterator</code>
+     * to build the resulting String, as well as to determine information
+     * about the resulting String.
+     * <p>
+     * The text of the returned <code>AttributedCharacterIterator</code> is
+     * the same that would be returned by
+     * <blockquote>
+     *     <code>{@link #format(java.lang.Object[], java.lang.StringBuffer,
+     *     java.text.FieldPosition) format}(arguments, new StringBuffer(), null).toString()</code>
+     * </blockquote>
+     * <p>
+     * In addition, the <code>AttributedCharacterIterator</code> contains at
+     * least attributes indicating where text was generated from an
+     * argument in the <code>arguments</code> array. The keys of these attributes are of
+     * type <code>MessageFormat.Field</code>, their values are
+     * <code>Integer</code> objects indicating the index in the <code>arguments</code>
+     * array of the argument from which the text was generated.
+     * <p>
+     * The attributes/value from the underlying <code>Format</code>
+     * instances that <code>MessageFormat</code> uses will also be
+     * placed in the resulting <code>AttributedCharacterIterator</code>.
+     * This allows you to not only find where an argument is placed in the
+     * resulting String, but also which fields it contains in turn.
+     *
+     * @param arguments an array of objects to be formatted and substituted.
+     * @return AttributedCharacterIterator describing the formatted value.
+     * @exception NullPointerException if <code>arguments</code> is null.
+     * @exception IllegalArgumentException if an argument in the
+     *            <code>arguments</code> array is not of the type
+     *            expected by the format element(s) that use it.
+     * @stable ICU 3.8
+     */
+    public AttributedCharacterIterator formatToCharacterIterator(Object arguments) {
+        AttributedCharacterIterator it = messageFormat.formatToCharacterIterator(arguments);
+
+        // Extract formatted String first
+        StringBuilder sb = new StringBuilder();
+        for (char c = it.first(); c != CharacterIterator.DONE; c = it.next()) {
+            sb.append(c);
+        }
+
+        // Create AttributedString
+        AttributedString attrstr = new AttributedString(sb.toString());
+
+        // Map JDK Field to ICU Field
+        int idx = 0;
+        it.first();
+        while (idx < it.getEndIndex()) {
+            int end = it.getRunLimit();
+            Map<Attribute, Object> attributes = it.getAttributes();
+            if (attributes != null) {
+                for (Entry<Attribute, Object> entry : attributes.entrySet()) {
+                    Attribute attr = entry.getKey();
+                    Object val = entry.getValue();
+                    if (attr.equals(java.text.MessageFormat.Field.ARGUMENT)) {
+                        val = attr = Field.ARGUMENT;
+                    }
+                    attrstr.addAttribute(attr, val, idx, end);
+                }
+            }
+            idx = end;
+            while (it.getIndex() < idx) {
+                it.next();
+            }
+        }
+
+        return attrstr.getIterator();
+    }
+
+    /**
+     * Parses the string.
+     *
+     * <p>Caveats: The parse may fail in a number of circumstances.
+     * For example:
+     * <ul>
+     * <li>If one of the arguments does not occur in the pattern.
+     * <li>If the format of an argument loses information, such as
+     *     with a choice format where a large number formats to "many".
+     * <li>Does not yet handle recursion (where
+     *     the substituted strings contain {n} references.)
+     * <li>Will not always find a match (or the correct match)
+     *     if some part of the parse is ambiguous.
+     *     For example, if the pattern "{1},{2}" is used with the
+     *     string arguments {"a,b", "c"}, it will format as "a,b,c".
+     *     When the result is parsed, it will return {"a", "b,c"}.
+     * <li>If a single argument is parsed more than once in the string,
+     *     then the later parse wins.
+     * </ul>
+     * When the parse fails, use ParsePosition.getErrorIndex() to find out
+     * where in the string did the parsing failed. The returned error
+     * index is the starting offset of the sub-patterns that the string
+     * is comparing with. For example, if the parsing string "AAA {0} BBB"
+     * is comparing against the pattern "AAD {0} BBB", the error index is
+     * 0. When an error occurs, the call to this method will return null.
+     * If the source is null, return an empty array.
+     * <p>
+     * This method is only supported with numbered arguments.  If
+     * the format pattern used named argument an
+     * IllegalArgumentException is thrown.
+     *
+     * @throws IllegalArgumentException if this format uses named arguments
+     * @stable ICU 3.0
+     */
+    public Object[] parse(String source, ParsePosition pos) {
+        return messageFormat.parse(source, pos);
+    }
+
+    /**
+     * {@icu} Parses the string, returning the results in a Map.
+     * This is similar to the version that returns an array
+     * of Object.  This supports both named and numbered
+     * arguments-- if numbered, the keys in the map are the
+     * corresponding Strings (e.g. "0", "1", "2"...).
+     *
+     * @param source the text to parse
+     * @param pos the position at which to start parsing.  on return,
+     *        contains the result of the parse.
+     * @return a Map containing key/value pairs for each parsed argument.
+     * @stable ICU 3.8
+     */
+    public Map<String, Object> parseToMap(String source, ParsePosition pos) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Parses text from the beginning of the given string to produce an object
+     * array.
+     * The method may not use the entire text of the given string.
+     * <p>
+     * See the {@link #parse(String, ParsePosition)} method for more information
+     * on message parsing.
+     *
+     * @param source A <code>String</code> whose beginning should be parsed.
+     * @return An <code>Object</code> array parsed from the string.
+     * @exception ParseException if the beginning of the specified string cannot be parsed.
+     * @exception IllegalArgumentException if this format uses named arguments
+     * @stable ICU 3.0
+     */
+    public Object[] parse(String source) throws ParseException {
+        return messageFormat.parse(source);
+    }
+
+    /**
+     * {@icu} Parses text from the beginning of the given string to produce a map from
+     * argument to values. The method may not use the entire text of the given string.
+     *
+     * <p>See the {@link #parse(String, ParsePosition)} method for more information on
+     * message parsing.
+     *
+     * @param source A <code>String</code> whose beginning should be parsed.
+     * @return A <code>Map</code> parsed from the string.
+     * @throws ParseException if the beginning of the specified string cannot
+     *         be parsed.
+     * @see #parseToMap(String, ParsePosition)
+     * @stable ICU 3.8
+     */
+    public Map<String, Object> parseToMap(String source) throws ParseException {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Parses text from a string to produce an object array or Map.
+     * <p>
+     * The method attempts to parse text starting at the index given by
+     * <code>pos</code>.
+     * If parsing succeeds, then the index of <code>pos</code> is updated
+     * to the index after the last character used (parsing does not necessarily
+     * use all characters up to the end of the string), and the parsed
+     * object array is returned. The updated <code>pos</code> can be used to
+     * indicate the starting point for the next call to this method.
+     * If an error occurs, then the index of <code>pos</code> is not
+     * changed, the error index of <code>pos</code> is set to the index of
+     * the character where the error occurred, and null is returned.
+     * <p>
+     * See the {@link #parse(String, ParsePosition)} method for more information
+     * on message parsing.
+     *
+     * @param source A <code>String</code>, part of which should be parsed.
+     * @param pos A <code>ParsePosition</code> object with index and error
+     *            index information as described above.
+     * @return An <code>Object</code> parsed from the string, either an
+     *         array of Object, or a Map, depending on whether named
+     *         arguments are used.  This can be queried using <code>usesNamedArguments</code>.
+     *         In case of error, returns null.
+     * @throws NullPointerException if <code>pos</code> is null.
+     * @stable ICU 3.0
+     */
+    public Object parseObject(String source, ParsePosition pos) {
+        return messageFormat.parse(source, pos);
+    }
+
+    /**
+     * Overrides clone.
+     *
+     * @return a clone of this instance.
+     * @stable ICU 3.0
+     */
+    public Object clone() {
+        MessageFormat fmt = new MessageFormat((java.text.MessageFormat)messageFormat.clone());
+        fmt.savedPattern = savedPattern;
+        return fmt;
+    }
+
+    /**
+     * Overrides equals.
+     * @stable ICU 3.0
+     */
+    public boolean equals(Object obj) {
+        try {
+            return messageFormat.equals(((MessageFormat)obj).messageFormat);
+        }
+        catch (Exception e) {
+            return false;
+        }
+    }
+
+    /**
+     * Overrides hashCode.
+     * @stable ICU 3.0
+     */
+    public int hashCode() {
+        return messageFormat.hashCode();
+    }
+
+    /**
+     * Defines constants that are used as attribute keys in the
+     * <code>AttributedCharacterIterator</code> returned
+     * from <code>MessageFormat.formatToCharacterIterator</code>.
+     *
+     * @stable ICU 3.8
+     */
+    public static class Field extends Format.Field {
+
+        private static final long serialVersionUID = 7510380454602616157L;
+
+        /**
+         * Create a <code>Field</code> with the specified name.
+         *
+         * @param name The name of the attribute
+         *
+         * @stable ICU 3.8
+         */
+        protected Field(String name) {
+            super(name);
+        }
+
+        /**
+         * Resolves instances being deserialized to the predefined constants.
+         *
+         * @return resolved MessageFormat.Field constant
+         * @throws InvalidObjectException if the constant could not be resolved.
+         *
+         * @stable ICU 3.8
+         */
+        protected Object readResolve() throws InvalidObjectException {
+            if (this.getClass() != MessageFormat.Field.class) {
+                throw new InvalidObjectException(
+                    "A subclass of MessageFormat.Field must implement readResolve.");
+            }
+            if (this.getName().equals(ARGUMENT.getName())) {
+                return ARGUMENT;
+            } else {
+                throw new InvalidObjectException("Unknown attribute name.");
+            }
+        }
+
+        /**
+         * Constant identifying a portion of a message that was generated
+         * from an argument passed into <code>formatToCharacterIterator</code>.
+         * The value associated with the key will be an <code>Integer</code>
+         * indicating the index in the <code>arguments</code> array of the
+         * argument from which the text was generated.
+         *
+         * @stable ICU 3.8
+         */
+        public static final Field ARGUMENT = new Field("message argument field");
+
+    }
+
+    private static final char SINGLE_QUOTE = '\'';
+    private static final char CURLY_BRACE_LEFT = '{';
+    private static final char CURLY_BRACE_RIGHT = '}';
+
+    private static final int STATE_INITIAL = 0;
+    private static final int STATE_SINGLE_QUOTE = 1;
+    private static final int STATE_IN_QUOTE = 2;
+    private static final int STATE_MSG_ELEMENT = 3;
+
+    /**
+     * {@icu} Converts an 'apostrophe-friendly' pattern into a standard
+     * pattern.  Standard patterns treat all apostrophes as
+     * quotes, which is problematic in some languages, e.g.
+     * French, where apostrophe is commonly used.  This utility
+     * assumes that only an unpaired apostrophe immediately before
+     * a brace is a true quote.  Other unpaired apostrophes are paired,
+     * and the resulting standard pattern string is returned.
+     *
+     * <p><b>Note</b> it is not guaranteed that the returned pattern
+     * is indeed a valid pattern.  The only effect is to convert
+     * between patterns having different quoting semantics.
+     *
+     * @param pattern the 'apostrophe-friendly' patttern to convert
+     * @return the standard equivalent of the original pattern
+     * @stable ICU 3.4
+     */
+    public static String autoQuoteApostrophe(String pattern) {
+        StringBuilder buf = new StringBuilder(pattern.length() * 2);
+        int state = STATE_INITIAL;
+        int braceCount = 0;
+        for (int i = 0, j = pattern.length(); i < j; ++i) {
+            char c = pattern.charAt(i);
+            switch (state) {
+            case STATE_INITIAL:
+                switch (c) {
+                case SINGLE_QUOTE:
+                    state = STATE_SINGLE_QUOTE;
+                    break;
+                case CURLY_BRACE_LEFT:
+                    state = STATE_MSG_ELEMENT;
+                    ++braceCount;
+                    break;
+                }
+                break;
+            case STATE_SINGLE_QUOTE:
+                switch (c) {
+                case SINGLE_QUOTE:
+                    state = STATE_INITIAL;
+                    break;
+                case CURLY_BRACE_LEFT:
+                case CURLY_BRACE_RIGHT:
+                    state = STATE_IN_QUOTE;
+                    break;
+                default:
+                    buf.append(SINGLE_QUOTE);
+                    state = STATE_INITIAL;
+                    break;
+                }
+                break;
+            case STATE_IN_QUOTE:
+                switch (c) {
+                case SINGLE_QUOTE:
+                    state = STATE_INITIAL;
+                    break;
+                }
+                break;
+            case STATE_MSG_ELEMENT:
+                switch (c) {
+                case CURLY_BRACE_LEFT:
+                    ++braceCount;
+                    break;
+                case CURLY_BRACE_RIGHT:
+                    if (--braceCount == 0) {
+                        state = STATE_INITIAL;
+                    }
+                    break;
+                }
+                break;
+            ///CLOVER:OFF
+            default: // Never happens.
+                break;
+            ///CLOVER:ON
+            }
+            buf.append(c);
+        }
+        // End of scan
+        if (state == STATE_SINGLE_QUOTE || state == STATE_IN_QUOTE) {
+            buf.append(SINGLE_QUOTE);
+        }
+        return new String(buf);
+    }
+
+    private static FieldPosition toJDKFieldPosition(FieldPosition icuPos) {
+        if (icuPos == null) {
+            return null;
+        }
+
+        int fieldID = icuPos.getField();
+        Format.Field fieldAttribute = icuPos.getFieldAttribute();
+
+        FieldPosition jdkPos = null;
+        if (fieldAttribute != null) {
+            // map field
+            if (fieldAttribute.equals(Field.ARGUMENT)) {
+                fieldAttribute = java.text.MessageFormat.Field.ARGUMENT;
+            }
+            jdkPos = new FieldPosition(fieldAttribute, fieldID);
+        } else {
+            jdkPos = new FieldPosition(fieldID);
+        }
+
+        jdkPos.setBeginIndex(icuPos.getBeginIndex());
+        jdkPos.setEndIndex(icuPos.getEndIndex());
+
+        return jdkPos;
+
+    }
+
+    private void wrapNestedFormatters(java.text.MessageFormat mfmt) {
+        // Update nested formatters created by Java MessageFormat
+        // with ICU versions, so FieldPosition / AttributedText will
+        // use ICU formatter's definition, such as com.ibm.icu.text.NumberFormat.INTEGER_FIELD
+
+        // Replacing nested formatter may change the pattern string
+        // originally used. For example, "{0,integer} files" is replaced
+        // with "{0} files". We preserve the original pattern.
+        savedPattern = mfmt.toPattern();
+
+        Format[] subfmts = mfmt.getFormats();
+        for (int i = 0; i < subfmts.length; i++) {
+            if (subfmts[i] instanceof java.text.DateFormat) {
+                subfmts[i] = new DateFormat((java.text.DateFormat)subfmts[i]);
+            } else if (subfmts[i] instanceof java.text.NumberFormat) {
+                subfmts[i] = new NumberFormat((java.text.NumberFormat)subfmts[i]);
+            }
+        }
+        mfmt.setFormats(subfmts);
+    }
+
+    private String savedPattern;
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/NumberFormat.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/NumberFormat.java
index 62f3202..831e146 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/NumberFormat.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/NumberFormat.java
@@ -1,1312 +1,1313 @@
-/*
- *******************************************************************************
- * Copyright (C) 1996-2011, International Business Machines Corporation and    *
- * others. All Rights Reserved.                                                *
- *******************************************************************************
- */
-
-package com.ibm.icu.text;
-
-import java.io.InvalidObjectException;
-import java.math.BigInteger;
-import java.text.FieldPosition;
-import java.text.Format;
-import java.text.ParseException;
-import java.text.ParsePosition;
-import java.util.Locale;
-import java.util.Set;
-
-import com.ibm.icu.util.Currency;
-import com.ibm.icu.util.CurrencyAmount;
-import com.ibm.icu.util.ULocale;
-
-/**
- * {@icuenhanced java.text.NumberFormat}.{@icu _usage_}
- *
- * <code>NumberFormat</code> is the abstract base class for all number
- * formats. This class provides the interface for formatting and parsing
- * numbers. <code>NumberFormat</code> also provides methods for determining
- * which locales have number formats, and what their names are.
- *
- * <code>NumberFormat</code> helps you to format and parse numbers for any locale.
- * Your code can be completely independent of the locale conventions for
- * decimal points, thousands-separators, or even the particular decimal
- * digits used, or whether the number format is even decimal.
- *
- * <p>
- * To format a number for the current Locale, use one of the factory
- * class methods:
- * <blockquote>
- * <pre>
- *  myString = NumberFormat.getInstance().format(myNumber);
- * </pre>
- * </blockquote>
- * If you are formatting multiple numbers, it is
- * more efficient to get the format and use it multiple times so that
- * the system doesn't have to fetch the information about the local
- * language and country conventions multiple times.
- * <blockquote>
- * <pre>
- * NumberFormat nf = NumberFormat.getInstance();
- * for (int i = 0; i < a.length; ++i) {
- *     output.println(nf.format(myNumber[i]) + "; ");
- * }
- * </pre>
- * </blockquote>
- * To format a number for a different Locale, specify it in the
- * call to <code>getInstance</code>.
- * <blockquote>
- * <pre>
- * NumberFormat nf = NumberFormat.getInstance(Locale.FRENCH);
- * </pre>
- * </blockquote>
- * You can also use a <code>NumberFormat</code> to parse numbers:
- * <blockquote>
- * <pre>
- * myNumber = nf.parse(myString);
- * </pre>
- * </blockquote>
- * Use <code>getInstance</code> or <code>getNumberInstance</code> to get the
- * normal number format. Use <code>getIntegerInstance</code> to get an
- * integer number format. Use <code>getCurrencyInstance</code> to get the
- * currency number format. And use <code>getPercentInstance</code> to get a
- * format for displaying percentages. With this format, a fraction like
- * 0.53 is displayed as 53%.
- *
- * <p>
- * Starting from ICU 4.2, you can use getInstance() by passing in a 'style'
- * as parameter to get the correct instance.
- * For example,
- * use getInstance(...NUMBERSTYLE) to get the normal number format,
- * getInstance(...PERCENTSTYLE) to get a format for displaying percentage,
- * getInstance(...SCIENTIFICSTYLE) to get a format for displaying scientific number,
- * getInstance(...INTEGERSTYLE) to get an integer number format,
- * getInstance(...CURRENCYSTYLE) to get the currency number format,
- * in which the currency is represented by its symbol, for example, "$3.00".
- * getInstance(...ISOCURRENCYSTYLE)  to get the currency number format,
- * in which the currency is represented by its ISO code, for example "USD3.00".
- * getInstance(...PLURALCURRENCYSTYLE) to get the currency number format,
- * in which the currency is represented by its full name in plural format,
- * for example, "3.00 US dollars" or "1.00 US dollar".
- *
- *
- * <p>
- * You can also control the display of numbers with such methods as
- * <code>setMinimumFractionDigits</code>.
- * If you want even more control over the format or parsing,
- * or want to give your users more control,
- * you can try casting the <code>NumberFormat</code> you get from the factory methods
- * to a <code>DecimalFormat</code>. This will work for the vast majority
- * of locales; just remember to put it in a <code>try</code> block in case you
- * encounter an unusual one.
- *
- * <p>
- * NumberFormat is designed such that some controls
- * work for formatting and others work for parsing.  The following is
- * the detailed description for each these control methods,
- * <p>
- * setParseIntegerOnly : only affects parsing, e.g.
- * if true,  "3456.78" -> 3456 (and leaves the parse position just after '6')
- * if false, "3456.78" -> 3456.78 (and leaves the parse position just after '8')
- * This is independent of formatting.  If you want to not show a decimal point
- * where there might be no digits after the decimal point, use
- * setDecimalSeparatorAlwaysShown on DecimalFormat.
- * <p>
- * You can also use forms of the <code>parse</code> and <code>format</code>
- * methods with <code>ParsePosition</code> and <code>FieldPosition</code> to
- * allow you to:
- * <ul>
- * <li> progressively parse through pieces of a string
- * <li> align the decimal point and other areas
- * </ul>
- * For example, you can align numbers in two ways:
- * <ol>
- * <li> If you are using a monospaced font with spacing for alignment,
- *      you can pass the <code>FieldPosition</code> in your format call, with
- *      <code>field</code> = <code>INTEGER_FIELD</code>. On output,
- *      <code>getEndIndex</code> will be set to the offset between the
- *      last character of the integer and the decimal. Add
- *      (desiredSpaceCount - getEndIndex) spaces at the front of the string.
- *
- * <li> If you are using proportional fonts,
- *      instead of padding with spaces, measure the width
- *      of the string in pixels from the start to <code>getEndIndex</code>.
- *      Then move the pen by
- *      (desiredPixelWidth - widthToAlignmentPoint) before drawing the text.
- *      It also works where there is no decimal, but possibly additional
- *      characters at the end, e.g., with parentheses in negative
- *      numbers: "(12)" for -12.
- * </ol>
- *
- * <h4>Synchronization</h4>
- * <p>
- * Number formats are generally not synchronized. It is recommended to create
- * separate format instances for each thread. If multiple threads access a format
- * concurrently, it must be synchronized externally.
- * <p>
- *
- * <h4>DecimalFormat</h4>
- * <p>DecimalFormat is the concrete implementation of NumberFormat, and the
- * NumberFormat API is essentially an abstraction from DecimalFormat's API.
- * Refer to DecimalFormat for more information about this API.</p>
- *
- * see          DecimalFormat
- * see          java.text.ChoiceFormat
- * @author       Mark Davis
- * @author       Helena Shih
- * @author       Alan Liu
- * @stable ICU 2.0
- */
-public class NumberFormat extends Format {
-    private static final long serialVersionUID = 1;
-
-    /**
-     * @internal
-     */
-    public final java.text.NumberFormat numberFormat;
-        
-    /**
-     * @internal
-     * @param delegate the NumberFormat to which to delegate
-     */
-    public NumberFormat(java.text.NumberFormat delegate) {
-        this.numberFormat = delegate;
-    }
-
-    /**
-     * {@icu} Constant to specify normal number style of format.
-     * @stable ICU 4.2
-     */
-    public static final int NUMBERSTYLE = 0;
-    /**
-     * {@icu} Constant to specify currency style of format which uses currency symbol
-     * to represent currency, for example: "$3.00".
-     * @stable ICU 4.2
-     */
-    public static final int CURRENCYSTYLE = 1;
-    /**
-     * {@icu} Constant to specify a style of format to display percent.
-     * @stable ICU 4.2
-     */
-    public static final int PERCENTSTYLE = 2;
-    /**
-     * {@icu} Constant to specify a style of format to display scientific number.
-     * @stable ICU 4.2
-     */
-    public static final int SCIENTIFICSTYLE = 3;
-    /**
-     * {@icu} Constant to specify a integer number style format.
-     * @stable ICU 4.2
-     */
-    public static final int INTEGERSTYLE = 4;
-    /**
-     * {@icu} Constant to specify currency style of format which uses currency
-     * ISO code to represent currency, for example: "USD3.00".
-     * @stable ICU 4.2
-     */
-    public static final int ISOCURRENCYSTYLE = 5;
-    /**
-     * {@icu} Constant to specify currency style of format which uses currency
-     * long name with plural format to represent currency, for example,
-     * "3.00 US Dollars".
-     * @stable ICU 4.2
-     */
-    public static final int PLURALCURRENCYSTYLE = 6;
-
-    /**
-     * Field constant used to construct a FieldPosition object. Signifies that
-     * the position of the integer part of a formatted number should be returned.
-     * @see java.text.FieldPosition
-     * @stable ICU 2.0
-     */
-    public static final int INTEGER_FIELD = 0;
-
-    /**
-     * Field constant used to construct a FieldPosition object. Signifies that
-     * the position of the fraction part of a formatted number should be returned.
-     * @see java.text.FieldPosition
-     * @stable ICU 2.0
-     */
-    public static final int FRACTION_FIELD = 1;
-
-    /**
-     * Formats a number and appends the resulting text to the given string buffer.
-     * {@icunote} recognizes <code>BigInteger</code>
-     * and <code>BigDecimal</code> objects.
-     * @see java.text.Format#format(Object, StringBuffer, FieldPosition)
-     * @stable ICU 2.0
-     */
-    public StringBuffer format(Object number,
-                               StringBuffer toAppendTo,
-                               FieldPosition pos) {
-        FieldPosition jdkPos = toJDKFieldPosition(pos);
-        StringBuffer buf = numberFormat.format(number, toAppendTo, jdkPos);
-        if (jdkPos != null) {
-            pos.setBeginIndex(jdkPos.getBeginIndex());
-            pos.setEndIndex(jdkPos.getEndIndex());
-        }
-        return buf;
-    }
-
-    /**
-     * Parses text from a string to produce a number.
-     * @param source the String to parse
-     * @param parsePosition the position at which to start the parse
-     * @return the parsed number, or null
-     * @see java.text.NumberFormat#parseObject(String, ParsePosition)
-     * @stable ICU 2.0
-     */
-    public final Object parseObject(String source,
-                                    ParsePosition parsePosition) {
-        return numberFormat.parse(source, parsePosition);
-    }
-
-    /**
-     * Specialization of format.
-     * @see java.text.Format#format(Object)
-     * @stable ICU 2.0
-     */
-    public final String format(double number) {
-        return numberFormat.format(number);
-    }
-
-    /**
-     * Specialization of format.
-     * @see java.text.Format#format(Object)
-     * @stable ICU 2.0
-     */
-    public final String format(long number) {
-        return numberFormat.format(number);
-    }
-
-    /**
-     * {@icu} Convenience method to format a BigInteger.
-     * @stable ICU 2.0
-     */
-    public final String format(BigInteger number) {
-        return numberFormat.format(number);
-    }
-
-    /**
-     * Convenience method to format a BigDecimal.
-     * @stable ICU 2.0
-     */
-    public final String format(java.math.BigDecimal number) {
-        return numberFormat.format(number);
-    }
-
-    /**
-     * {@icu} Convenience method to format an ICU BigDecimal.
-     * @stable ICU 2.0
-     */
-    public final String format(com.ibm.icu.math.BigDecimal number) {
-        return numberFormat.format(number.toBigDecimal());
-    }
-
-    /**
-     * {@icu} Convenience method to format a CurrencyAmount.
-     * @stable ICU 3.0
-     */
-    public final String format(CurrencyAmount currAmt) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Specialization of format.
-     * @see java.text.Format#format(Object, StringBuffer, FieldPosition)
-     * @stable ICU 2.0
-     */
-    public StringBuffer format(double number,
-                                        StringBuffer toAppendTo,
-                                        FieldPosition pos) {
-        FieldPosition jdkPos = toJDKFieldPosition(pos);
-        StringBuffer buf = numberFormat.format(number, toAppendTo, jdkPos);
-        pos.setBeginIndex(jdkPos.getBeginIndex());
-        pos.setEndIndex(jdkPos.getEndIndex());
-        return buf;
-    }
-
-    /**
-     * Specialization of format.
-     * @see java.text.Format#format(Object, StringBuffer, FieldPosition)
-     * @stable ICU 2.0
-     */
-    public StringBuffer format(long number,
-                                        StringBuffer toAppendTo,
-                                        FieldPosition pos) {
-        FieldPosition jdkPos = toJDKFieldPosition(pos);
-        StringBuffer buf = numberFormat.format(number, toAppendTo, jdkPos);
-        pos.setBeginIndex(jdkPos.getBeginIndex());
-        pos.setEndIndex(jdkPos.getEndIndex());
-        return buf;
-    }
-    /**
-     * {@icu} Formats a BigInteger. Specialization of format.
-     * @see java.text.Format#format(Object, StringBuffer, FieldPosition)
-     * @stable ICU 2.0
-     */
-    public StringBuffer format(BigInteger number,
-                                        StringBuffer toAppendTo,
-                                        FieldPosition pos) {
-        FieldPosition jdkPos = toJDKFieldPosition(pos);
-        StringBuffer buf = numberFormat.format(number, toAppendTo, jdkPos);
-        pos.setBeginIndex(jdkPos.getBeginIndex());
-        pos.setEndIndex(jdkPos.getEndIndex());
-        return buf;
-    }
-    /**
-     * {@icu} Formats a BigDecimal. Specialization of format.
-     * @see java.text.Format#format(Object, StringBuffer, FieldPosition)
-     * @stable ICU 2.0
-     */
-    public StringBuffer format(java.math.BigDecimal number,
-                                        StringBuffer toAppendTo,
-                                        FieldPosition pos) {
-        FieldPosition jdkPos = toJDKFieldPosition(pos);
-        StringBuffer buf = numberFormat.format(number, toAppendTo, jdkPos);
-        pos.setBeginIndex(jdkPos.getBeginIndex());
-        pos.setEndIndex(jdkPos.getEndIndex());
-        return buf;
-    }
-    /**
-     * {@icu} Formats an ICU BigDecimal. Specialization of format.
-     * @see java.text.Format#format(Object, StringBuffer, FieldPosition)
-     * @stable ICU 2.0
-     */
-    public StringBuffer format(com.ibm.icu.math.BigDecimal number,
-                                        StringBuffer toAppendTo,
-                                        FieldPosition pos) {
-        FieldPosition jdkPos = toJDKFieldPosition(pos);
-        StringBuffer buf = numberFormat.format(number.toBigDecimal(), toAppendTo, jdkPos);
-        pos.setBeginIndex(jdkPos.getBeginIndex());
-        pos.setEndIndex(jdkPos.getEndIndex());
-        return buf;
-    }
-
-    /**
-     * {@icu} Formats a CurrencyAmount. Specialization of format.
-     * @see java.text.Format#format(Object, StringBuffer, FieldPosition)
-     * @stable ICU 3.0
-     */
-    public StringBuffer format(CurrencyAmount currAmt,
-                               StringBuffer toAppendTo,
-                               FieldPosition pos) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Returns a Long if possible (e.g., within the range [Long.MIN_VALUE,
-     * Long.MAX_VALUE] and with no decimals), otherwise a Double.
-     * If IntegerOnly is set, will stop at a decimal
-     * point (or equivalent; e.g., for rational numbers "1 2/3", will stop
-     * after the 1).
-     * Does not throw an exception; if no object can be parsed, index is
-     * unchanged!
-     * @see #isParseIntegerOnly
-     * @see java.text.Format#parseObject(String, ParsePosition)
-     * @stable ICU 2.0
-     */
-    public Number parse(String text, ParsePosition parsePosition) {
-        return numberFormat.parse(text, parsePosition);
-    }
-
-    /**
-     * Parses text from the beginning of the given string to produce a number.
-     * The method might not use the entire text of the given string.
-     *
-     * @param text A String whose beginning should be parsed.
-     * @return A Number parsed from the string.
-     * @throws ParseException if the beginning of the specified string
-     * cannot be parsed.
-     * @see #format
-     * @stable ICU 2.0
-     */
-    public Number parse(String text) throws ParseException {
-        return numberFormat.parse(text);
-    }
-
-    /**
-     * Parses text from the given string as a CurrencyAmount.  Unlike
-     * the parse() method, this method will attempt to parse a generic
-     * currency name, searching for a match of this object's locale's
-     * currency display names, or for a 3-letter ISO currency code.
-     * This method will fail if this format is not a currency format,
-     * that is, if it does not contain the currency pattern symbol
-     * (U+00A4) in its prefix or suffix.
-     *
-     * @param text the string to parse
-     * @param pos input-output position; on input, the position within
-     * text to match; must have 0 <= pos.getIndex() < text.length();
-     * on output, the position after the last matched character. If
-     * the parse fails, the position in unchanged upon output.
-     * @return a CurrencyAmount, or null upon failure
-     */
-    CurrencyAmount parseCurrency(String text, ParsePosition pos) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Returns true if this format will parse numbers as integers only.
-     * For example in the English locale, with ParseIntegerOnly true, the
-     * string "1234." would be parsed as the integer value 1234 and parsing
-     * would stop at the "." character.  The decimal separator accepted
-     * by the parse operation is locale-dependent and determined by the
-     * subclass.
-     * @return true if this will parse integers only
-     * @stable ICU 2.0
-     */
-    public boolean isParseIntegerOnly() {
-        return numberFormat.isParseIntegerOnly();
-    }
-
-    /**
-     * Sets whether or not numbers should be parsed as integers only.
-     * @param value true if this should parse integers only
-     * @see #isParseIntegerOnly
-     * @stable ICU 2.0
-     */
-    public void setParseIntegerOnly(boolean value) {
-        numberFormat.setParseIntegerOnly(value);
-    }
-
-    /**
-     * {@icu} Sets whether strict parsing is in effect.  When this is true, the
-     * following conditions cause a parse failure (examples use the pattern "#,##0.#"):<ul>
-     * <li>Leading zeros<br>
-     * '00', '0123' fail the parse, but '0' and '0.001' pass</li>
-     * <li>Leading or doubled grouping separators<br>
-     * ',123' and '1,,234" fail</li>
-     * <li>Groups of incorrect length when grouping is used<br>
-     * '1,23' and '1234,567' fail, but '1234' passes</li>
-     * <li>Grouping separators used in numbers followed by exponents<br>
-     * '1,234E5' fails, but '1234E5' and '1,234E' pass ('E' is not an exponent when
-     * not followed by a number)</li>
-     * </ul>
-     * When strict parsing is off, leading zeros and all grouping separators are ignored.
-     * This is the default behavior.
-     * @param value True to enable strict parsing.  Default is false.
-     * @see #isParseStrict
-     * @stable ICU 3.6
-     */
-    public void setParseStrict(boolean value) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Returns whether strict parsing is in effect.
-     * @return true if strict parsing is in effect
-     * @see #setParseStrict
-     * @stable ICU 3.6
-     */
-    public boolean isParseStrict() {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    //============== Locale Stuff =====================
-
-    /**
-     * Returns the default number format for the current default locale.
-     * The default format is one of the styles provided by the other
-     * factory methods: getNumberInstance, getIntegerInstance,
-     * getCurrencyInstance or getPercentInstance.
-     * Exactly which one is locale-dependent.
-     * @stable ICU 2.0
-     */
-    //Bug 4408066 [Richard/GCL]
-    public final static NumberFormat getInstance() {
-        return getInstance(ULocale.getDefault(), NUMBERSTYLE);
-    }
-
-    /**
-     * Returns the default number format for the specified locale.
-     * The default format is one of the styles provided by the other
-     * factory methods: getNumberInstance, getCurrencyInstance or getPercentInstance.
-     * Exactly which one is locale-dependent.
-     * @stable ICU 2.0
-     */
-    public static NumberFormat getInstance(Locale inLocale) {
-        return getInstance(ULocale.forLocale(inLocale), NUMBERSTYLE);
-    }
-
-    /**
-     * {@icu} Returns the default number format for the specified locale.
-     * The default format is one of the styles provided by the other
-     * factory methods: getNumberInstance, getCurrencyInstance or getPercentInstance.
-     * Exactly which one is locale-dependent.
-     * @stable ICU 3.2
-     */
-    public static NumberFormat getInstance(ULocale inLocale) {
-        return getInstance(inLocale, NUMBERSTYLE);
-    }
-
-    /**
-     * {@icu} Returns a specific style number format for default locale.
-     * @param style  number format style
-     * @stable ICU 4.2
-     */
-    public final static NumberFormat getInstance(int style) {
-        return getInstance(ULocale.getDefault(), style);
-    }
-
-    /**
-     * {@icu} Returns a specific style number format for a specific locale.
-     * @param inLocale  the specific locale.
-     * @param style     number format style
-     * @stable ICU 4.2
-     */
-    public static NumberFormat getInstance(Locale inLocale, int style) {
-        return getInstance(ULocale.forLocale(inLocale), style);
-    }
-
-
-    /**
-     * Returns a general-purpose number format for the current default locale.
-     * @stable ICU 2.0
-     */
-    public final static NumberFormat getNumberInstance() {
-        return getInstance(ULocale.getDefault(), NUMBERSTYLE);
-    }
-
-    /**
-     * Returns a general-purpose number format for the specified locale.
-     * @stable ICU 2.0
-     */
-    public static NumberFormat getNumberInstance(Locale inLocale) {
-        return getInstance(ULocale.forLocale(inLocale), NUMBERSTYLE);
-    }
-
-    /**
-     * {@icu} Returns a general-purpose number format for the specified locale.
-     * @stable ICU 3.2
-     */
-    public static NumberFormat getNumberInstance(ULocale inLocale) {
-        return getInstance(inLocale, NUMBERSTYLE);
-    }
-
-    /**
-     * Returns an integer number format for the current default locale. The
-     * returned number format is configured to round floating point numbers
-     * to the nearest integer using IEEE half-even rounding (see {@link
-     * com.ibm.icu.math.BigDecimal#ROUND_HALF_EVEN ROUND_HALF_EVEN}) for formatting,
-     * and to parse only the integer part of an input string (see {@link
-     * #isParseIntegerOnly isParseIntegerOnly}).
-     *
-     * @return a number format for integer values
-     * @stable ICU 2.0
-     */
-    //Bug 4408066 [Richard/GCL]
-    public final static NumberFormat getIntegerInstance() {
-        return getInstance(ULocale.getDefault(), INTEGERSTYLE);
-    }
-
-    /**
-     * Returns an integer number format for the specified locale. The
-     * returned number format is configured to round floating point numbers
-     * to the nearest integer using IEEE half-even rounding (see {@link
-     * com.ibm.icu.math.BigDecimal#ROUND_HALF_EVEN ROUND_HALF_EVEN}) for formatting,
-     * and to parse only the integer part of an input string (see {@link
-     * #isParseIntegerOnly isParseIntegerOnly}).
-     *
-     * @param inLocale the locale for which a number format is needed
-     * @return a number format for integer values
-     * @stable ICU 2.0
-     */
-    //Bug 4408066 [Richard/GCL]
-    public static NumberFormat getIntegerInstance(Locale inLocale) {
-        return getInstance(ULocale.forLocale(inLocale), INTEGERSTYLE);
-    }
-
-    /**
-     * {@icu} Returns an integer number format for the specified locale. The
-     * returned number format is configured to round floating point numbers
-     * to the nearest integer using IEEE half-even rounding (see {@link
-     * com.ibm.icu.math.BigDecimal#ROUND_HALF_EVEN ROUND_HALF_EVEN}) for formatting,
-     * and to parse only the integer part of an input string (see {@link
-     * #isParseIntegerOnly isParseIntegerOnly}).
-     *
-     * @param inLocale the locale for which a number format is needed
-     * @return a number format for integer values
-     * @stable ICU 3.2
-     */
-    public static NumberFormat getIntegerInstance(ULocale inLocale) {
-        return getInstance(inLocale, INTEGERSTYLE);
-    }
-
-    /**
-     * Returns a currency format for the current default locale.
-     * @return a number format for currency
-     * @stable ICU 2.0
-     */
-    public final static NumberFormat getCurrencyInstance() {
-        return getInstance(ULocale.getDefault(), CURRENCYSTYLE);
-    }
-
-    /**
-     * Returns a currency format for the specified locale.
-     * @return a number format for currency
-     * @stable ICU 2.0
-     */
-    public static NumberFormat getCurrencyInstance(Locale inLocale) {
-        return getInstance(ULocale.forLocale(inLocale), CURRENCYSTYLE);
-    }
-
-    /**
-     * {@icu} Returns a currency format for the specified locale.
-     * @return a number format for currency
-     * @stable ICU 3.2
-     */
-    public static NumberFormat getCurrencyInstance(ULocale inLocale) {
-        return getInstance(inLocale, CURRENCYSTYLE);
-    }
-
-    /**
-     * Returns a percentage format for the current default locale.
-     * @return a number format for percents
-     * @stable ICU 2.0
-     */
-    public final static NumberFormat getPercentInstance() {
-        return getInstance(ULocale.getDefault(), PERCENTSTYLE);
-    }
-
-    /**
-     * Returns a percentage format for the specified locale.
-     * @return a number format for percents
-     * @stable ICU 2.0
-     */
-    public static NumberFormat getPercentInstance(Locale inLocale) {
-        return getInstance(ULocale.forLocale(inLocale), PERCENTSTYLE);
-    }
-
-    /**
-     * {@icu} Returns a percentage format for the specified locale.
-     * @return a number format for percents
-     * @stable ICU 3.2
-     */
-    public static NumberFormat getPercentInstance(ULocale inLocale) {
-        return getInstance(inLocale, PERCENTSTYLE);
-    }
-
-    /**
-     * {@icu} Returns a scientific format for the current default locale.
-     * @return a scientific number format
-     * @stable ICU 2.0
-     */
-    public final static NumberFormat getScientificInstance() {
-        return getInstance(ULocale.getDefault(), SCIENTIFICSTYLE);
-    }
-
-    /**
-     * {@icu} Returns a scientific format for the specified locale.
-     * @return a scientific number format
-     * @stable ICU 2.0
-     */
-    public static NumberFormat getScientificInstance(Locale inLocale) {
-        return getInstance(ULocale.forLocale(inLocale), SCIENTIFICSTYLE);
-    }
-
-    /**
-     * {@icu} Returns a scientific format for the specified locale.
-     * @return a scientific number format
-     * @stable ICU 3.2
-     */
-    public static NumberFormat getScientificInstance(ULocale inLocale) {
-        return getInstance(inLocale, SCIENTIFICSTYLE);
-    }
-
-    /**
-     * A NumberFormatFactory is used to register new number formats.  The factory
-     * should be able to create any of the predefined formats for each locale it
-     * supports.  When registered, the locales it supports extend or override the
-     * locales already supported by ICU.
-     *
-     * <p><b>Note:</b> as of ICU4J 3.2, the default API for NumberFormatFactory uses
-     * ULocale instead of Locale.  Instead of overriding createFormat(Locale, int),
-     * new implementations should override createFactory(ULocale, int).  Note that
-     * one of these two methods <b>MUST</b> be overridden or else an infinite
-     * loop will occur.
-     *
-     * @stable ICU 2.6
-     */
-    public static abstract class NumberFormatFactory {
-        /**
-         * Value passed to format requesting a default number format.
-         * @stable ICU 2.6
-         */
-        public static final int FORMAT_NUMBER = NUMBERSTYLE;
-
-        /**
-         * Value passed to format requesting a currency format.
-         * @stable ICU 2.6
-         */
-        public static final int FORMAT_CURRENCY = CURRENCYSTYLE;
-
-        /**
-         * Value passed to format requesting a percent format.
-         * @stable ICU 2.6
-         */
-        public static final int FORMAT_PERCENT = PERCENTSTYLE;
-
-        /**
-         * Value passed to format requesting a scientific format.
-         * @stable ICU 2.6
-         */
-        public static final int FORMAT_SCIENTIFIC = SCIENTIFICSTYLE;
-
-        /**
-         * Value passed to format requesting an integer format.
-         * @stable ICU 2.6
-         */
-        public static final int FORMAT_INTEGER = INTEGERSTYLE;
-
-        /**
-         * Returns true if this factory is visible.  Default is true.
-         * If not visible, the locales supported by this factory will not
-         * be listed by getAvailableLocales.  This value must not change.
-         * @return true if the factory is visible.
-         * @stable ICU 2.6
-         */
-        public boolean visible() {
-            return true;
-        }
-
-        /**
-         * Returns an immutable collection of the locale names directly
-         * supported by this factory.
-         * @return the supported locale names.
-         * @stable ICU 2.6
-         */
-         public abstract Set<String> getSupportedLocaleNames();
-
-        /**
-         * Returns a number format of the appropriate type.  If the locale
-         * is not supported, return null.  If the locale is supported, but
-         * the type is not provided by this service, return null.  Otherwise
-         * return an appropriate instance of NumberFormat.
-         * <b>Note:</b> as of ICU4J 3.2, implementations should override
-         * this method instead of createFormat(Locale, int).
-         * @param loc the locale for which to create the format
-         * @param formatType the type of format
-         * @return the NumberFormat, or null.
-         * @stable ICU 3.2
-         */
-        public NumberFormat createFormat(ULocale loc, int formatType) {
-            return createFormat(loc.toLocale(), formatType);
-        }
-
-        /**
-         * Returns a number format of the appropriate type.  If the locale
-         * is not supported, return null.  If the locale is supported, but
-         * the type is not provided by this service, return null.  Otherwise
-         * return an appropriate instance of NumberFormat.
-         * <b>Note:</b> as of ICU4J 3.2, createFormat(ULocale, int) should be
-         * overridden instead of this method.  This method is no longer
-         * abstract and delegates to that method.
-         * @param loc the locale for which to create the format
-         * @param formatType the type of format
-         * @return the NumberFormat, or null.
-         * @stable ICU 2.6
-         */
-        public NumberFormat createFormat(Locale loc, int formatType) {
-            return createFormat(ULocale.forLocale(loc), formatType);
-        }
-
-        /**
-         * @stable ICU 2.6
-         */
-        protected NumberFormatFactory() {
-        }
-    }
-
-    /**
-     * Returns the list of Locales for which NumberFormats are available.
-     * @return the available locales
-     * @stable ICU 2.0
-     */
-    public static Locale[] getAvailableLocales() {
-        return java.text.NumberFormat.getAvailableLocales();
-    }
-
-    /**
-     * {@icu} Returns the list of Locales for which NumberFormats are available.
-     * @return the available locales
-     * @draft ICU 3.2 (retain)
-     * @provisional This API might change or be removed in a future release.
-     */
-    public static ULocale[] getAvailableULocales() {
-        if (availableULocales == null) {
-            synchronized (NumberFormat.class) {
-                if (availableULocales == null) {
-                    Locale[] locales = java.text.NumberFormat.getAvailableLocales();
-                    ULocale[] ulocales = new ULocale[locales.length];
-                    for (int i = 0; i < locales.length; ++i) {
-                        ulocales[i] = ULocale.forLocale(locales[i]);
-                    }
-                    availableULocales = ulocales;
-                }
-            }
-        }
-        return (ULocale[])availableULocales.clone();
-    }
-    private static volatile ULocale[] availableULocales;
-
-    /**
-     * {@icu} Registers a new NumberFormatFactory.  The factory is adopted by
-     * the service and must not be modified.  The returned object is a
-     * key that can be used to unregister this factory.
-     * @param factory the factory to register
-     * @return a key with which to unregister the factory
-     * @stable ICU 2.6
-     */
-    public static Object registerFactory(NumberFormatFactory factory) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Unregisters the factory or instance associated with this key (obtained from
-     * registerInstance or registerFactory).
-     * @param registryKey a key obtained from registerFactory
-     * @return true if the object was successfully unregistered
-     * @stable ICU 2.6
-     */
-    public static boolean unregister(Object registryKey) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Overrides hashCode.
-     * @stable ICU 2.0
-     */
-    public int hashCode() {
-        return numberFormat.hashCode();
-    }
-
-    /**
-     * Overrides equals.
-     * Two NumberFormats are equal if they are of the same class
-     * and the settings (groupingUsed, parseIntegerOnly, maximumIntegerDigits, etc.
-     * are equal.
-     * @param obj the object to compare against
-     * @return true if the object is equal to this.
-     * @stable ICU 2.0
-     */
-    public boolean equals(Object obj) {
-        try {
-            return numberFormat.equals(((NumberFormat)obj).numberFormat);
-        }
-        catch (Exception e) {
-            return false;
-        }
-    }
-
-    /**
-     * Overrides clone.
-     * @stable ICU 2.0
-     */
-    public Object clone() {
-        return new NumberFormat((java.text.NumberFormat)numberFormat.clone());
-    }
-
-    /**
-     * Returns true if grouping is used in this format. For example, in the
-     * en_US locale, with grouping on, the number 1234567 will be formatted
-     * as "1,234,567". The grouping separator as well as the size of each group
-     * is locale-dependent and is determined by subclasses of NumberFormat.
-     * Grouping affects both parsing and formatting.
-     * @return true if grouping is used
-     * @see #setGroupingUsed
-     * @stable ICU 2.0
-     */
-    public boolean isGroupingUsed() {
-        return numberFormat.isGroupingUsed();
-    }
-
-    /**
-     * Sets whether or not grouping will be used in this format.  Grouping
-     * affects both parsing and formatting.
-     * @see #isGroupingUsed
-     * @param newValue true to use grouping.
-     * @stable ICU 2.0
-     */
-    public void setGroupingUsed(boolean newValue) {
-        numberFormat.setGroupingUsed(newValue);
-    }
-
-    /**
-     * Returns the maximum number of digits allowed in the integer portion of a
-     * number.  The default value is 40, which subclasses can override.
-     * When formatting, the exact behavior when this value is exceeded is
-     * subclass-specific.  When parsing, this has no effect.
-     * @return the maximum number of integer digits
-     * @see #setMaximumIntegerDigits
-     * @stable ICU 2.0
-     */
-    public int getMaximumIntegerDigits() {
-        return numberFormat.getMaximumIntegerDigits();
-    }
-
-    /**
-     * Sets the maximum number of digits allowed in the integer portion of a
-     * number. This must be >= minimumIntegerDigits.  If the
-     * new value for maximumIntegerDigits is less than the current value
-     * of minimumIntegerDigits, then minimumIntegerDigits will also be set to
-     * the new value.
-     * @param newValue the maximum number of integer digits to be shown; if
-     * less than zero, then zero is used.  Subclasses might enforce an
-     * upper limit to this value appropriate to the numeric type being formatted.
-     * @see #getMaximumIntegerDigits
-     * @stable ICU 2.0
-     */
-    public void setMaximumIntegerDigits(int newValue) {
-        numberFormat.setMaximumIntegerDigits(newValue);
-    }
-
-    /**
-     * Returns the minimum number of digits allowed in the integer portion of a
-     * number.  The default value is 1, which subclasses can override.
-     * When formatting, if this value is not reached, numbers are padded on the
-     * left with the locale-specific '0' character to ensure at least this
-     * number of integer digits.  When parsing, this has no effect.
-     * @return the minimum number of integer digits
-     * @see #setMinimumIntegerDigits
-     * @stable ICU 2.0
-     */
-    public int getMinimumIntegerDigits() {
-        return numberFormat.getMinimumIntegerDigits();
-    }
-
-    /**
-     * Sets the minimum number of digits allowed in the integer portion of a
-     * number.  This must be <= maximumIntegerDigits.  If the
-     * new value for minimumIntegerDigits is more than the current value
-     * of maximumIntegerDigits, then maximumIntegerDigits will also be set to
-     * the new value.
-     * @param newValue the minimum number of integer digits to be shown; if
-     * less than zero, then zero is used. Subclasses might enforce an
-     * upper limit to this value appropriate to the numeric type being formatted.
-     * @see #getMinimumIntegerDigits
-     * @stable ICU 2.0
-     */
-    public void setMinimumIntegerDigits(int newValue) {
-        numberFormat.setMinimumIntegerDigits(newValue);
-    }
-
-    /**
-     * Returns the maximum number of digits allowed in the fraction
-     * portion of a number.  The default value is 3, which subclasses
-     * can override.  When formatting, the exact behavior when this
-     * value is exceeded is subclass-specific.  When parsing, this has
-     * no effect.
-     * @return the maximum number of fraction digits
-     * @see #setMaximumFractionDigits
-     * @stable ICU 2.0
-     */
-    public int getMaximumFractionDigits() {
-        return numberFormat.getMaximumFractionDigits();
-    }
-
-    /**
-     * Sets the maximum number of digits allowed in the fraction portion of a
-     * number. This must be >= minimumFractionDigits.  If the
-     * new value for maximumFractionDigits is less than the current value
-     * of minimumFractionDigits, then minimumFractionDigits will also be set to
-     * the new value.
-     * @param newValue the maximum number of fraction digits to be shown; if
-     * less than zero, then zero is used. The concrete subclass may enforce an
-     * upper limit to this value appropriate to the numeric type being formatted.
-     * @see #getMaximumFractionDigits
-     * @stable ICU 2.0
-     */
-    public void setMaximumFractionDigits(int newValue) {
-        numberFormat.setMaximumFractionDigits(newValue);
-    }
-
-    /**
-     * Returns the minimum number of digits allowed in the fraction portion of a
-     * number.  The default value is 0, which subclasses can override.
-     * When formatting, if this value is not reached, numbers are padded on
-     * the right with the locale-specific '0' character to ensure at least
-     * this number of fraction digits.  When parsing, this has no effect.
-     * @return the minimum number of fraction digits
-     * @see #setMinimumFractionDigits
-     * @stable ICU 2.0
-     */
-    public int getMinimumFractionDigits() {
-        return numberFormat.getMinimumFractionDigits();
-    }
-
-    /**
-     * Sets the minimum number of digits allowed in the fraction portion of a
-     * number.  This must be <= maximumFractionDigits.  If the
-     * new value for minimumFractionDigits exceeds the current value
-     * of maximumFractionDigits, then maximumFractionDigits will also be set to
-     * the new value.
-     * @param newValue the minimum number of fraction digits to be shown; if
-     * less than zero, then zero is used.  Subclasses might enforce an
-     * upper limit to this value appropriate to the numeric type being formatted.
-     * @see #getMinimumFractionDigits
-     * @stable ICU 2.0
-     */
-    public void setMinimumFractionDigits(int newValue) {
-        numberFormat.setMinimumFractionDigits(newValue);
-    }
-
-    /**
-     * Sets the <tt>Currency</tt> object used to display currency
-     * amounts.  This takes effect immediately, if this format is a
-     * currency format.  If this format is not a currency format, then
-     * the currency object is used if and when this object becomes a
-     * currency format.
-     * @param theCurrency new currency object to use.  May be null for
-     * some subclasses.
-     * @stable ICU 2.6
-     */
-    public void setCurrency(Currency theCurrency) {
-        numberFormat.setCurrency(theCurrency.currency);
-    }
-
-    /**
-     * Returns the <tt>Currency</tt> object used to display currency
-     * amounts.  This may be null.
-     * @stable ICU 2.6
-     */
-    public Currency getCurrency() {
-        return new Currency(numberFormat.getCurrency());
-    }
-
-    /**
-     * Returns the rounding mode used in this NumberFormat.  The default implementation of
-     * tis method in NumberFormat always throws <code>UnsupportedOperationException</code>.
-     * @return A rounding mode, between <code>BigDecimal.ROUND_UP</code>
-     * and <code>BigDecimal.ROUND_UNNECESSARY</code>.
-     * @see #setRoundingMode(int)
-     * @stable ICU 4.0
-     */
-    public int getRoundingMode() {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Set the rounding mode used in this NumberFormat.  The default implementation of
-     * tis method in NumberFormat always throws <code>UnsupportedOperationException</code>.
-     * @param roundingMode A rounding mode, between
-     * <code>BigDecimal.ROUND_UP</code> and
-     * <code>BigDecimal.ROUND_UNNECESSARY</code>.
-     * @see #getRoundingMode()
-     * @stable ICU 4.0
-     */
-    public void setRoundingMode(int roundingMode) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-
-    /**
-     * Returns a specific style number format for a specific locale.
-     * @param desiredLocale  the specific locale.
-     * @param choice         number format style
-     * @throws IllegalArgumentException  if choice is not one of
-     *                                   NUMBERSTYLE, CURRENCYSTYLE,
-     *                                   PERCENTSTYLE, SCIENTIFICSTYLE,
-     *                                   INTEGERSTYLE,
-     *                                   ISOCURRENCYSTYLE, PLURALCURRENCYSTYLE,
-     * @stable ICU 4.2
-     */
-    public static NumberFormat getInstance(ULocale desiredLocale, int choice) {
-        Locale locale = desiredLocale.toLocale();
-        java.text.NumberFormat nf = null;
-        switch (choice) {
-        case NUMBERSTYLE:
-            nf = java.text.NumberFormat.getInstance(locale);
-            break;
-        case INTEGERSTYLE:
-            nf = java.text.NumberFormat.getIntegerInstance(locale);
-            break;
-        case CURRENCYSTYLE:
-            nf = java.text.NumberFormat.getCurrencyInstance(locale);
-            break;
-        case PERCENTSTYLE:
-            nf = java.text.NumberFormat.getPercentInstance(locale);
-            break;
-        case SCIENTIFICSTYLE:
-            nf = new java.text.DecimalFormat("#E0",
-                    new java.text.DecimalFormatSymbols(locale));
-            nf.setMaximumFractionDigits(10);
-            break;
-        }
-        return new NumberFormat(nf);
-    }
-
-    /**
-     * Empty constructor.  Public for compatibily with JDK which lets the
-     * compiler generate a default public constructor even though this is
-     * an abstract class.
-     * @stable ICU 2.6
-     */
-    public NumberFormat() {
-        this(java.text.NumberFormat.getInstance());
-    }
-
-    /**
-     * The instances of this inner class are used as attribute keys and values
-     * in AttributedCharacterIterator that
-     * NumberFormat.formatToCharacterIterator() method returns.
-     * <p>
-     * There is no public constructor to this class, the only instances are the
-     * constants defined here.
-     * <p>
-     * @stable ICU 3.6
-     */
-    public static class Field extends Format.Field {
-        // generated by serialver from JDK 1.4.1_01
-        static final long serialVersionUID = -4516273749929385842L;
-
-        /**
-         * @stable ICU 3.6
-         */
-        public static final Field SIGN = new Field("sign");
-
-        /**
-         * @stable ICU 3.6
-         */
-        public static final Field INTEGER = new Field("integer");
-
-        /**
-         * @stable ICU 3.6
-         */
-        public static final Field FRACTION = new Field("fraction");
-
-        /**
-         * @stable ICU 3.6
-         */
-        public static final Field EXPONENT = new Field("exponent");
-
-        /**
-         * @stable ICU 3.6
-         */
-        public static final Field EXPONENT_SIGN = new Field("exponent sign");
-
-        /**
-         * @stable ICU 3.6
-         */
-        public static final Field EXPONENT_SYMBOL = new Field("exponent symbol");
-
-        /**
-         * @stable ICU 3.6
-         */
-        public static final Field DECIMAL_SEPARATOR = new Field("decimal separator");
-        /**
-         * @stable ICU 3.6
-         */
-        public static final Field GROUPING_SEPARATOR = new Field("grouping separator");
-
-        /**
-         * @stable ICU 3.6
-         */
-        public static final Field PERCENT = new Field("percent");
-
-        /**
-         * @stable ICU 3.6
-         */
-        public static final Field PERMILLE = new Field("per mille");
-
-        /**
-         * @stable ICU 3.6
-         */
-        public static final Field CURRENCY = new Field("currency");
-
-        /**
-         * Constructs a new instance of NumberFormat.Field with the given field
-         * name.
-         * @stable ICU 3.6
-         */
-        protected Field(String fieldName) {
-            super(fieldName);
-        }
-
-        /**
-         * serizalization method resolve instances to the constant
-         * NumberFormat.Field values
-         * @stable ICU 3.6
-         */
-        protected Object readResolve() throws InvalidObjectException {
-            if (this.getName().equals(INTEGER.getName()))
-                return INTEGER;
-            if (this.getName().equals(FRACTION.getName()))
-                return FRACTION;
-            if (this.getName().equals(EXPONENT.getName()))
-                return EXPONENT;
-            if (this.getName().equals(EXPONENT_SIGN.getName()))
-                return EXPONENT_SIGN;
-            if (this.getName().equals(EXPONENT_SYMBOL.getName()))
-                return EXPONENT_SYMBOL;
-            if (this.getName().equals(CURRENCY.getName()))
-                return CURRENCY;
-            if (this.getName().equals(DECIMAL_SEPARATOR.getName()))
-                return DECIMAL_SEPARATOR;
-            if (this.getName().equals(GROUPING_SEPARATOR.getName()))
-                return GROUPING_SEPARATOR;
-            if (this.getName().equals(PERCENT.getName()))
-                return PERCENT;
-            if (this.getName().equals(PERMILLE.getName()))
-                return PERMILLE;
-            if (this.getName().equals(SIGN.getName()))
-                return SIGN;
-
-            throw new InvalidObjectException("An invalid object.");
-        }
-    }
-
-    private static FieldPosition toJDKFieldPosition(FieldPosition icuPos) {
-        if (icuPos == null) {
-            return null;
-        }
-
-        int fieldID = icuPos.getField();
-        Format.Field fieldAttribute = icuPos.getFieldAttribute();
-
-        FieldPosition jdkPos = null;
-
-        if (fieldID >= 0) {
-            if (fieldID == FRACTION_FIELD) {
-                fieldID = java.text.NumberFormat.FRACTION_FIELD;
-            } else if (fieldID == INTEGER_FIELD) {
-                fieldID = java.text.NumberFormat.INTEGER_FIELD;
-            }
-        }
-
-        if (fieldAttribute != null) {
-            // map field
-            if (fieldAttribute.equals(Field.CURRENCY)) {
-                fieldAttribute = java.text.NumberFormat.Field.CURRENCY;
-            } else if (fieldAttribute.equals(Field.DECIMAL_SEPARATOR)) {
-                fieldAttribute = java.text.NumberFormat.Field.DECIMAL_SEPARATOR;
-            } else if (fieldAttribute.equals(Field.EXPONENT)) {
-                fieldAttribute = java.text.NumberFormat.Field.EXPONENT;
-            } else if (fieldAttribute.equals(Field.EXPONENT_SIGN)) {
-                fieldAttribute = java.text.NumberFormat.Field.EXPONENT_SIGN;
-            } else if (fieldAttribute.equals(Field.EXPONENT_SYMBOL)) {
-                fieldAttribute = java.text.NumberFormat.Field.EXPONENT_SYMBOL;
-            } else if (fieldAttribute.equals(Field.FRACTION)) {
-                fieldAttribute = java.text.NumberFormat.Field.FRACTION;
-            } else if (fieldAttribute.equals(Field.GROUPING_SEPARATOR)) {
-                fieldAttribute = java.text.NumberFormat.Field.GROUPING_SEPARATOR;
-            } else if (fieldAttribute.equals(Field.INTEGER)) {
-                fieldAttribute = java.text.NumberFormat.Field.INTEGER;
-            } else if (fieldAttribute.equals(Field.PERCENT)) {
-                fieldAttribute = java.text.NumberFormat.Field.PERCENT;
-            } else if (fieldAttribute.equals(Field.PERMILLE)) {
-                fieldAttribute = java.text.NumberFormat.Field.PERMILLE;
-            } else if (fieldAttribute.equals(Field.SIGN)) {
-                fieldAttribute = java.text.NumberFormat.Field.SIGN;
-            }
-
-            jdkPos = new FieldPosition(fieldAttribute, fieldID);
-        } else {
-            jdkPos = new FieldPosition(fieldID);
-        }
-
-        jdkPos.setBeginIndex(icuPos.getBeginIndex());
-        jdkPos.setEndIndex(icuPos.getEndIndex());
-
-        return jdkPos;
-    }
-}
+/*
+ *******************************************************************************
+ * Copyright (C) 1996-2011, International Business Machines Corporation and    *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+
+package com.ibm.icu.text;
+
+import java.io.InvalidObjectException;
+import java.math.BigInteger;
+import java.text.FieldPosition;
+import java.text.Format;
+import java.text.ParseException;
+import java.text.ParsePosition;
+import java.util.Locale;
+import java.util.Set;
+
+import com.ibm.icu.util.Currency;
+import com.ibm.icu.util.CurrencyAmount;
+import com.ibm.icu.util.ULocale;
+import com.ibm.icu.util.ULocale.Category;
+
+/**
+ * {@icuenhanced java.text.NumberFormat}.{@icu _usage_}
+ *
+ * <code>NumberFormat</code> is the abstract base class for all number
+ * formats. This class provides the interface for formatting and parsing
+ * numbers. <code>NumberFormat</code> also provides methods for determining
+ * which locales have number formats, and what their names are.
+ *
+ * <code>NumberFormat</code> helps you to format and parse numbers for any locale.
+ * Your code can be completely independent of the locale conventions for
+ * decimal points, thousands-separators, or even the particular decimal
+ * digits used, or whether the number format is even decimal.
+ *
+ * <p>
+ * To format a number for the current Locale, use one of the factory
+ * class methods:
+ * <blockquote>
+ * <pre>
+ *  myString = NumberFormat.getInstance().format(myNumber);
+ * </pre>
+ * </blockquote>
+ * If you are formatting multiple numbers, it is
+ * more efficient to get the format and use it multiple times so that
+ * the system doesn't have to fetch the information about the local
+ * language and country conventions multiple times.
+ * <blockquote>
+ * <pre>
+ * NumberFormat nf = NumberFormat.getInstance();
+ * for (int i = 0; i < a.length; ++i) {
+ *     output.println(nf.format(myNumber[i]) + "; ");
+ * }
+ * </pre>
+ * </blockquote>
+ * To format a number for a different Locale, specify it in the
+ * call to <code>getInstance</code>.
+ * <blockquote>
+ * <pre>
+ * NumberFormat nf = NumberFormat.getInstance(Locale.FRENCH);
+ * </pre>
+ * </blockquote>
+ * You can also use a <code>NumberFormat</code> to parse numbers:
+ * <blockquote>
+ * <pre>
+ * myNumber = nf.parse(myString);
+ * </pre>
+ * </blockquote>
+ * Use <code>getInstance</code> or <code>getNumberInstance</code> to get the
+ * normal number format. Use <code>getIntegerInstance</code> to get an
+ * integer number format. Use <code>getCurrencyInstance</code> to get the
+ * currency number format. And use <code>getPercentInstance</code> to get a
+ * format for displaying percentages. With this format, a fraction like
+ * 0.53 is displayed as 53%.
+ *
+ * <p>
+ * Starting from ICU 4.2, you can use getInstance() by passing in a 'style'
+ * as parameter to get the correct instance.
+ * For example,
+ * use getInstance(...NUMBERSTYLE) to get the normal number format,
+ * getInstance(...PERCENTSTYLE) to get a format for displaying percentage,
+ * getInstance(...SCIENTIFICSTYLE) to get a format for displaying scientific number,
+ * getInstance(...INTEGERSTYLE) to get an integer number format,
+ * getInstance(...CURRENCYSTYLE) to get the currency number format,
+ * in which the currency is represented by its symbol, for example, "$3.00".
+ * getInstance(...ISOCURRENCYSTYLE)  to get the currency number format,
+ * in which the currency is represented by its ISO code, for example "USD3.00".
+ * getInstance(...PLURALCURRENCYSTYLE) to get the currency number format,
+ * in which the currency is represented by its full name in plural format,
+ * for example, "3.00 US dollars" or "1.00 US dollar".
+ *
+ *
+ * <p>
+ * You can also control the display of numbers with such methods as
+ * <code>setMinimumFractionDigits</code>.
+ * If you want even more control over the format or parsing,
+ * or want to give your users more control,
+ * you can try casting the <code>NumberFormat</code> you get from the factory methods
+ * to a <code>DecimalFormat</code>. This will work for the vast majority
+ * of locales; just remember to put it in a <code>try</code> block in case you
+ * encounter an unusual one.
+ *
+ * <p>
+ * NumberFormat is designed such that some controls
+ * work for formatting and others work for parsing.  The following is
+ * the detailed description for each these control methods,
+ * <p>
+ * setParseIntegerOnly : only affects parsing, e.g.
+ * if true,  "3456.78" -> 3456 (and leaves the parse position just after '6')
+ * if false, "3456.78" -> 3456.78 (and leaves the parse position just after '8')
+ * This is independent of formatting.  If you want to not show a decimal point
+ * where there might be no digits after the decimal point, use
+ * setDecimalSeparatorAlwaysShown on DecimalFormat.
+ * <p>
+ * You can also use forms of the <code>parse</code> and <code>format</code>
+ * methods with <code>ParsePosition</code> and <code>FieldPosition</code> to
+ * allow you to:
+ * <ul>
+ * <li> progressively parse through pieces of a string
+ * <li> align the decimal point and other areas
+ * </ul>
+ * For example, you can align numbers in two ways:
+ * <ol>
+ * <li> If you are using a monospaced font with spacing for alignment,
+ *      you can pass the <code>FieldPosition</code> in your format call, with
+ *      <code>field</code> = <code>INTEGER_FIELD</code>. On output,
+ *      <code>getEndIndex</code> will be set to the offset between the
+ *      last character of the integer and the decimal. Add
+ *      (desiredSpaceCount - getEndIndex) spaces at the front of the string.
+ *
+ * <li> If you are using proportional fonts,
+ *      instead of padding with spaces, measure the width
+ *      of the string in pixels from the start to <code>getEndIndex</code>.
+ *      Then move the pen by
+ *      (desiredPixelWidth - widthToAlignmentPoint) before drawing the text.
+ *      It also works where there is no decimal, but possibly additional
+ *      characters at the end, e.g., with parentheses in negative
+ *      numbers: "(12)" for -12.
+ * </ol>
+ *
+ * <h4>Synchronization</h4>
+ * <p>
+ * Number formats are generally not synchronized. It is recommended to create
+ * separate format instances for each thread. If multiple threads access a format
+ * concurrently, it must be synchronized externally.
+ * <p>
+ *
+ * <h4>DecimalFormat</h4>
+ * <p>DecimalFormat is the concrete implementation of NumberFormat, and the
+ * NumberFormat API is essentially an abstraction from DecimalFormat's API.
+ * Refer to DecimalFormat for more information about this API.</p>
+ *
+ * see          DecimalFormat
+ * see          java.text.ChoiceFormat
+ * @author       Mark Davis
+ * @author       Helena Shih
+ * @author       Alan Liu
+ * @stable ICU 2.0
+ */
+public class NumberFormat extends Format {
+    private static final long serialVersionUID = 1;
+
+    /**
+     * @internal
+     */
+    public final java.text.NumberFormat numberFormat;
+        
+    /**
+     * @internal
+     * @param delegate the NumberFormat to which to delegate
+     */
+    public NumberFormat(java.text.NumberFormat delegate) {
+        this.numberFormat = delegate;
+    }
+
+    /**
+     * {@icu} Constant to specify normal number style of format.
+     * @stable ICU 4.2
+     */
+    public static final int NUMBERSTYLE = 0;
+    /**
+     * {@icu} Constant to specify currency style of format which uses currency symbol
+     * to represent currency, for example: "$3.00".
+     * @stable ICU 4.2
+     */
+    public static final int CURRENCYSTYLE = 1;
+    /**
+     * {@icu} Constant to specify a style of format to display percent.
+     * @stable ICU 4.2
+     */
+    public static final int PERCENTSTYLE = 2;
+    /**
+     * {@icu} Constant to specify a style of format to display scientific number.
+     * @stable ICU 4.2
+     */
+    public static final int SCIENTIFICSTYLE = 3;
+    /**
+     * {@icu} Constant to specify a integer number style format.
+     * @stable ICU 4.2
+     */
+    public static final int INTEGERSTYLE = 4;
+    /**
+     * {@icu} Constant to specify currency style of format which uses currency
+     * ISO code to represent currency, for example: "USD3.00".
+     * @stable ICU 4.2
+     */
+    public static final int ISOCURRENCYSTYLE = 5;
+    /**
+     * {@icu} Constant to specify currency style of format which uses currency
+     * long name with plural format to represent currency, for example,
+     * "3.00 US Dollars".
+     * @stable ICU 4.2
+     */
+    public static final int PLURALCURRENCYSTYLE = 6;
+
+    /**
+     * Field constant used to construct a FieldPosition object. Signifies that
+     * the position of the integer part of a formatted number should be returned.
+     * @see java.text.FieldPosition
+     * @stable ICU 2.0
+     */
+    public static final int INTEGER_FIELD = 0;
+
+    /**
+     * Field constant used to construct a FieldPosition object. Signifies that
+     * the position of the fraction part of a formatted number should be returned.
+     * @see java.text.FieldPosition
+     * @stable ICU 2.0
+     */
+    public static final int FRACTION_FIELD = 1;
+
+    /**
+     * Formats a number and appends the resulting text to the given string buffer.
+     * {@icunote} recognizes <code>BigInteger</code>
+     * and <code>BigDecimal</code> objects.
+     * @see java.text.Format#format(Object, StringBuffer, FieldPosition)
+     * @stable ICU 2.0
+     */
+    public StringBuffer format(Object number,
+                               StringBuffer toAppendTo,
+                               FieldPosition pos) {
+        FieldPosition jdkPos = toJDKFieldPosition(pos);
+        StringBuffer buf = numberFormat.format(number, toAppendTo, jdkPos);
+        if (jdkPos != null) {
+            pos.setBeginIndex(jdkPos.getBeginIndex());
+            pos.setEndIndex(jdkPos.getEndIndex());
+        }
+        return buf;
+    }
+
+    /**
+     * Parses text from a string to produce a number.
+     * @param source the String to parse
+     * @param parsePosition the position at which to start the parse
+     * @return the parsed number, or null
+     * @see java.text.NumberFormat#parseObject(String, ParsePosition)
+     * @stable ICU 2.0
+     */
+    public final Object parseObject(String source,
+                                    ParsePosition parsePosition) {
+        return numberFormat.parse(source, parsePosition);
+    }
+
+    /**
+     * Specialization of format.
+     * @see java.text.Format#format(Object)
+     * @stable ICU 2.0
+     */
+    public final String format(double number) {
+        return numberFormat.format(number);
+    }
+
+    /**
+     * Specialization of format.
+     * @see java.text.Format#format(Object)
+     * @stable ICU 2.0
+     */
+    public final String format(long number) {
+        return numberFormat.format(number);
+    }
+
+    /**
+     * {@icu} Convenience method to format a BigInteger.
+     * @stable ICU 2.0
+     */
+    public final String format(BigInteger number) {
+        return numberFormat.format(number);
+    }
+
+    /**
+     * Convenience method to format a BigDecimal.
+     * @stable ICU 2.0
+     */
+    public final String format(java.math.BigDecimal number) {
+        return numberFormat.format(number);
+    }
+
+    /**
+     * {@icu} Convenience method to format an ICU BigDecimal.
+     * @stable ICU 2.0
+     */
+    public final String format(com.ibm.icu.math.BigDecimal number) {
+        return numberFormat.format(number.toBigDecimal());
+    }
+
+    /**
+     * {@icu} Convenience method to format a CurrencyAmount.
+     * @stable ICU 3.0
+     */
+    public final String format(CurrencyAmount currAmt) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Specialization of format.
+     * @see java.text.Format#format(Object, StringBuffer, FieldPosition)
+     * @stable ICU 2.0
+     */
+    public StringBuffer format(double number,
+                                        StringBuffer toAppendTo,
+                                        FieldPosition pos) {
+        FieldPosition jdkPos = toJDKFieldPosition(pos);
+        StringBuffer buf = numberFormat.format(number, toAppendTo, jdkPos);
+        pos.setBeginIndex(jdkPos.getBeginIndex());
+        pos.setEndIndex(jdkPos.getEndIndex());
+        return buf;
+    }
+
+    /**
+     * Specialization of format.
+     * @see java.text.Format#format(Object, StringBuffer, FieldPosition)
+     * @stable ICU 2.0
+     */
+    public StringBuffer format(long number,
+                                        StringBuffer toAppendTo,
+                                        FieldPosition pos) {
+        FieldPosition jdkPos = toJDKFieldPosition(pos);
+        StringBuffer buf = numberFormat.format(number, toAppendTo, jdkPos);
+        pos.setBeginIndex(jdkPos.getBeginIndex());
+        pos.setEndIndex(jdkPos.getEndIndex());
+        return buf;
+    }
+    /**
+     * {@icu} Formats a BigInteger. Specialization of format.
+     * @see java.text.Format#format(Object, StringBuffer, FieldPosition)
+     * @stable ICU 2.0
+     */
+    public StringBuffer format(BigInteger number,
+                                        StringBuffer toAppendTo,
+                                        FieldPosition pos) {
+        FieldPosition jdkPos = toJDKFieldPosition(pos);
+        StringBuffer buf = numberFormat.format(number, toAppendTo, jdkPos);
+        pos.setBeginIndex(jdkPos.getBeginIndex());
+        pos.setEndIndex(jdkPos.getEndIndex());
+        return buf;
+    }
+    /**
+     * {@icu} Formats a BigDecimal. Specialization of format.
+     * @see java.text.Format#format(Object, StringBuffer, FieldPosition)
+     * @stable ICU 2.0
+     */
+    public StringBuffer format(java.math.BigDecimal number,
+                                        StringBuffer toAppendTo,
+                                        FieldPosition pos) {
+        FieldPosition jdkPos = toJDKFieldPosition(pos);
+        StringBuffer buf = numberFormat.format(number, toAppendTo, jdkPos);
+        pos.setBeginIndex(jdkPos.getBeginIndex());
+        pos.setEndIndex(jdkPos.getEndIndex());
+        return buf;
+    }
+    /**
+     * {@icu} Formats an ICU BigDecimal. Specialization of format.
+     * @see java.text.Format#format(Object, StringBuffer, FieldPosition)
+     * @stable ICU 2.0
+     */
+    public StringBuffer format(com.ibm.icu.math.BigDecimal number,
+                                        StringBuffer toAppendTo,
+                                        FieldPosition pos) {
+        FieldPosition jdkPos = toJDKFieldPosition(pos);
+        StringBuffer buf = numberFormat.format(number.toBigDecimal(), toAppendTo, jdkPos);
+        pos.setBeginIndex(jdkPos.getBeginIndex());
+        pos.setEndIndex(jdkPos.getEndIndex());
+        return buf;
+    }
+
+    /**
+     * {@icu} Formats a CurrencyAmount. Specialization of format.
+     * @see java.text.Format#format(Object, StringBuffer, FieldPosition)
+     * @stable ICU 3.0
+     */
+    public StringBuffer format(CurrencyAmount currAmt,
+                               StringBuffer toAppendTo,
+                               FieldPosition pos) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Returns a Long if possible (e.g., within the range [Long.MIN_VALUE,
+     * Long.MAX_VALUE] and with no decimals), otherwise a Double.
+     * If IntegerOnly is set, will stop at a decimal
+     * point (or equivalent; e.g., for rational numbers "1 2/3", will stop
+     * after the 1).
+     * Does not throw an exception; if no object can be parsed, index is
+     * unchanged!
+     * @see #isParseIntegerOnly
+     * @see java.text.Format#parseObject(String, ParsePosition)
+     * @stable ICU 2.0
+     */
+    public Number parse(String text, ParsePosition parsePosition) {
+        return numberFormat.parse(text, parsePosition);
+    }
+
+    /**
+     * Parses text from the beginning of the given string to produce a number.
+     * The method might not use the entire text of the given string.
+     *
+     * @param text A String whose beginning should be parsed.
+     * @return A Number parsed from the string.
+     * @throws ParseException if the beginning of the specified string
+     * cannot be parsed.
+     * @see #format
+     * @stable ICU 2.0
+     */
+    public Number parse(String text) throws ParseException {
+        return numberFormat.parse(text);
+    }
+
+    /**
+     * Parses text from the given string as a CurrencyAmount.  Unlike
+     * the parse() method, this method will attempt to parse a generic
+     * currency name, searching for a match of this object's locale's
+     * currency display names, or for a 3-letter ISO currency code.
+     * This method will fail if this format is not a currency format,
+     * that is, if it does not contain the currency pattern symbol
+     * (U+00A4) in its prefix or suffix.
+     *
+     * @param text the string to parse
+     * @param pos input-output position; on input, the position within
+     * text to match; must have 0 <= pos.getIndex() < text.length();
+     * on output, the position after the last matched character. If
+     * the parse fails, the position in unchanged upon output.
+     * @return a CurrencyAmount, or null upon failure
+     */
+    CurrencyAmount parseCurrency(String text, ParsePosition pos) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Returns true if this format will parse numbers as integers only.
+     * For example in the English locale, with ParseIntegerOnly true, the
+     * string "1234." would be parsed as the integer value 1234 and parsing
+     * would stop at the "." character.  The decimal separator accepted
+     * by the parse operation is locale-dependent and determined by the
+     * subclass.
+     * @return true if this will parse integers only
+     * @stable ICU 2.0
+     */
+    public boolean isParseIntegerOnly() {
+        return numberFormat.isParseIntegerOnly();
+    }
+
+    /**
+     * Sets whether or not numbers should be parsed as integers only.
+     * @param value true if this should parse integers only
+     * @see #isParseIntegerOnly
+     * @stable ICU 2.0
+     */
+    public void setParseIntegerOnly(boolean value) {
+        numberFormat.setParseIntegerOnly(value);
+    }
+
+    /**
+     * {@icu} Sets whether strict parsing is in effect.  When this is true, the
+     * following conditions cause a parse failure (examples use the pattern "#,##0.#"):<ul>
+     * <li>Leading zeros<br>
+     * '00', '0123' fail the parse, but '0' and '0.001' pass</li>
+     * <li>Leading or doubled grouping separators<br>
+     * ',123' and '1,,234" fail</li>
+     * <li>Groups of incorrect length when grouping is used<br>
+     * '1,23' and '1234,567' fail, but '1234' passes</li>
+     * <li>Grouping separators used in numbers followed by exponents<br>
+     * '1,234E5' fails, but '1234E5' and '1,234E' pass ('E' is not an exponent when
+     * not followed by a number)</li>
+     * </ul>
+     * When strict parsing is off, leading zeros and all grouping separators are ignored.
+     * This is the default behavior.
+     * @param value True to enable strict parsing.  Default is false.
+     * @see #isParseStrict
+     * @stable ICU 3.6
+     */
+    public void setParseStrict(boolean value) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Returns whether strict parsing is in effect.
+     * @return true if strict parsing is in effect
+     * @see #setParseStrict
+     * @stable ICU 3.6
+     */
+    public boolean isParseStrict() {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    //============== Locale Stuff =====================
+
+    /**
+     * Returns the default number format for the current default locale.
+     * The default format is one of the styles provided by the other
+     * factory methods: getNumberInstance, getIntegerInstance,
+     * getCurrencyInstance or getPercentInstance.
+     * Exactly which one is locale-dependent.
+     * @stable ICU 2.0
+     */
+    //Bug 4408066 [Richard/GCL]
+    public final static NumberFormat getInstance() {
+        return getInstance(ULocale.getDefault(Category.FORMAT), NUMBERSTYLE);
+    }
+
+    /**
+     * Returns the default number format for the specified locale.
+     * The default format is one of the styles provided by the other
+     * factory methods: getNumberInstance, getCurrencyInstance or getPercentInstance.
+     * Exactly which one is locale-dependent.
+     * @stable ICU 2.0
+     */
+    public static NumberFormat getInstance(Locale inLocale) {
+        return getInstance(ULocale.forLocale(inLocale), NUMBERSTYLE);
+    }
+
+    /**
+     * {@icu} Returns the default number format for the specified locale.
+     * The default format is one of the styles provided by the other
+     * factory methods: getNumberInstance, getCurrencyInstance or getPercentInstance.
+     * Exactly which one is locale-dependent.
+     * @stable ICU 3.2
+     */
+    public static NumberFormat getInstance(ULocale inLocale) {
+        return getInstance(inLocale, NUMBERSTYLE);
+    }
+
+    /**
+     * {@icu} Returns a specific style number format for default locale.
+     * @param style  number format style
+     * @stable ICU 4.2
+     */
+    public final static NumberFormat getInstance(int style) {
+        return getInstance(ULocale.getDefault(Category.FORMAT), style);
+    }
+
+    /**
+     * {@icu} Returns a specific style number format for a specific locale.
+     * @param inLocale  the specific locale.
+     * @param style     number format style
+     * @stable ICU 4.2
+     */
+    public static NumberFormat getInstance(Locale inLocale, int style) {
+        return getInstance(ULocale.forLocale(inLocale), style);
+    }
+
+
+    /**
+     * Returns a general-purpose number format for the current default locale.
+     * @stable ICU 2.0
+     */
+    public final static NumberFormat getNumberInstance() {
+        return getInstance(ULocale.getDefault(Category.FORMAT), NUMBERSTYLE);
+    }
+
+    /**
+     * Returns a general-purpose number format for the specified locale.
+     * @stable ICU 2.0
+     */
+    public static NumberFormat getNumberInstance(Locale inLocale) {
+        return getInstance(ULocale.forLocale(inLocale), NUMBERSTYLE);
+    }
+
+    /**
+     * {@icu} Returns a general-purpose number format for the specified locale.
+     * @stable ICU 3.2
+     */
+    public static NumberFormat getNumberInstance(ULocale inLocale) {
+        return getInstance(inLocale, NUMBERSTYLE);
+    }
+
+    /**
+     * Returns an integer number format for the current default locale. The
+     * returned number format is configured to round floating point numbers
+     * to the nearest integer using IEEE half-even rounding (see {@link
+     * com.ibm.icu.math.BigDecimal#ROUND_HALF_EVEN ROUND_HALF_EVEN}) for formatting,
+     * and to parse only the integer part of an input string (see {@link
+     * #isParseIntegerOnly isParseIntegerOnly}).
+     *
+     * @return a number format for integer values
+     * @stable ICU 2.0
+     */
+    //Bug 4408066 [Richard/GCL]
+    public final static NumberFormat getIntegerInstance() {
+        return getInstance(ULocale.getDefault(Category.FORMAT), INTEGERSTYLE);
+    }
+
+    /**
+     * Returns an integer number format for the specified locale. The
+     * returned number format is configured to round floating point numbers
+     * to the nearest integer using IEEE half-even rounding (see {@link
+     * com.ibm.icu.math.BigDecimal#ROUND_HALF_EVEN ROUND_HALF_EVEN}) for formatting,
+     * and to parse only the integer part of an input string (see {@link
+     * #isParseIntegerOnly isParseIntegerOnly}).
+     *
+     * @param inLocale the locale for which a number format is needed
+     * @return a number format for integer values
+     * @stable ICU 2.0
+     */
+    //Bug 4408066 [Richard/GCL]
+    public static NumberFormat getIntegerInstance(Locale inLocale) {
+        return getInstance(ULocale.forLocale(inLocale), INTEGERSTYLE);
+    }
+
+    /**
+     * {@icu} Returns an integer number format for the specified locale. The
+     * returned number format is configured to round floating point numbers
+     * to the nearest integer using IEEE half-even rounding (see {@link
+     * com.ibm.icu.math.BigDecimal#ROUND_HALF_EVEN ROUND_HALF_EVEN}) for formatting,
+     * and to parse only the integer part of an input string (see {@link
+     * #isParseIntegerOnly isParseIntegerOnly}).
+     *
+     * @param inLocale the locale for which a number format is needed
+     * @return a number format for integer values
+     * @stable ICU 3.2
+     */
+    public static NumberFormat getIntegerInstance(ULocale inLocale) {
+        return getInstance(inLocale, INTEGERSTYLE);
+    }
+
+    /**
+     * Returns a currency format for the current default locale.
+     * @return a number format for currency
+     * @stable ICU 2.0
+     */
+    public final static NumberFormat getCurrencyInstance() {
+        return getInstance(ULocale.getDefault(Category.FORMAT), CURRENCYSTYLE);
+    }
+
+    /**
+     * Returns a currency format for the specified locale.
+     * @return a number format for currency
+     * @stable ICU 2.0
+     */
+    public static NumberFormat getCurrencyInstance(Locale inLocale) {
+        return getInstance(ULocale.forLocale(inLocale), CURRENCYSTYLE);
+    }
+
+    /**
+     * {@icu} Returns a currency format for the specified locale.
+     * @return a number format for currency
+     * @stable ICU 3.2
+     */
+    public static NumberFormat getCurrencyInstance(ULocale inLocale) {
+        return getInstance(inLocale, CURRENCYSTYLE);
+    }
+
+    /**
+     * Returns a percentage format for the current default locale.
+     * @return a number format for percents
+     * @stable ICU 2.0
+     */
+    public final static NumberFormat getPercentInstance() {
+        return getInstance(ULocale.getDefault(Category.FORMAT), PERCENTSTYLE);
+    }
+
+    /**
+     * Returns a percentage format for the specified locale.
+     * @return a number format for percents
+     * @stable ICU 2.0
+     */
+    public static NumberFormat getPercentInstance(Locale inLocale) {
+        return getInstance(ULocale.forLocale(inLocale), PERCENTSTYLE);
+    }
+
+    /**
+     * {@icu} Returns a percentage format for the specified locale.
+     * @return a number format for percents
+     * @stable ICU 3.2
+     */
+    public static NumberFormat getPercentInstance(ULocale inLocale) {
+        return getInstance(inLocale, PERCENTSTYLE);
+    }
+
+    /**
+     * {@icu} Returns a scientific format for the current default locale.
+     * @return a scientific number format
+     * @stable ICU 2.0
+     */
+    public final static NumberFormat getScientificInstance() {
+        return getInstance(ULocale.getDefault(Category.FORMAT), SCIENTIFICSTYLE);
+    }
+
+    /**
+     * {@icu} Returns a scientific format for the specified locale.
+     * @return a scientific number format
+     * @stable ICU 2.0
+     */
+    public static NumberFormat getScientificInstance(Locale inLocale) {
+        return getInstance(ULocale.forLocale(inLocale), SCIENTIFICSTYLE);
+    }
+
+    /**
+     * {@icu} Returns a scientific format for the specified locale.
+     * @return a scientific number format
+     * @stable ICU 3.2
+     */
+    public static NumberFormat getScientificInstance(ULocale inLocale) {
+        return getInstance(inLocale, SCIENTIFICSTYLE);
+    }
+
+    /**
+     * A NumberFormatFactory is used to register new number formats.  The factory
+     * should be able to create any of the predefined formats for each locale it
+     * supports.  When registered, the locales it supports extend or override the
+     * locales already supported by ICU.
+     *
+     * <p><b>Note:</b> as of ICU4J 3.2, the default API for NumberFormatFactory uses
+     * ULocale instead of Locale.  Instead of overriding createFormat(Locale, int),
+     * new implementations should override createFactory(ULocale, int).  Note that
+     * one of these two methods <b>MUST</b> be overridden or else an infinite
+     * loop will occur.
+     *
+     * @stable ICU 2.6
+     */
+    public static abstract class NumberFormatFactory {
+        /**
+         * Value passed to format requesting a default number format.
+         * @stable ICU 2.6
+         */
+        public static final int FORMAT_NUMBER = NUMBERSTYLE;
+
+        /**
+         * Value passed to format requesting a currency format.
+         * @stable ICU 2.6
+         */
+        public static final int FORMAT_CURRENCY = CURRENCYSTYLE;
+
+        /**
+         * Value passed to format requesting a percent format.
+         * @stable ICU 2.6
+         */
+        public static final int FORMAT_PERCENT = PERCENTSTYLE;
+
+        /**
+         * Value passed to format requesting a scientific format.
+         * @stable ICU 2.6
+         */
+        public static final int FORMAT_SCIENTIFIC = SCIENTIFICSTYLE;
+
+        /**
+         * Value passed to format requesting an integer format.
+         * @stable ICU 2.6
+         */
+        public static final int FORMAT_INTEGER = INTEGERSTYLE;
+
+        /**
+         * Returns true if this factory is visible.  Default is true.
+         * If not visible, the locales supported by this factory will not
+         * be listed by getAvailableLocales.  This value must not change.
+         * @return true if the factory is visible.
+         * @stable ICU 2.6
+         */
+        public boolean visible() {
+            return true;
+        }
+
+        /**
+         * Returns an immutable collection of the locale names directly
+         * supported by this factory.
+         * @return the supported locale names.
+         * @stable ICU 2.6
+         */
+         public abstract Set<String> getSupportedLocaleNames();
+
+        /**
+         * Returns a number format of the appropriate type.  If the locale
+         * is not supported, return null.  If the locale is supported, but
+         * the type is not provided by this service, return null.  Otherwise
+         * return an appropriate instance of NumberFormat.
+         * <b>Note:</b> as of ICU4J 3.2, implementations should override
+         * this method instead of createFormat(Locale, int).
+         * @param loc the locale for which to create the format
+         * @param formatType the type of format
+         * @return the NumberFormat, or null.
+         * @stable ICU 3.2
+         */
+        public NumberFormat createFormat(ULocale loc, int formatType) {
+            return createFormat(loc.toLocale(), formatType);
+        }
+
+        /**
+         * Returns a number format of the appropriate type.  If the locale
+         * is not supported, return null.  If the locale is supported, but
+         * the type is not provided by this service, return null.  Otherwise
+         * return an appropriate instance of NumberFormat.
+         * <b>Note:</b> as of ICU4J 3.2, createFormat(ULocale, int) should be
+         * overridden instead of this method.  This method is no longer
+         * abstract and delegates to that method.
+         * @param loc the locale for which to create the format
+         * @param formatType the type of format
+         * @return the NumberFormat, or null.
+         * @stable ICU 2.6
+         */
+        public NumberFormat createFormat(Locale loc, int formatType) {
+            return createFormat(ULocale.forLocale(loc), formatType);
+        }
+
+        /**
+         * @stable ICU 2.6
+         */
+        protected NumberFormatFactory() {
+        }
+    }
+
+    /**
+     * Returns the list of Locales for which NumberFormats are available.
+     * @return the available locales
+     * @stable ICU 2.0
+     */
+    public static Locale[] getAvailableLocales() {
+        return java.text.NumberFormat.getAvailableLocales();
+    }
+
+    /**
+     * {@icu} Returns the list of Locales for which NumberFormats are available.
+     * @return the available locales
+     * @draft ICU 3.2 (retain)
+     * @provisional This API might change or be removed in a future release.
+     */
+    public static ULocale[] getAvailableULocales() {
+        if (availableULocales == null) {
+            synchronized (NumberFormat.class) {
+                if (availableULocales == null) {
+                    Locale[] locales = java.text.NumberFormat.getAvailableLocales();
+                    ULocale[] ulocales = new ULocale[locales.length];
+                    for (int i = 0; i < locales.length; ++i) {
+                        ulocales[i] = ULocale.forLocale(locales[i]);
+                    }
+                    availableULocales = ulocales;
+                }
+            }
+        }
+        return (ULocale[])availableULocales.clone();
+    }
+    private static volatile ULocale[] availableULocales;
+
+    /**
+     * {@icu} Registers a new NumberFormatFactory.  The factory is adopted by
+     * the service and must not be modified.  The returned object is a
+     * key that can be used to unregister this factory.
+     * @param factory the factory to register
+     * @return a key with which to unregister the factory
+     * @stable ICU 2.6
+     */
+    public static Object registerFactory(NumberFormatFactory factory) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Unregisters the factory or instance associated with this key (obtained from
+     * registerInstance or registerFactory).
+     * @param registryKey a key obtained from registerFactory
+     * @return true if the object was successfully unregistered
+     * @stable ICU 2.6
+     */
+    public static boolean unregister(Object registryKey) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Overrides hashCode.
+     * @stable ICU 2.0
+     */
+    public int hashCode() {
+        return numberFormat.hashCode();
+    }
+
+    /**
+     * Overrides equals.
+     * Two NumberFormats are equal if they are of the same class
+     * and the settings (groupingUsed, parseIntegerOnly, maximumIntegerDigits, etc.
+     * are equal.
+     * @param obj the object to compare against
+     * @return true if the object is equal to this.
+     * @stable ICU 2.0
+     */
+    public boolean equals(Object obj) {
+        try {
+            return numberFormat.equals(((NumberFormat)obj).numberFormat);
+        }
+        catch (Exception e) {
+            return false;
+        }
+    }
+
+    /**
+     * Overrides clone.
+     * @stable ICU 2.0
+     */
+    public Object clone() {
+        return new NumberFormat((java.text.NumberFormat)numberFormat.clone());
+    }
+
+    /**
+     * Returns true if grouping is used in this format. For example, in the
+     * en_US locale, with grouping on, the number 1234567 will be formatted
+     * as "1,234,567". The grouping separator as well as the size of each group
+     * is locale-dependent and is determined by subclasses of NumberFormat.
+     * Grouping affects both parsing and formatting.
+     * @return true if grouping is used
+     * @see #setGroupingUsed
+     * @stable ICU 2.0
+     */
+    public boolean isGroupingUsed() {
+        return numberFormat.isGroupingUsed();
+    }
+
+    /**
+     * Sets whether or not grouping will be used in this format.  Grouping
+     * affects both parsing and formatting.
+     * @see #isGroupingUsed
+     * @param newValue true to use grouping.
+     * @stable ICU 2.0
+     */
+    public void setGroupingUsed(boolean newValue) {
+        numberFormat.setGroupingUsed(newValue);
+    }
+
+    /**
+     * Returns the maximum number of digits allowed in the integer portion of a
+     * number.  The default value is 40, which subclasses can override.
+     * When formatting, the exact behavior when this value is exceeded is
+     * subclass-specific.  When parsing, this has no effect.
+     * @return the maximum number of integer digits
+     * @see #setMaximumIntegerDigits
+     * @stable ICU 2.0
+     */
+    public int getMaximumIntegerDigits() {
+        return numberFormat.getMaximumIntegerDigits();
+    }
+
+    /**
+     * Sets the maximum number of digits allowed in the integer portion of a
+     * number. This must be >= minimumIntegerDigits.  If the
+     * new value for maximumIntegerDigits is less than the current value
+     * of minimumIntegerDigits, then minimumIntegerDigits will also be set to
+     * the new value.
+     * @param newValue the maximum number of integer digits to be shown; if
+     * less than zero, then zero is used.  Subclasses might enforce an
+     * upper limit to this value appropriate to the numeric type being formatted.
+     * @see #getMaximumIntegerDigits
+     * @stable ICU 2.0
+     */
+    public void setMaximumIntegerDigits(int newValue) {
+        numberFormat.setMaximumIntegerDigits(newValue);
+    }
+
+    /**
+     * Returns the minimum number of digits allowed in the integer portion of a
+     * number.  The default value is 1, which subclasses can override.
+     * When formatting, if this value is not reached, numbers are padded on the
+     * left with the locale-specific '0' character to ensure at least this
+     * number of integer digits.  When parsing, this has no effect.
+     * @return the minimum number of integer digits
+     * @see #setMinimumIntegerDigits
+     * @stable ICU 2.0
+     */
+    public int getMinimumIntegerDigits() {
+        return numberFormat.getMinimumIntegerDigits();
+    }
+
+    /**
+     * Sets the minimum number of digits allowed in the integer portion of a
+     * number.  This must be <= maximumIntegerDigits.  If the
+     * new value for minimumIntegerDigits is more than the current value
+     * of maximumIntegerDigits, then maximumIntegerDigits will also be set to
+     * the new value.
+     * @param newValue the minimum number of integer digits to be shown; if
+     * less than zero, then zero is used. Subclasses might enforce an
+     * upper limit to this value appropriate to the numeric type being formatted.
+     * @see #getMinimumIntegerDigits
+     * @stable ICU 2.0
+     */
+    public void setMinimumIntegerDigits(int newValue) {
+        numberFormat.setMinimumIntegerDigits(newValue);
+    }
+
+    /**
+     * Returns the maximum number of digits allowed in the fraction
+     * portion of a number.  The default value is 3, which subclasses
+     * can override.  When formatting, the exact behavior when this
+     * value is exceeded is subclass-specific.  When parsing, this has
+     * no effect.
+     * @return the maximum number of fraction digits
+     * @see #setMaximumFractionDigits
+     * @stable ICU 2.0
+     */
+    public int getMaximumFractionDigits() {
+        return numberFormat.getMaximumFractionDigits();
+    }
+
+    /**
+     * Sets the maximum number of digits allowed in the fraction portion of a
+     * number. This must be >= minimumFractionDigits.  If the
+     * new value for maximumFractionDigits is less than the current value
+     * of minimumFractionDigits, then minimumFractionDigits will also be set to
+     * the new value.
+     * @param newValue the maximum number of fraction digits to be shown; if
+     * less than zero, then zero is used. The concrete subclass may enforce an
+     * upper limit to this value appropriate to the numeric type being formatted.
+     * @see #getMaximumFractionDigits
+     * @stable ICU 2.0
+     */
+    public void setMaximumFractionDigits(int newValue) {
+        numberFormat.setMaximumFractionDigits(newValue);
+    }
+
+    /**
+     * Returns the minimum number of digits allowed in the fraction portion of a
+     * number.  The default value is 0, which subclasses can override.
+     * When formatting, if this value is not reached, numbers are padded on
+     * the right with the locale-specific '0' character to ensure at least
+     * this number of fraction digits.  When parsing, this has no effect.
+     * @return the minimum number of fraction digits
+     * @see #setMinimumFractionDigits
+     * @stable ICU 2.0
+     */
+    public int getMinimumFractionDigits() {
+        return numberFormat.getMinimumFractionDigits();
+    }
+
+    /**
+     * Sets the minimum number of digits allowed in the fraction portion of a
+     * number.  This must be <= maximumFractionDigits.  If the
+     * new value for minimumFractionDigits exceeds the current value
+     * of maximumFractionDigits, then maximumFractionDigits will also be set to
+     * the new value.
+     * @param newValue the minimum number of fraction digits to be shown; if
+     * less than zero, then zero is used.  Subclasses might enforce an
+     * upper limit to this value appropriate to the numeric type being formatted.
+     * @see #getMinimumFractionDigits
+     * @stable ICU 2.0
+     */
+    public void setMinimumFractionDigits(int newValue) {
+        numberFormat.setMinimumFractionDigits(newValue);
+    }
+
+    /**
+     * Sets the <tt>Currency</tt> object used to display currency
+     * amounts.  This takes effect immediately, if this format is a
+     * currency format.  If this format is not a currency format, then
+     * the currency object is used if and when this object becomes a
+     * currency format.
+     * @param theCurrency new currency object to use.  May be null for
+     * some subclasses.
+     * @stable ICU 2.6
+     */
+    public void setCurrency(Currency theCurrency) {
+        numberFormat.setCurrency(theCurrency.currency);
+    }
+
+    /**
+     * Returns the <tt>Currency</tt> object used to display currency
+     * amounts.  This may be null.
+     * @stable ICU 2.6
+     */
+    public Currency getCurrency() {
+        return new Currency(numberFormat.getCurrency());
+    }
+
+    /**
+     * Returns the rounding mode used in this NumberFormat.  The default implementation of
+     * tis method in NumberFormat always throws <code>UnsupportedOperationException</code>.
+     * @return A rounding mode, between <code>BigDecimal.ROUND_UP</code>
+     * and <code>BigDecimal.ROUND_UNNECESSARY</code>.
+     * @see #setRoundingMode(int)
+     * @stable ICU 4.0
+     */
+    public int getRoundingMode() {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Set the rounding mode used in this NumberFormat.  The default implementation of
+     * tis method in NumberFormat always throws <code>UnsupportedOperationException</code>.
+     * @param roundingMode A rounding mode, between
+     * <code>BigDecimal.ROUND_UP</code> and
+     * <code>BigDecimal.ROUND_UNNECESSARY</code>.
+     * @see #getRoundingMode()
+     * @stable ICU 4.0
+     */
+    public void setRoundingMode(int roundingMode) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+
+    /**
+     * Returns a specific style number format for a specific locale.
+     * @param desiredLocale  the specific locale.
+     * @param choice         number format style
+     * @throws IllegalArgumentException  if choice is not one of
+     *                                   NUMBERSTYLE, CURRENCYSTYLE,
+     *                                   PERCENTSTYLE, SCIENTIFICSTYLE,
+     *                                   INTEGERSTYLE,
+     *                                   ISOCURRENCYSTYLE, PLURALCURRENCYSTYLE,
+     * @stable ICU 4.2
+     */
+    public static NumberFormat getInstance(ULocale desiredLocale, int choice) {
+        Locale locale = desiredLocale.toLocale();
+        java.text.NumberFormat nf = null;
+        switch (choice) {
+        case NUMBERSTYLE:
+            nf = java.text.NumberFormat.getInstance(locale);
+            break;
+        case INTEGERSTYLE:
+            nf = java.text.NumberFormat.getIntegerInstance(locale);
+            break;
+        case CURRENCYSTYLE:
+            nf = java.text.NumberFormat.getCurrencyInstance(locale);
+            break;
+        case PERCENTSTYLE:
+            nf = java.text.NumberFormat.getPercentInstance(locale);
+            break;
+        case SCIENTIFICSTYLE:
+            nf = new java.text.DecimalFormat("#E0",
+                    new java.text.DecimalFormatSymbols(locale));
+            nf.setMaximumFractionDigits(10);
+            break;
+        }
+        return new NumberFormat(nf);
+    }
+
+    /**
+     * Empty constructor.  Public for compatibily with JDK which lets the
+     * compiler generate a default public constructor even though this is
+     * an abstract class.
+     * @stable ICU 2.6
+     */
+    public NumberFormat() {
+        this(java.text.NumberFormat.getInstance());
+    }
+
+    /**
+     * The instances of this inner class are used as attribute keys and values
+     * in AttributedCharacterIterator that
+     * NumberFormat.formatToCharacterIterator() method returns.
+     * <p>
+     * There is no public constructor to this class, the only instances are the
+     * constants defined here.
+     * <p>
+     * @stable ICU 3.6
+     */
+    public static class Field extends Format.Field {
+        // generated by serialver from JDK 1.4.1_01
+        static final long serialVersionUID = -4516273749929385842L;
+
+        /**
+         * @stable ICU 3.6
+         */
+        public static final Field SIGN = new Field("sign");
+
+        /**
+         * @stable ICU 3.6
+         */
+        public static final Field INTEGER = new Field("integer");
+
+        /**
+         * @stable ICU 3.6
+         */
+        public static final Field FRACTION = new Field("fraction");
+
+        /**
+         * @stable ICU 3.6
+         */
+        public static final Field EXPONENT = new Field("exponent");
+
+        /**
+         * @stable ICU 3.6
+         */
+        public static final Field EXPONENT_SIGN = new Field("exponent sign");
+
+        /**
+         * @stable ICU 3.6
+         */
+        public static final Field EXPONENT_SYMBOL = new Field("exponent symbol");
+
+        /**
+         * @stable ICU 3.6
+         */
+        public static final Field DECIMAL_SEPARATOR = new Field("decimal separator");
+        /**
+         * @stable ICU 3.6
+         */
+        public static final Field GROUPING_SEPARATOR = new Field("grouping separator");
+
+        /**
+         * @stable ICU 3.6
+         */
+        public static final Field PERCENT = new Field("percent");
+
+        /**
+         * @stable ICU 3.6
+         */
+        public static final Field PERMILLE = new Field("per mille");
+
+        /**
+         * @stable ICU 3.6
+         */
+        public static final Field CURRENCY = new Field("currency");
+
+        /**
+         * Constructs a new instance of NumberFormat.Field with the given field
+         * name.
+         * @stable ICU 3.6
+         */
+        protected Field(String fieldName) {
+            super(fieldName);
+        }
+
+        /**
+         * serizalization method resolve instances to the constant
+         * NumberFormat.Field values
+         * @stable ICU 3.6
+         */
+        protected Object readResolve() throws InvalidObjectException {
+            if (this.getName().equals(INTEGER.getName()))
+                return INTEGER;
+            if (this.getName().equals(FRACTION.getName()))
+                return FRACTION;
+            if (this.getName().equals(EXPONENT.getName()))
+                return EXPONENT;
+            if (this.getName().equals(EXPONENT_SIGN.getName()))
+                return EXPONENT_SIGN;
+            if (this.getName().equals(EXPONENT_SYMBOL.getName()))
+                return EXPONENT_SYMBOL;
+            if (this.getName().equals(CURRENCY.getName()))
+                return CURRENCY;
+            if (this.getName().equals(DECIMAL_SEPARATOR.getName()))
+                return DECIMAL_SEPARATOR;
+            if (this.getName().equals(GROUPING_SEPARATOR.getName()))
+                return GROUPING_SEPARATOR;
+            if (this.getName().equals(PERCENT.getName()))
+                return PERCENT;
+            if (this.getName().equals(PERMILLE.getName()))
+                return PERMILLE;
+            if (this.getName().equals(SIGN.getName()))
+                return SIGN;
+
+            throw new InvalidObjectException("An invalid object.");
+        }
+    }
+
+    private static FieldPosition toJDKFieldPosition(FieldPosition icuPos) {
+        if (icuPos == null) {
+            return null;
+        }
+
+        int fieldID = icuPos.getField();
+        Format.Field fieldAttribute = icuPos.getFieldAttribute();
+
+        FieldPosition jdkPos = null;
+
+        if (fieldID >= 0) {
+            if (fieldID == FRACTION_FIELD) {
+                fieldID = java.text.NumberFormat.FRACTION_FIELD;
+            } else if (fieldID == INTEGER_FIELD) {
+                fieldID = java.text.NumberFormat.INTEGER_FIELD;
+            }
+        }
+
+        if (fieldAttribute != null) {
+            // map field
+            if (fieldAttribute.equals(Field.CURRENCY)) {
+                fieldAttribute = java.text.NumberFormat.Field.CURRENCY;
+            } else if (fieldAttribute.equals(Field.DECIMAL_SEPARATOR)) {
+                fieldAttribute = java.text.NumberFormat.Field.DECIMAL_SEPARATOR;
+            } else if (fieldAttribute.equals(Field.EXPONENT)) {
+                fieldAttribute = java.text.NumberFormat.Field.EXPONENT;
+            } else if (fieldAttribute.equals(Field.EXPONENT_SIGN)) {
+                fieldAttribute = java.text.NumberFormat.Field.EXPONENT_SIGN;
+            } else if (fieldAttribute.equals(Field.EXPONENT_SYMBOL)) {
+                fieldAttribute = java.text.NumberFormat.Field.EXPONENT_SYMBOL;
+            } else if (fieldAttribute.equals(Field.FRACTION)) {
+                fieldAttribute = java.text.NumberFormat.Field.FRACTION;
+            } else if (fieldAttribute.equals(Field.GROUPING_SEPARATOR)) {
+                fieldAttribute = java.text.NumberFormat.Field.GROUPING_SEPARATOR;
+            } else if (fieldAttribute.equals(Field.INTEGER)) {
+                fieldAttribute = java.text.NumberFormat.Field.INTEGER;
+            } else if (fieldAttribute.equals(Field.PERCENT)) {
+                fieldAttribute = java.text.NumberFormat.Field.PERCENT;
+            } else if (fieldAttribute.equals(Field.PERMILLE)) {
+                fieldAttribute = java.text.NumberFormat.Field.PERMILLE;
+            } else if (fieldAttribute.equals(Field.SIGN)) {
+                fieldAttribute = java.text.NumberFormat.Field.SIGN;
+            }
+
+            jdkPos = new FieldPosition(fieldAttribute, fieldID);
+        } else {
+            jdkPos = new FieldPosition(fieldID);
+        }
+
+        jdkPos.setBeginIndex(icuPos.getBeginIndex());
+        jdkPos.setEndIndex(icuPos.getEndIndex());
+
+        return jdkPos;
+    }
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/RawCollationKey.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/RawCollationKey.java
index 71fcb59..45316dc 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/RawCollationKey.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/RawCollationKey.java
@@ -1,14 +1,14 @@
-/*
- *******************************************************************************
- * Copyright (C) 2011, International Business Machines Corporation and         *
- * others. All Rights Reserved.                                                *
- *******************************************************************************
- */
-package com.ibm.icu.text;
-
-/*
- * Empty stub
- */
-public class RawCollationKey {
-    private RawCollationKey() {}
-}
+/*
+ *******************************************************************************
+ * Copyright (C) 2011, International Business Machines Corporation and         *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+package com.ibm.icu.text;
+
+/*
+ * Empty stub
+ */
+public class RawCollationKey {
+    private RawCollationKey() {}
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/SimpleDateFormat.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/SimpleDateFormat.java
index befcaa6..e8e5785 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/SimpleDateFormat.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/SimpleDateFormat.java
@@ -1,514 +1,514 @@
-/*
- *******************************************************************************
- * Copyright (C) 1996-2011, International Business Machines Corporation and    *
- * others. All Rights Reserved.                                                *
- *******************************************************************************
- */
-
-package com.ibm.icu.text;
-
-import java.text.AttributedCharacterIterator;
-import java.text.AttributedCharacterIterator.Attribute;
-import java.text.AttributedString;
-import java.text.CharacterIterator;
-import java.text.FieldPosition;
-import java.text.ParsePosition;
-import java.util.Date;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import com.ibm.icu.util.Calendar;
-import com.ibm.icu.util.ULocale;
-
-
-/**
- * {@icuenhanced java.text.SimpleDateFormat}.{@icu _usage_}
- *
- * <p><code>SimpleDateFormat</code> is a concrete class for formatting and
- * parsing dates in a locale-sensitive manner. It allows for formatting
- * (date -> text), parsing (text -> date), and normalization.
- *
- * <p>
- * <code>SimpleDateFormat</code> allows you to start by choosing
- * any user-defined patterns for date-time formatting. However, you
- * are encouraged to create a date-time formatter with either
- * <code>getTimeInstance</code>, <code>getDateInstance</code>, or
- * <code>getDateTimeInstance</code> in <code>DateFormat</code>. Each
- * of these class methods can return a date/time formatter initialized
- * with a default format pattern. You may modify the format pattern
- * using the <code>applyPattern</code> methods as desired.
- * For more information on using these methods, see
- * {@link DateFormat}.
- *
- * <p>
- * <strong>Time Format Syntax:</strong>
- * <p>
- * To specify the time format use a <em>time pattern</em> string.
- * In this pattern, all ASCII letters are reserved as pattern letters,
- * which are defined as the following:
- * <blockquote>
- * <pre>
- * Symbol   Meaning                 Presentation        Example
- * ------   -------                 ------------        -------
- * G        era designator          (Text)              AD
- * y&#x2020;       year                    (Number)            1996
- * Y*       year (week of year)     (Number)            1997
- * u*       extended year           (Number)            4601
- * M        month in year           (Text & Number)     July & 07
- * d        day in month            (Number)            10
- * h        hour in am/pm (1~12)    (Number)            12
- * H        hour in day (0~23)      (Number)            0
- * m        minute in hour          (Number)            30
- * s        second in minute        (Number)            55
- * S        fractional second       (Number)            978
- * E        day of week             (Text)              Tuesday
- * e*       day of week (local 1~7) (Text & Number)     Tuesday & 2
- * D        day in year             (Number)            189
- * F        day of week in month    (Number)            2 (2nd Wed in July)
- * w        week in year            (Number)            27
- * W        week in month           (Number)            2
- * a        am/pm marker            (Text)              PM
- * k        hour in day (1~24)      (Number)            24
- * K        hour in am/pm (0~11)    (Number)            0
- * z        time zone               (Text)              Pacific Standard Time
- * Z        time zone (RFC 822)     (Number)            -0800
- * v        time zone (generic)     (Text)              Pacific Time
- * V        time zone (location)    (Text)              United States (Los Angeles)
- * g*       Julian day              (Number)            2451334
- * A*       milliseconds in day     (Number)            69540000
- * Q*       quarter in year         (Text & Number)     Q1 & 01
- * c*       stand alone day of week (Text & Number)     Tuesday & 2
- * L*       stand alone month       (Text & Number)     July & 07
- * q*       stand alone quarter     (Text & Number)     Q1 & 01
- * '        escape for text         (Delimiter)         'Date='
- * ''       single quote            (Literal)           'o''clock'
- * </pre>
- * </blockquote>
- * <tt><b>*</b></tt> These items are not supported by Java's SimpleDateFormat.<br>
- * <tt><b>&#x2020;</b></tt> ICU interprets a single 'y' differently than Java.</p>
- * <p>
- * The count of pattern letters determine the format.
- * <p>
- * <strong>(Text)</strong>: 4 or more pattern letters--use full form,
- * &lt; 4--use short or abbreviated form if one exists.
- * <p>
- * <strong>(Number)</strong>: the minimum number of digits. Shorter
- * numbers are zero-padded to this amount. Year is handled specially;
- * that is, if the count of 'y' is 2, the Year will be truncated to 2 digits.
- * (e.g., if "yyyy" produces "1997", "yy" produces "97".)
- * Unlike other fields, fractional seconds are padded on the right with zero.
- * <p>
- * <strong>(Text & Number)</strong>: 3 or over, use text, otherwise use number.
- * <p>
- * Any characters in the pattern that are not in the ranges of ['a'..'z']
- * and ['A'..'Z'] will be treated as quoted text. For instance, characters
- * like ':', '.', ' ', '#' and '@' will appear in the resulting time text
- * even they are not embraced within single quotes.
- * <p>
- * A pattern containing any invalid pattern letter will result in a thrown
- * exception during formatting or parsing.
- *
- * <p>
- * <strong>Examples Using the US Locale:</strong>
- * <blockquote>
- * <pre>
- * Format Pattern                         Result
- * --------------                         -------
- * "yyyy.MM.dd G 'at' HH:mm:ss vvvv" ->>  1996.07.10 AD at 15:08:56 Pacific Time
- * "EEE, MMM d, ''yy"                ->>  Wed, July 10, '96
- * "h:mm a"                          ->>  12:08 PM
- * "hh 'o''clock' a, zzzz"           ->>  12 o'clock PM, Pacific Daylight Time
- * "K:mm a, vvv"                     ->>  0:00 PM, PT
- * "yyyyy.MMMMM.dd GGG hh:mm aaa"    ->>  01996.July.10 AD 12:08 PM
- * </pre>
- * </blockquote>
- * <strong>Code Sample:</strong>
- * <blockquote>
- * <pre>
- * SimpleTimeZone pdt = new SimpleTimeZone(-8 * 60 * 60 * 1000, "PST");
- * pdt.setStartRule(Calendar.APRIL, 1, Calendar.SUNDAY, 2*60*60*1000);
- * pdt.setEndRule(Calendar.OCTOBER, -1, Calendar.SUNDAY, 2*60*60*1000);
- * <br>
- * // Format the current time.
- * SimpleDateFormat formatter
- *     = new SimpleDateFormat ("yyyy.MM.dd G 'at' hh:mm:ss a zzz");
- * Date currentTime_1 = new Date();
- * String dateString = formatter.format(currentTime_1);
- * <br>
- * // Parse the previous string back into a Date.
- * ParsePosition pos = new ParsePosition(0);
- * Date currentTime_2 = formatter.parse(dateString, pos);
- * </pre>
- * </blockquote>
- * In the example, the time value <code>currentTime_2</code> obtained from
- * parsing will be equal to <code>currentTime_1</code>. However, they may not be
- * equal if the am/pm marker 'a' is left out from the format pattern while
- * the "hour in am/pm" pattern symbol is used. This information loss can
- * happen when formatting the time in PM.
- *
- * <p>When parsing a date string using the abbreviated year pattern ("yy"),
- * SimpleDateFormat must interpret the abbreviated year
- * relative to some century.  It does this by adjusting dates to be
- * within 80 years before and 20 years after the time the SimpleDateFormat
- * instance is created. For example, using a pattern of "MM/dd/yy" and a
- * SimpleDateFormat instance created on Jan 1, 1997,  the string
- * "01/11/12" would be interpreted as Jan 11, 2012 while the string "05/04/64"
- * would be interpreted as May 4, 1964.
- * During parsing, only strings consisting of exactly two digits, as defined by
- * {@link com.ibm.icu.lang.UCharacter#isDigit(int)}, will be parsed into the default
- * century.
- * Any other numeric string, such as a one digit string, a three or more digit
- * string, or a two digit string that isn't all digits (for example, "-1"), is
- * interpreted literally.  So "01/02/3" or "01/02/003" are parsed, using the
- * same pattern, as Jan 2, 3 AD.  Likewise, "01/02/-3" is parsed as Jan 2, 4 BC.
- *
- * <p>If the year pattern does not have exactly two 'y' characters, the year is
- * interpreted literally, regardless of the number of digits.  So using the
- * pattern "MM/dd/yyyy", "01/11/12" parses to Jan 11, 12 A.D.
- *
- * <p>When numeric fields abut one another directly, with no intervening delimiter
- * characters, they constitute a run of abutting numeric fields.  Such runs are
- * parsed specially.  For example, the format "HHmmss" parses the input text
- * "123456" to 12:34:56, parses the input text "12345" to 1:23:45, and fails to
- * parse "1234".  In other words, the leftmost field of the run is flexible,
- * while the others keep a fixed width.  If the parse fails anywhere in the run,
- * then the leftmost field is shortened by one character, and the entire run is
- * parsed again. This is repeated until either the parse succeeds or the
- * leftmost field is one character in length.  If the parse still fails at that
- * point, the parse of the run fails.
- *
- * <p>For time zones that have no names, use strings GMT+hours:minutes or
- * GMT-hours:minutes.
- *
- * <p>The calendar defines what is the first day of the week, the first week
- * of the year, whether hours are zero based or not (0 vs 12 or 24), and the
- * time zone. There is one common decimal format to handle all the numbers;
- * the digit count is handled programmatically according to the pattern.
- *
- * <h4>Synchronization</h4>
- *
- * Date formats are not synchronized. It is recommended to create separate
- * format instances for each thread. If multiple threads access a format
- * concurrently, it must be synchronized externally.
- *
- * @see          com.ibm.icu.util.Calendar
- * @see          com.ibm.icu.util.GregorianCalendar
- * @see          com.ibm.icu.util.TimeZone
- * @see          DateFormat
- * @see          DateFormatSymbols
- * @see          DecimalFormat
- * @author       Mark Davis, Chen-Lieh Huang, Alan Liu
- * @stable ICU 2.0
- */
-public class SimpleDateFormat extends DateFormat {
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * Constructs a SimpleDateFormat using the default pattern for the default
-     * locale.  <b>Note:</b> Not all locales support SimpleDateFormat; for full
-     * generality, use the factory methods in the DateFormat class.
-     *
-     * @see DateFormat
-     * @stable ICU 2.0
-     */
-    public SimpleDateFormat() {
-        super(new java.text.SimpleDateFormat());
-    }
-
-    /**
-     * Constructs a SimpleDateFormat using the given pattern in the default
-     * locale.  <b>Note:</b> Not all locales support SimpleDateFormat; for full
-     * generality, use the factory methods in the DateFormat class.
-     * @stable ICU 2.0
-     */
-    public SimpleDateFormat(String pattern)
-    {
-        super(new java.text.SimpleDateFormat(pattern));
-    }
-
-    /**
-     * Constructs a SimpleDateFormat using the given pattern and locale.
-     * <b>Note:</b> Not all locales support SimpleDateFormat; for full
-     * generality, use the factory methods in the DateFormat class.
-     * @stable ICU 2.0
-     */
-    public SimpleDateFormat(String pattern, Locale loc)
-    {
-        super(new java.text.SimpleDateFormat(pattern, loc));
-    }
-
-    /**
-     * Constructs a SimpleDateFormat using the given pattern and locale.
-     * <b>Note:</b> Not all locales support SimpleDateFormat; for full
-     * generality, use the factory methods in the DateFormat class.
-     * @stable ICU 3.2
-     */
-    public SimpleDateFormat(String pattern, ULocale loc)
-    {
-        this(pattern, loc.toLocale());
-    }
-
-    /**
-     * Constructs a SimpleDateFormat using the given pattern , override and locale.
-     * @param pattern The pattern to be used
-     * @param override The override string.  A numbering system override string can take one of the following forms:
-     *     1). If just a numbering system name is specified, it applies to all numeric fields in the date format pattern.
-     *     2). To specify an alternate numbering system on a field by field basis, use the field letters from the pattern
-     *         followed by an = sign, followed by the numbering system name.  For example, to specify that just the year
-     *         be formatted using Hebrew digits, use the override "y=hebr".  Multiple overrides can be specified in a single
-     *         string by separating them with a semi-colon. For example, the override string "m=thai;y=deva" would format using
-     *         Thai digits for the month and Devanagari digits for the year.
-     * @param loc The locale to be used
-     * @stable ICU 4.2
-     */
-    public SimpleDateFormat(String pattern, String override, ULocale loc)
-    {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Constructs a SimpleDateFormat using the given pattern and
-     * locale-specific symbol data.
-     * Warning: uses default locale for digits!
-     * @stable ICU 2.0
-     */
-    public SimpleDateFormat(String pattern, DateFormatSymbols formatData)
-    {
-        super(new java.text.SimpleDateFormat(pattern, formatData.dfs));
-    }
-
-    /**
-     * Sets the 100-year period 2-digit years will be interpreted as being in
-     * to begin on the date the user specifies.
-     * @param startDate During parsing, two digit years will be placed in the range
-     * <code>startDate</code> to <code>startDate + 100 years</code>.
-     * @stable ICU 2.0
-     */
-    public void set2DigitYearStart(Date startDate) {
-        ((java.text.SimpleDateFormat)dateFormat).set2DigitYearStart(startDate);
-    }
-
-    /**
-     * Returns the beginning date of the 100-year period 2-digit years are interpreted
-     * as being within.
-     * @return the start of the 100-year period into which two digit years are
-     * parsed
-     * @stable ICU 2.0
-     */
-    public Date get2DigitYearStart() {
-        return ((java.text.SimpleDateFormat)dateFormat).get2DigitYearStart();
-    }
-
-    /**
-     * Formats a date or time, which is the standard millis
-     * since January 1, 1970, 00:00:00 GMT.
-     * <p>Example: using the US locale:
-     * "yyyy.MM.dd G 'at' HH:mm:ss zzz" ->> 1996.07.10 AD at 15:08:56 PDT
-     * @param cal the calendar whose date-time value is to be formatted into a date-time string
-     * @param toAppendTo where the new date-time text is to be appended
-     * @param pos the formatting position. On input: an alignment field,
-     * if desired. On output: the offsets of the alignment field.
-     * @return the formatted date-time string.
-     * @see DateFormat
-     * @stable ICU 2.0
-     */
-    public StringBuffer format(Calendar cal, StringBuffer toAppendTo,
-                               FieldPosition pos) {
-        StringBuffer result;
-        FieldPosition jdkPos = toJDKFieldPosition(pos);
-        synchronized(dateFormat) {
-            java.util.Calendar oldCal = dateFormat.getCalendar();
-            dateFormat.setCalendar(cal.calendar);
-            result = dateFormat.format(cal.getTime(), toAppendTo, jdkPos);
-            dateFormat.setCalendar(oldCal);
-        }
-        if (jdkPos != null) {
-            pos.setBeginIndex(jdkPos.getBeginIndex());
-            pos.setEndIndex(jdkPos.getEndIndex());
-        }
-        return result;
-    }
-
-    /**
-     * Overrides superclass method
-     * @stable ICU 2.0
-     */
-    public void setNumberFormat(NumberFormat newNumberFormat) {
-        super.setNumberFormat(newNumberFormat);
-    }
-
-    /**
-     * Overrides DateFormat
-     * @see DateFormat
-     * @stable ICU 2.0
-     */
-    public void parse(String text, Calendar cal, ParsePosition parsePos)
-    {
-        // Note: parsed time zone won't be set in the result calendar
-        cal.setTime(dateFormat.parse(text, parsePos));
-    }
-
-    /**
-     * Return a pattern string describing this date format.
-     * @stable ICU 2.0
-     */
-    public String toPattern() {
-        return ((java.text.SimpleDateFormat)dateFormat).toPattern();
-    }
-
-    /**
-     * Return a localized pattern string describing this date format.
-     * @stable ICU 2.0
-     */
-    public String toLocalizedPattern() {
-        return ((java.text.SimpleDateFormat)dateFormat).toLocalizedPattern();
-    }
-
-    /**
-     * Apply the given unlocalized pattern string to this date format.
-     * @stable ICU 2.0
-     */
-    public void applyPattern(String pat) {
-        ((java.text.SimpleDateFormat)dateFormat).applyPattern(pat);
-    }
-
-    /**
-     * Apply the given localized pattern string to this date format.
-     * @stable ICU 2.0
-     */
-    public void applyLocalizedPattern(String pat) {
-        ((java.text.SimpleDateFormat)dateFormat).applyLocalizedPattern(pat);
-    }
-
-    /**
-     * Gets the date/time formatting data.
-     * @return a copy of the date-time formatting data associated
-     * with this date-time formatter.
-     * @stable ICU 2.0
-     */
-    public DateFormatSymbols getDateFormatSymbols() {
-        return new DateFormatSymbols(((java.text.SimpleDateFormat)dateFormat).getDateFormatSymbols());
-    }
-
-    /**
-     * Allows you to set the date/time formatting data.
-     * @param newFormatSymbols the new symbols
-     * @stable ICU 2.0
-     */
-    public void setDateFormatSymbols(DateFormatSymbols newFormatSymbols) {
-        ((java.text.SimpleDateFormat)dateFormat).setDateFormatSymbols(newFormatSymbols.dfs);
-    }
-
-    // For clone to use
-    private SimpleDateFormat(java.text.SimpleDateFormat sdf) {
-        super(sdf);
-    }
-
-    /**
-     * Overrides Cloneable
-     * @stable ICU 2.0
-     */
-    public Object clone() {
-        return new SimpleDateFormat((java.text.SimpleDateFormat)dateFormat.clone());
-    }
-
-    /**
-     * Override hashCode.
-     * Generates the hash code for the SimpleDateFormat object
-     * @stable ICU 2.0
-     */
-    public int hashCode()
-    {
-        return super.hashCode();
-    }
-
-    /**
-     * Override equals.
-     * @stable ICU 2.0
-     */
-    public boolean equals(Object obj)
-    {
-        return super.equals(obj);
-    }
-
-    /**
-     * Format the object to an attributed string, and return the corresponding iterator
-     * Overrides superclass method.
-     *
-     * @param obj The object to format
-     * @return <code>AttributedCharacterIterator</code> describing the formatted value.
-     *
-     * @stable ICU 3.8
-     */
-    public AttributedCharacterIterator formatToCharacterIterator(Object obj) {
-        AttributedCharacterIterator it = dateFormat.formatToCharacterIterator(obj);
-
-        // Extract formatted String first
-        StringBuilder sb = new StringBuilder();
-        for (char c = it.first(); c != CharacterIterator.DONE; c = it.next()) {
-            sb.append(c);
-        }
-
-        // Create AttributedString
-        AttributedString attrstr = new AttributedString(sb.toString());
-
-        // Map JDK Field to ICU Field
-        int idx = 0;
-        it.first();
-        while (idx < it.getEndIndex()) {
-            int end = it.getRunLimit();
-            Map<Attribute, Object> attributes = it.getAttributes();
-            if (attributes != null) {
-                for (Entry<Attribute, Object> entry : attributes.entrySet()) {
-                    Attribute attr = entry.getKey();
-                    Object val = entry.getValue();
-                    if (attr.equals(java.text.DateFormat.Field.AM_PM)) {
-                        val = attr = Field.AM_PM;
-                    } else if (attr.equals(java.text.DateFormat.Field.DAY_OF_MONTH)) {
-                        val = attr = Field.DAY_OF_MONTH;
-                    } else if (attr.equals(java.text.DateFormat.Field.DAY_OF_WEEK)) {
-                        val = attr = Field.DAY_OF_WEEK ;
-                    } else if (attr.equals(java.text.DateFormat.Field.DAY_OF_WEEK_IN_MONTH)) {
-                        val = attr = Field.DAY_OF_WEEK_IN_MONTH ;
-                    } else if (attr.equals(java.text.DateFormat.Field.DAY_OF_YEAR)) {
-                        val = attr = Field.DAY_OF_YEAR;
-                    } else if (attr.equals(java.text.DateFormat.Field.ERA)) {
-                        val = attr = Field.ERA;
-                    } else if (attr.equals(java.text.DateFormat.Field.HOUR_OF_DAY0)) {
-                        val = attr = Field.HOUR_OF_DAY0;
-                    } else if (attr.equals(java.text.DateFormat.Field.HOUR_OF_DAY1)) {
-                        val = attr = Field.HOUR_OF_DAY1;
-                    } else if (attr.equals(java.text.DateFormat.Field.HOUR0)) {
-                        val = attr = Field.HOUR0;
-                    } else if (attr.equals(java.text.DateFormat.Field.HOUR1)) {
-                        val = attr = Field.HOUR1;
-                    } else if (attr.equals(java.text.DateFormat.Field.MILLISECOND)) {
-                        val = attr = Field.MILLISECOND;
-                    } else if (attr.equals(java.text.DateFormat.Field.MINUTE)) {
-                        val = attr = Field.MINUTE;
-                    } else if (attr.equals(java.text.DateFormat.Field.MONTH)) {
-                        val = attr = Field.MONTH;
-                    } else if (attr.equals(java.text.DateFormat.Field.SECOND)) {
-                        val = attr = Field.SECOND;
-                    } else if (attr.equals(java.text.DateFormat.Field.TIME_ZONE)) {
-                        val = attr = Field.TIME_ZONE;
-                    } else if (attr.equals(java.text.DateFormat.Field.WEEK_OF_MONTH)) {
-                        val = attr = Field.WEEK_OF_MONTH;
-                    } else if (attr.equals(java.text.DateFormat.Field.WEEK_OF_YEAR)) {
-                        val = attr = Field.WEEK_OF_YEAR;
-                    } else if (attr.equals(java.text.DateFormat.Field.YEAR)) {
-                        val = attr = Field.YEAR;
-                    }
-                    attrstr.addAttribute(attr, val, idx, end);
-                }
-            }
-            idx = end;
-            while (it.getIndex() < idx) {
-                it.next();
-            }
-        }
-
-        return attrstr.getIterator();
-    }
-}
+/*
+ *******************************************************************************
+ * Copyright (C) 1996-2011, International Business Machines Corporation and    *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+
+package com.ibm.icu.text;
+
+import java.text.AttributedCharacterIterator;
+import java.text.AttributedCharacterIterator.Attribute;
+import java.text.AttributedString;
+import java.text.CharacterIterator;
+import java.text.FieldPosition;
+import java.text.ParsePosition;
+import java.util.Date;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import com.ibm.icu.util.Calendar;
+import com.ibm.icu.util.ULocale;
+
+
+/**
+ * {@icuenhanced java.text.SimpleDateFormat}.{@icu _usage_}
+ *
+ * <p><code>SimpleDateFormat</code> is a concrete class for formatting and
+ * parsing dates in a locale-sensitive manner. It allows for formatting
+ * (date -> text), parsing (text -> date), and normalization.
+ *
+ * <p>
+ * <code>SimpleDateFormat</code> allows you to start by choosing
+ * any user-defined patterns for date-time formatting. However, you
+ * are encouraged to create a date-time formatter with either
+ * <code>getTimeInstance</code>, <code>getDateInstance</code>, or
+ * <code>getDateTimeInstance</code> in <code>DateFormat</code>. Each
+ * of these class methods can return a date/time formatter initialized
+ * with a default format pattern. You may modify the format pattern
+ * using the <code>applyPattern</code> methods as desired.
+ * For more information on using these methods, see
+ * {@link DateFormat}.
+ *
+ * <p>
+ * <strong>Time Format Syntax:</strong>
+ * <p>
+ * To specify the time format use a <em>time pattern</em> string.
+ * In this pattern, all ASCII letters are reserved as pattern letters,
+ * which are defined as the following:
+ * <blockquote>
+ * <pre>
+ * Symbol   Meaning                 Presentation        Example
+ * ------   -------                 ------------        -------
+ * G        era designator          (Text)              AD
+ * y&#x2020;       year                    (Number)            1996
+ * Y*       year (week of year)     (Number)            1997
+ * u*       extended year           (Number)            4601
+ * M        month in year           (Text & Number)     July & 07
+ * d        day in month            (Number)            10
+ * h        hour in am/pm (1~12)    (Number)            12
+ * H        hour in day (0~23)      (Number)            0
+ * m        minute in hour          (Number)            30
+ * s        second in minute        (Number)            55
+ * S        fractional second       (Number)            978
+ * E        day of week             (Text)              Tuesday
+ * e*       day of week (local 1~7) (Text & Number)     Tuesday & 2
+ * D        day in year             (Number)            189
+ * F        day of week in month    (Number)            2 (2nd Wed in July)
+ * w        week in year            (Number)            27
+ * W        week in month           (Number)            2
+ * a        am/pm marker            (Text)              PM
+ * k        hour in day (1~24)      (Number)            24
+ * K        hour in am/pm (0~11)    (Number)            0
+ * z        time zone               (Text)              Pacific Standard Time
+ * Z        time zone (RFC 822)     (Number)            -0800
+ * v        time zone (generic)     (Text)              Pacific Time
+ * V        time zone (location)    (Text)              United States (Los Angeles)
+ * g*       Julian day              (Number)            2451334
+ * A*       milliseconds in day     (Number)            69540000
+ * Q*       quarter in year         (Text & Number)     Q1 & 01
+ * c*       stand alone day of week (Text & Number)     Tuesday & 2
+ * L*       stand alone month       (Text & Number)     July & 07
+ * q*       stand alone quarter     (Text & Number)     Q1 & 01
+ * '        escape for text         (Delimiter)         'Date='
+ * ''       single quote            (Literal)           'o''clock'
+ * </pre>
+ * </blockquote>
+ * <tt><b>*</b></tt> These items are not supported by Java's SimpleDateFormat.<br>
+ * <tt><b>&#x2020;</b></tt> ICU interprets a single 'y' differently than Java.</p>
+ * <p>
+ * The count of pattern letters determine the format.
+ * <p>
+ * <strong>(Text)</strong>: 4 or more pattern letters--use full form,
+ * &lt; 4--use short or abbreviated form if one exists.
+ * <p>
+ * <strong>(Number)</strong>: the minimum number of digits. Shorter
+ * numbers are zero-padded to this amount. Year is handled specially;
+ * that is, if the count of 'y' is 2, the Year will be truncated to 2 digits.
+ * (e.g., if "yyyy" produces "1997", "yy" produces "97".)
+ * Unlike other fields, fractional seconds are padded on the right with zero.
+ * <p>
+ * <strong>(Text & Number)</strong>: 3 or over, use text, otherwise use number.
+ * <p>
+ * Any characters in the pattern that are not in the ranges of ['a'..'z']
+ * and ['A'..'Z'] will be treated as quoted text. For instance, characters
+ * like ':', '.', ' ', '#' and '@' will appear in the resulting time text
+ * even they are not embraced within single quotes.
+ * <p>
+ * A pattern containing any invalid pattern letter will result in a thrown
+ * exception during formatting or parsing.
+ *
+ * <p>
+ * <strong>Examples Using the US Locale:</strong>
+ * <blockquote>
+ * <pre>
+ * Format Pattern                         Result
+ * --------------                         -------
+ * "yyyy.MM.dd G 'at' HH:mm:ss vvvv" ->>  1996.07.10 AD at 15:08:56 Pacific Time
+ * "EEE, MMM d, ''yy"                ->>  Wed, July 10, '96
+ * "h:mm a"                          ->>  12:08 PM
+ * "hh 'o''clock' a, zzzz"           ->>  12 o'clock PM, Pacific Daylight Time
+ * "K:mm a, vvv"                     ->>  0:00 PM, PT
+ * "yyyyy.MMMMM.dd GGG hh:mm aaa"    ->>  01996.July.10 AD 12:08 PM
+ * </pre>
+ * </blockquote>
+ * <strong>Code Sample:</strong>
+ * <blockquote>
+ * <pre>
+ * SimpleTimeZone pdt = new SimpleTimeZone(-8 * 60 * 60 * 1000, "PST");
+ * pdt.setStartRule(Calendar.APRIL, 1, Calendar.SUNDAY, 2*60*60*1000);
+ * pdt.setEndRule(Calendar.OCTOBER, -1, Calendar.SUNDAY, 2*60*60*1000);
+ * <br>
+ * // Format the current time.
+ * SimpleDateFormat formatter
+ *     = new SimpleDateFormat ("yyyy.MM.dd G 'at' hh:mm:ss a zzz");
+ * Date currentTime_1 = new Date();
+ * String dateString = formatter.format(currentTime_1);
+ * <br>
+ * // Parse the previous string back into a Date.
+ * ParsePosition pos = new ParsePosition(0);
+ * Date currentTime_2 = formatter.parse(dateString, pos);
+ * </pre>
+ * </blockquote>
+ * In the example, the time value <code>currentTime_2</code> obtained from
+ * parsing will be equal to <code>currentTime_1</code>. However, they may not be
+ * equal if the am/pm marker 'a' is left out from the format pattern while
+ * the "hour in am/pm" pattern symbol is used. This information loss can
+ * happen when formatting the time in PM.
+ *
+ * <p>When parsing a date string using the abbreviated year pattern ("yy"),
+ * SimpleDateFormat must interpret the abbreviated year
+ * relative to some century.  It does this by adjusting dates to be
+ * within 80 years before and 20 years after the time the SimpleDateFormat
+ * instance is created. For example, using a pattern of "MM/dd/yy" and a
+ * SimpleDateFormat instance created on Jan 1, 1997,  the string
+ * "01/11/12" would be interpreted as Jan 11, 2012 while the string "05/04/64"
+ * would be interpreted as May 4, 1964.
+ * During parsing, only strings consisting of exactly two digits, as defined by
+ * {@link com.ibm.icu.lang.UCharacter#isDigit(int)}, will be parsed into the default
+ * century.
+ * Any other numeric string, such as a one digit string, a three or more digit
+ * string, or a two digit string that isn't all digits (for example, "-1"), is
+ * interpreted literally.  So "01/02/3" or "01/02/003" are parsed, using the
+ * same pattern, as Jan 2, 3 AD.  Likewise, "01/02/-3" is parsed as Jan 2, 4 BC.
+ *
+ * <p>If the year pattern does not have exactly two 'y' characters, the year is
+ * interpreted literally, regardless of the number of digits.  So using the
+ * pattern "MM/dd/yyyy", "01/11/12" parses to Jan 11, 12 A.D.
+ *
+ * <p>When numeric fields abut one another directly, with no intervening delimiter
+ * characters, they constitute a run of abutting numeric fields.  Such runs are
+ * parsed specially.  For example, the format "HHmmss" parses the input text
+ * "123456" to 12:34:56, parses the input text "12345" to 1:23:45, and fails to
+ * parse "1234".  In other words, the leftmost field of the run is flexible,
+ * while the others keep a fixed width.  If the parse fails anywhere in the run,
+ * then the leftmost field is shortened by one character, and the entire run is
+ * parsed again. This is repeated until either the parse succeeds or the
+ * leftmost field is one character in length.  If the parse still fails at that
+ * point, the parse of the run fails.
+ *
+ * <p>For time zones that have no names, use strings GMT+hours:minutes or
+ * GMT-hours:minutes.
+ *
+ * <p>The calendar defines what is the first day of the week, the first week
+ * of the year, whether hours are zero based or not (0 vs 12 or 24), and the
+ * time zone. There is one common decimal format to handle all the numbers;
+ * the digit count is handled programmatically according to the pattern.
+ *
+ * <h4>Synchronization</h4>
+ *
+ * Date formats are not synchronized. It is recommended to create separate
+ * format instances for each thread. If multiple threads access a format
+ * concurrently, it must be synchronized externally.
+ *
+ * @see          com.ibm.icu.util.Calendar
+ * @see          com.ibm.icu.util.GregorianCalendar
+ * @see          com.ibm.icu.util.TimeZone
+ * @see          DateFormat
+ * @see          DateFormatSymbols
+ * @see          DecimalFormat
+ * @author       Mark Davis, Chen-Lieh Huang, Alan Liu
+ * @stable ICU 2.0
+ */
+public class SimpleDateFormat extends DateFormat {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * Constructs a SimpleDateFormat using the default pattern for the default
+     * locale.  <b>Note:</b> Not all locales support SimpleDateFormat; for full
+     * generality, use the factory methods in the DateFormat class.
+     *
+     * @see DateFormat
+     * @stable ICU 2.0
+     */
+    public SimpleDateFormat() {
+        super(new java.text.SimpleDateFormat());
+    }
+
+    /**
+     * Constructs a SimpleDateFormat using the given pattern in the default
+     * locale.  <b>Note:</b> Not all locales support SimpleDateFormat; for full
+     * generality, use the factory methods in the DateFormat class.
+     * @stable ICU 2.0
+     */
+    public SimpleDateFormat(String pattern)
+    {
+        super(new java.text.SimpleDateFormat(pattern));
+    }
+
+    /**
+     * Constructs a SimpleDateFormat using the given pattern and locale.
+     * <b>Note:</b> Not all locales support SimpleDateFormat; for full
+     * generality, use the factory methods in the DateFormat class.
+     * @stable ICU 2.0
+     */
+    public SimpleDateFormat(String pattern, Locale loc)
+    {
+        super(new java.text.SimpleDateFormat(pattern, loc));
+    }
+
+    /**
+     * Constructs a SimpleDateFormat using the given pattern and locale.
+     * <b>Note:</b> Not all locales support SimpleDateFormat; for full
+     * generality, use the factory methods in the DateFormat class.
+     * @stable ICU 3.2
+     */
+    public SimpleDateFormat(String pattern, ULocale loc)
+    {
+        this(pattern, loc.toLocale());
+    }
+
+    /**
+     * Constructs a SimpleDateFormat using the given pattern , override and locale.
+     * @param pattern The pattern to be used
+     * @param override The override string.  A numbering system override string can take one of the following forms:
+     *     1). If just a numbering system name is specified, it applies to all numeric fields in the date format pattern.
+     *     2). To specify an alternate numbering system on a field by field basis, use the field letters from the pattern
+     *         followed by an = sign, followed by the numbering system name.  For example, to specify that just the year
+     *         be formatted using Hebrew digits, use the override "y=hebr".  Multiple overrides can be specified in a single
+     *         string by separating them with a semi-colon. For example, the override string "m=thai;y=deva" would format using
+     *         Thai digits for the month and Devanagari digits for the year.
+     * @param loc The locale to be used
+     * @stable ICU 4.2
+     */
+    public SimpleDateFormat(String pattern, String override, ULocale loc)
+    {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Constructs a SimpleDateFormat using the given pattern and
+     * locale-specific symbol data.
+     * Warning: uses default locale for digits!
+     * @stable ICU 2.0
+     */
+    public SimpleDateFormat(String pattern, DateFormatSymbols formatData)
+    {
+        super(new java.text.SimpleDateFormat(pattern, formatData.dfs));
+    }
+
+    /**
+     * Sets the 100-year period 2-digit years will be interpreted as being in
+     * to begin on the date the user specifies.
+     * @param startDate During parsing, two digit years will be placed in the range
+     * <code>startDate</code> to <code>startDate + 100 years</code>.
+     * @stable ICU 2.0
+     */
+    public void set2DigitYearStart(Date startDate) {
+        ((java.text.SimpleDateFormat)dateFormat).set2DigitYearStart(startDate);
+    }
+
+    /**
+     * Returns the beginning date of the 100-year period 2-digit years are interpreted
+     * as being within.
+     * @return the start of the 100-year period into which two digit years are
+     * parsed
+     * @stable ICU 2.0
+     */
+    public Date get2DigitYearStart() {
+        return ((java.text.SimpleDateFormat)dateFormat).get2DigitYearStart();
+    }
+
+    /**
+     * Formats a date or time, which is the standard millis
+     * since January 1, 1970, 00:00:00 GMT.
+     * <p>Example: using the US locale:
+     * "yyyy.MM.dd G 'at' HH:mm:ss zzz" ->> 1996.07.10 AD at 15:08:56 PDT
+     * @param cal the calendar whose date-time value is to be formatted into a date-time string
+     * @param toAppendTo where the new date-time text is to be appended
+     * @param pos the formatting position. On input: an alignment field,
+     * if desired. On output: the offsets of the alignment field.
+     * @return the formatted date-time string.
+     * @see DateFormat
+     * @stable ICU 2.0
+     */
+    public StringBuffer format(Calendar cal, StringBuffer toAppendTo,
+                               FieldPosition pos) {
+        StringBuffer result;
+        FieldPosition jdkPos = toJDKFieldPosition(pos);
+        synchronized(dateFormat) {
+            java.util.Calendar oldCal = dateFormat.getCalendar();
+            dateFormat.setCalendar(cal.calendar);
+            result = dateFormat.format(cal.getTime(), toAppendTo, jdkPos);
+            dateFormat.setCalendar(oldCal);
+        }
+        if (jdkPos != null) {
+            pos.setBeginIndex(jdkPos.getBeginIndex());
+            pos.setEndIndex(jdkPos.getEndIndex());
+        }
+        return result;
+    }
+
+    /**
+     * Overrides superclass method
+     * @stable ICU 2.0
+     */
+    public void setNumberFormat(NumberFormat newNumberFormat) {
+        super.setNumberFormat(newNumberFormat);
+    }
+
+    /**
+     * Overrides DateFormat
+     * @see DateFormat
+     * @stable ICU 2.0
+     */
+    public void parse(String text, Calendar cal, ParsePosition parsePos)
+    {
+        // Note: parsed time zone won't be set in the result calendar
+        cal.setTime(dateFormat.parse(text, parsePos));
+    }
+
+    /**
+     * Return a pattern string describing this date format.
+     * @stable ICU 2.0
+     */
+    public String toPattern() {
+        return ((java.text.SimpleDateFormat)dateFormat).toPattern();
+    }
+
+    /**
+     * Return a localized pattern string describing this date format.
+     * @stable ICU 2.0
+     */
+    public String toLocalizedPattern() {
+        return ((java.text.SimpleDateFormat)dateFormat).toLocalizedPattern();
+    }
+
+    /**
+     * Apply the given unlocalized pattern string to this date format.
+     * @stable ICU 2.0
+     */
+    public void applyPattern(String pat) {
+        ((java.text.SimpleDateFormat)dateFormat).applyPattern(pat);
+    }
+
+    /**
+     * Apply the given localized pattern string to this date format.
+     * @stable ICU 2.0
+     */
+    public void applyLocalizedPattern(String pat) {
+        ((java.text.SimpleDateFormat)dateFormat).applyLocalizedPattern(pat);
+    }
+
+    /**
+     * Gets the date/time formatting data.
+     * @return a copy of the date-time formatting data associated
+     * with this date-time formatter.
+     * @stable ICU 2.0
+     */
+    public DateFormatSymbols getDateFormatSymbols() {
+        return new DateFormatSymbols(((java.text.SimpleDateFormat)dateFormat).getDateFormatSymbols());
+    }
+
+    /**
+     * Allows you to set the date/time formatting data.
+     * @param newFormatSymbols the new symbols
+     * @stable ICU 2.0
+     */
+    public void setDateFormatSymbols(DateFormatSymbols newFormatSymbols) {
+        ((java.text.SimpleDateFormat)dateFormat).setDateFormatSymbols(newFormatSymbols.dfs);
+    }
+
+    // For clone to use
+    private SimpleDateFormat(java.text.SimpleDateFormat sdf) {
+        super(sdf);
+    }
+
+    /**
+     * Overrides Cloneable
+     * @stable ICU 2.0
+     */
+    public Object clone() {
+        return new SimpleDateFormat((java.text.SimpleDateFormat)dateFormat.clone());
+    }
+
+    /**
+     * Override hashCode.
+     * Generates the hash code for the SimpleDateFormat object
+     * @stable ICU 2.0
+     */
+    public int hashCode()
+    {
+        return super.hashCode();
+    }
+
+    /**
+     * Override equals.
+     * @stable ICU 2.0
+     */
+    public boolean equals(Object obj)
+    {
+        return super.equals(obj);
+    }
+
+    /**
+     * Format the object to an attributed string, and return the corresponding iterator
+     * Overrides superclass method.
+     *
+     * @param obj The object to format
+     * @return <code>AttributedCharacterIterator</code> describing the formatted value.
+     *
+     * @stable ICU 3.8
+     */
+    public AttributedCharacterIterator formatToCharacterIterator(Object obj) {
+        AttributedCharacterIterator it = dateFormat.formatToCharacterIterator(obj);
+
+        // Extract formatted String first
+        StringBuilder sb = new StringBuilder();
+        for (char c = it.first(); c != CharacterIterator.DONE; c = it.next()) {
+            sb.append(c);
+        }
+
+        // Create AttributedString
+        AttributedString attrstr = new AttributedString(sb.toString());
+
+        // Map JDK Field to ICU Field
+        int idx = 0;
+        it.first();
+        while (idx < it.getEndIndex()) {
+            int end = it.getRunLimit();
+            Map<Attribute, Object> attributes = it.getAttributes();
+            if (attributes != null) {
+                for (Entry<Attribute, Object> entry : attributes.entrySet()) {
+                    Attribute attr = entry.getKey();
+                    Object val = entry.getValue();
+                    if (attr.equals(java.text.DateFormat.Field.AM_PM)) {
+                        val = attr = Field.AM_PM;
+                    } else if (attr.equals(java.text.DateFormat.Field.DAY_OF_MONTH)) {
+                        val = attr = Field.DAY_OF_MONTH;
+                    } else if (attr.equals(java.text.DateFormat.Field.DAY_OF_WEEK)) {
+                        val = attr = Field.DAY_OF_WEEK ;
+                    } else if (attr.equals(java.text.DateFormat.Field.DAY_OF_WEEK_IN_MONTH)) {
+                        val = attr = Field.DAY_OF_WEEK_IN_MONTH ;
+                    } else if (attr.equals(java.text.DateFormat.Field.DAY_OF_YEAR)) {
+                        val = attr = Field.DAY_OF_YEAR;
+                    } else if (attr.equals(java.text.DateFormat.Field.ERA)) {
+                        val = attr = Field.ERA;
+                    } else if (attr.equals(java.text.DateFormat.Field.HOUR_OF_DAY0)) {
+                        val = attr = Field.HOUR_OF_DAY0;
+                    } else if (attr.equals(java.text.DateFormat.Field.HOUR_OF_DAY1)) {
+                        val = attr = Field.HOUR_OF_DAY1;
+                    } else if (attr.equals(java.text.DateFormat.Field.HOUR0)) {
+                        val = attr = Field.HOUR0;
+                    } else if (attr.equals(java.text.DateFormat.Field.HOUR1)) {
+                        val = attr = Field.HOUR1;
+                    } else if (attr.equals(java.text.DateFormat.Field.MILLISECOND)) {
+                        val = attr = Field.MILLISECOND;
+                    } else if (attr.equals(java.text.DateFormat.Field.MINUTE)) {
+                        val = attr = Field.MINUTE;
+                    } else if (attr.equals(java.text.DateFormat.Field.MONTH)) {
+                        val = attr = Field.MONTH;
+                    } else if (attr.equals(java.text.DateFormat.Field.SECOND)) {
+                        val = attr = Field.SECOND;
+                    } else if (attr.equals(java.text.DateFormat.Field.TIME_ZONE)) {
+                        val = attr = Field.TIME_ZONE;
+                    } else if (attr.equals(java.text.DateFormat.Field.WEEK_OF_MONTH)) {
+                        val = attr = Field.WEEK_OF_MONTH;
+                    } else if (attr.equals(java.text.DateFormat.Field.WEEK_OF_YEAR)) {
+                        val = attr = Field.WEEK_OF_YEAR;
+                    } else if (attr.equals(java.text.DateFormat.Field.YEAR)) {
+                        val = attr = Field.YEAR;
+                    }
+                    attrstr.addAttribute(attr, val, idx, end);
+                }
+            }
+            idx = end;
+            while (it.getIndex() < idx) {
+                it.next();
+            }
+        }
+
+        return attrstr.getIterator();
+    }
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/UFormat.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/UFormat.java
index 9fc73a6..52194db 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/UFormat.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/UFormat.java
@@ -1,80 +1,80 @@
-/*
- *******************************************************************************
- * Copyright (C) 2003-2011, International Business Machines Corporation and    *
- * others. All Rights Reserved.                                                *
- *******************************************************************************
- */
-package com.ibm.icu.text;
-
-import java.text.Format;
-
-import com.ibm.icu.util.ULocale;
-
-/**
- * An abstract class that extends {@link java.text.Format} to provide
- * additional ICU protocol, specifically, the <tt>getLocale()</tt>
- * API.  All ICU format classes are subclasses of this class.
- *
- * @see com.ibm.icu.util.ULocale
- * @author weiv
- * @author Alan Liu
- * @draft ICU 2.8 (retain)
- * @provisional This API might change or be removed in a future release.
- */
-public abstract class UFormat extends Format {
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * @draft ICU 2.8 (retain)
-     * @provisional This API might change or be removed in a future release.
-     */
-    public UFormat() {}
-
-    /**
-     * Return the locale that was used to create this object, or null.
-     * This may may differ from the locale requested at the time of
-     * this object's creation.  For example, if an object is created
-     * for locale <tt>en_US_CALIFORNIA</tt>, the actual data may be
-     * drawn from <tt>en</tt> (the <i>actual</i> locale), and
-     * <tt>en_US</tt> may be the most specific locale that exists (the
-     * <i>valid</i> locale).
-     *
-     * <p>Note: This method will be implemented in ICU 3.0; ICU 2.8
-     * contains a partial preview implementation.  The <i>actual</i>
-     * locale is returned correctly, but the <i>valid</i> locale is
-     * not, in most cases.
-     * @param type type of information requested, either {@link
-     * com.ibm.icu.util.ULocale#VALID_LOCALE} or {@link
-     * com.ibm.icu.util.ULocale#ACTUAL_LOCALE}.
-     * @return the information specified by <i>type</i>, or null if
-     * this object was not constructed from locale data.
-     * @see com.ibm.icu.util.ULocale
-     * @see com.ibm.icu.util.ULocale#VALID_LOCALE
-     * @see com.ibm.icu.util.ULocale#ACTUAL_LOCALE
-     * @draft ICU 2.8 (retain)
-     * @provisional This API might change or be removed in a future release.
-     */
-    public final ULocale getLocale(ULocale.Type type) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Set information about the locales that were used to create this
-     * object.  If the object was not constructed from locale data,
-     * both arguments should be set to null.  Otherwise, neither
-     * should be null.  The actual locale must be at the same level or
-     * less specific than the valid locale.  This method is intended
-     * for use by factories or other entities that create objects of
-     * this class.
-     * @param valid the most specific locale containing any resource
-     * data, or null
-     * @param actual the locale containing data used to construct this
-     * object, or null
-     * @see com.ibm.icu.util.ULocale
-     * @see com.ibm.icu.util.ULocale#VALID_LOCALE
-     * @see com.ibm.icu.util.ULocale#ACTUAL_LOCALE
-     */
-    final void setLocale(ULocale valid, ULocale actual) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-}
+/*
+ *******************************************************************************
+ * Copyright (C) 2003-2011, International Business Machines Corporation and    *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+package com.ibm.icu.text;
+
+import java.text.Format;
+
+import com.ibm.icu.util.ULocale;
+
+/**
+ * An abstract class that extends {@link java.text.Format} to provide
+ * additional ICU protocol, specifically, the <tt>getLocale()</tt>
+ * API.  All ICU format classes are subclasses of this class.
+ *
+ * @see com.ibm.icu.util.ULocale
+ * @author weiv
+ * @author Alan Liu
+ * @draft ICU 2.8 (retain)
+ * @provisional This API might change or be removed in a future release.
+ */
+public abstract class UFormat extends Format {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * @draft ICU 2.8 (retain)
+     * @provisional This API might change or be removed in a future release.
+     */
+    public UFormat() {}
+
+    /**
+     * Return the locale that was used to create this object, or null.
+     * This may may differ from the locale requested at the time of
+     * this object's creation.  For example, if an object is created
+     * for locale <tt>en_US_CALIFORNIA</tt>, the actual data may be
+     * drawn from <tt>en</tt> (the <i>actual</i> locale), and
+     * <tt>en_US</tt> may be the most specific locale that exists (the
+     * <i>valid</i> locale).
+     *
+     * <p>Note: This method will be implemented in ICU 3.0; ICU 2.8
+     * contains a partial preview implementation.  The <i>actual</i>
+     * locale is returned correctly, but the <i>valid</i> locale is
+     * not, in most cases.
+     * @param type type of information requested, either {@link
+     * com.ibm.icu.util.ULocale#VALID_LOCALE} or {@link
+     * com.ibm.icu.util.ULocale#ACTUAL_LOCALE}.
+     * @return the information specified by <i>type</i>, or null if
+     * this object was not constructed from locale data.
+     * @see com.ibm.icu.util.ULocale
+     * @see com.ibm.icu.util.ULocale#VALID_LOCALE
+     * @see com.ibm.icu.util.ULocale#ACTUAL_LOCALE
+     * @draft ICU 2.8 (retain)
+     * @provisional This API might change or be removed in a future release.
+     */
+    public final ULocale getLocale(ULocale.Type type) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Set information about the locales that were used to create this
+     * object.  If the object was not constructed from locale data,
+     * both arguments should be set to null.  Otherwise, neither
+     * should be null.  The actual locale must be at the same level or
+     * less specific than the valid locale.  This method is intended
+     * for use by factories or other entities that create objects of
+     * this class.
+     * @param valid the most specific locale containing any resource
+     * data, or null
+     * @param actual the locale containing data used to construct this
+     * object, or null
+     * @see com.ibm.icu.util.ULocale
+     * @see com.ibm.icu.util.ULocale#VALID_LOCALE
+     * @see com.ibm.icu.util.ULocale#ACTUAL_LOCALE
+     */
+    final void setLocale(ULocale valid, ULocale actual) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/UnicodeSet.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/UnicodeSet.java
index 1092ba9..e99df5f 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/UnicodeSet.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/UnicodeSet.java
@@ -1,14 +1,14 @@
-/*
- *******************************************************************************
- * Copyright (C) 2011, International Business Machines Corporation and         *
- * others. All Rights Reserved.                                                *
- *******************************************************************************
- */
-package com.ibm.icu.text;
-
-/*
- * Empty stub
- */
-public class UnicodeSet {
-    private UnicodeSet() {}
-}
+/*
+ *******************************************************************************
+ * Copyright (C) 2011, International Business Machines Corporation and         *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+package com.ibm.icu.text;
+
+/*
+ * Empty stub
+ */
+public class UnicodeSet {
+    private UnicodeSet() {}
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/Calendar.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/Calendar.java
index 739a040..d7b4730 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/Calendar.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/Calendar.java
@@ -1,2345 +1,2346 @@
-/*
-*   Copyright (C) 1996-2011, International Business Machines
-*   Corporation and others.  All Rights Reserved.
-*/
-
-package com.ibm.icu.util;
-
-import java.io.Serializable;
-import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.Locale;
-
-import com.ibm.icu.text.DateFormat;
-
-/**
- * {@icuenhanced java.util.Calendar}.{@icu _usage_}
- *
- * <p><code>Calendar</code> is an abstract base class for converting between
- * a <code>Date</code> object and a set of integer fields such as
- * <code>YEAR</code>, <code>MONTH</code>, <code>DAY</code>, <code>HOUR</code>,
- * and so on. (A <code>Date</code> object represents a specific instant in
- * time with millisecond precision. See
- * {@link Date}
- * for information about the <code>Date</code> class.)
- *
- * <p>Subclasses of <code>Calendar</code> interpret a <code>Date</code>
- * according to the rules of a specific calendar system.  ICU4J contains
- * several subclasses implementing different international calendar systems.
- *
- * <p>
- * Like other locale-sensitive classes, <code>Calendar</code> provides a
- * class method, <code>getInstance</code>, for getting a generally useful
- * object of this type. <code>Calendar</code>'s <code>getInstance</code> method
- * returns a calendar of a type appropriate to the locale, whose
- * time fields have been initialized with the current date and time:
- * <blockquote>
- * <pre>Calendar rightNow = Calendar.getInstance()</pre>
- * </blockquote>
- *
- * <p>When a <code>ULocale</code> is used by <code>getInstance</code>, its
- * '<code>calendar</code>' tag and value are retrieved if present.  If a recognized
- * value is supplied, a calendar is provided and configured as appropriate.
- * Currently recognized tags are "buddhist", "chinese", "coptic", "ethiopic",
- * "gregorian", "hebrew", "islamic", "islamic-civil", "japanese", and "roc".  For
- * example: <blockquote>
- * <pre>Calendar cal = Calendar.getInstance(new ULocale("en_US@calendar=japanese"));</pre>
- * </blockquote> will return an instance of JapaneseCalendar (using en_US conventions for
- * minimum days in first week, start day of week, et cetera).
- *
- * <p>A <code>Calendar</code> object can produce all the time field values
- * needed to implement the date-time formatting for a particular language and
- * calendar style (for example, Japanese-Gregorian, Japanese-Traditional).
- * <code>Calendar</code> defines the range of values returned by certain fields,
- * as well as their meaning.  For example, the first month of the year has value
- * <code>MONTH</code> == <code>JANUARY</code> for all calendars.  Other values
- * are defined by the concrete subclass, such as <code>ERA</code> and
- * <code>YEAR</code>.  See individual field documentation and subclass
- * documentation for details.
- *
- * <p>When a <code>Calendar</code> is <em>lenient</em>, it accepts a wider range
- * of field values than it produces.  For example, a lenient
- * <code>GregorianCalendar</code> interprets <code>MONTH</code> ==
- * <code>JANUARY</code>, <code>DAY_OF_MONTH</code> == 32 as February 1.  A
- * non-lenient <code>GregorianCalendar</code> throws an exception when given
- * out-of-range field settings.  When calendars recompute field values for
- * return by <code>get()</code>, they normalize them.  For example, a
- * <code>GregorianCalendar</code> always produces <code>DAY_OF_MONTH</code>
- * values between 1 and the length of the month.
- *
- * <p><code>Calendar</code> defines a locale-specific seven day week using two
- * parameters: the first day of the week and the minimal days in first week
- * (from 1 to 7).  These numbers are taken from the locale resource data when a
- * <code>Calendar</code> is constructed.  They may also be specified explicitly
- * through the API.
- *
- * <p>When setting or getting the <code>WEEK_OF_MONTH</code> or
- * <code>WEEK_OF_YEAR</code> fields, <code>Calendar</code> must determine the
- * first week of the month or year as a reference point.  The first week of a
- * month or year is defined as the earliest seven day period beginning on
- * <code>getFirstDayOfWeek()</code> and containing at least
- * <code>getMinimalDaysInFirstWeek()</code> days of that month or year.  Weeks
- * numbered ..., -1, 0 precede the first week; weeks numbered 2, 3,... follow
- * it.  Note that the normalized numbering returned by <code>get()</code> may be
- * different.  For example, a specific <code>Calendar</code> subclass may
- * designate the week before week 1 of a year as week <em>n</em> of the previous
- * year.
- *
- * <p> When computing a <code>Date</code> from time fields, two special
- * circumstances may arise: there may be insufficient information to compute the
- * <code>Date</code> (such as only year and month but no day in the month), or
- * there may be inconsistent information (such as "Tuesday, July 15, 1996" --
- * July 15, 1996 is actually a Monday).
- *
- * <p><strong>Insufficient information.</strong> The calendar will use default
- * information to specify the missing fields. This may vary by calendar; for
- * the Gregorian calendar, the default for a field is the same as that of the
- * start of the epoch: i.e., YEAR = 1970, MONTH = JANUARY, DATE = 1, etc.
- *
- * <p><strong>Inconsistent information.</strong> If fields conflict, the calendar
- * will give preference to fields set more recently. For example, when
- * determining the day, the calendar will look for one of the following
- * combinations of fields.  The most recent combination, as determined by the
- * most recently set single field, will be used.
- *
- * <blockquote>
- * <pre>
- * MONTH + DAY_OF_MONTH
- * MONTH + WEEK_OF_MONTH + DAY_OF_WEEK
- * MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK
- * DAY_OF_YEAR
- * DAY_OF_WEEK + WEEK_OF_YEAR</pre>
- * </blockquote>
- *
- * For the time of day:
- *
- * <blockquote>
- * <pre>
- * HOUR_OF_DAY
- * AM_PM + HOUR</pre>
- * </blockquote>
- *
- * <p><strong>Note:</strong> for some non-Gregorian calendars, different
- * fields may be necessary for complete disambiguation. For example, a full
- * specification of the historial Arabic astronomical calendar requires year,
- * month, day-of-month <em>and</em> day-of-week in some cases.
- *
- * <p><strong>Note:</strong> There are certain possible ambiguities in
- * interpretation of certain singular times, which are resolved in the
- * following ways:
- * <ol>
- *     <li> 24:00:00 "belongs" to the following day. That is,
- *          23:59 on Dec 31, 1969 &lt; 24:00 on Jan 1, 1970 &lt; 24:01:00 on Jan 1, 1970
- *
- *     <li> Although historically not precise, midnight also belongs to "am",
- *          and noon belongs to "pm", so on the same day,
- *          12:00 am (midnight) &lt; 12:01 am, and 12:00 pm (noon) &lt; 12:01 pm
- * </ol>
- *
- * <p>The date or time format strings are not part of the definition of a
- * calendar, as those must be modifiable or overridable by the user at
- * runtime. Use {@link DateFormat}
- * to format dates.
- *
- * <p><strong>Field manipulation methods</strong></p>
- *
- * <p><code>Calendar</code> fields can be changed using three methods:
- * <code>set()</code>, <code>add()</code>, and <code>roll()</code>.</p>
- *
- * <p><strong><code>set(f, value)</code></strong> changes field
- * <code>f</code> to <code>value</code>.  In addition, it sets an
- * internal member variable to indicate that field <code>f</code> has
- * been changed. Although field <code>f</code> is changed immediately,
- * the calendar's milliseconds is not recomputed until the next call to
- * <code>get()</code>, <code>getTime()</code>, or
- * <code>getTimeInMillis()</code> is made. Thus, multiple calls to
- * <code>set()</code> do not trigger multiple, unnecessary
- * computations. As a result of changing a field using
- * <code>set()</code>, other fields may also change, depending on the
- * field, the field value, and the calendar system. In addition,
- * <code>get(f)</code> will not necessarily return <code>value</code>
- * after the fields have been recomputed. The specifics are determined by
- * the concrete calendar class.</p>
- *
- * <p><em>Example</em>: Consider a <code>GregorianCalendar</code>
- * originally set to August 31, 1999. Calling <code>set(Calendar.MONTH,
- * Calendar.SEPTEMBER)</code> sets the calendar to September 31,
- * 1999. This is a temporary internal representation that resolves to
- * October 1, 1999 if <code>getTime()</code>is then called. However, a
- * call to <code>set(Calendar.DAY_OF_MONTH, 30)</code> before the call to
- * <code>getTime()</code> sets the calendar to September 30, 1999, since
- * no recomputation occurs after <code>set()</code> itself.</p>
- *
- * <p><strong><code>add(f, delta)</code></strong> adds <code>delta</code>
- * to field <code>f</code>.  This is equivalent to calling <code>set(f,
- * get(f) + delta)</code> with two adjustments:</p>
- *
- * <blockquote>
- *   <p><strong>Add rule 1</strong>. The value of field <code>f</code>
- *   after the call minus the value of field <code>f</code> before the
- *   call is <code>delta</code>, modulo any overflow that has occurred in
- *   field <code>f</code>. Overflow occurs when a field value exceeds its
- *   range and, as a result, the next larger field is incremented or
- *   decremented and the field value is adjusted back into its range.</p>
- *
- *   <p><strong>Add rule 2</strong>. If a smaller field is expected to be
- *   invariant, but &nbsp; it is impossible for it to be equal to its
- *   prior value because of changes in its minimum or maximum after field
- *   <code>f</code> is changed, then its value is adjusted to be as close
- *   as possible to its expected value. A smaller field represents a
- *   smaller unit of time. <code>HOUR</code> is a smaller field than
- *   <code>DAY_OF_MONTH</code>. No adjustment is made to smaller fields
- *   that are not expected to be invariant. The calendar system
- *   determines what fields are expected to be invariant.</p>
- * </blockquote>
- *
- * <p>In addition, unlike <code>set()</code>, <code>add()</code> forces
- * an immediate recomputation of the calendar's milliseconds and all
- * fields.</p>
- *
- * <p><em>Example</em>: Consider a <code>GregorianCalendar</code>
- * originally set to August 31, 1999. Calling <code>add(Calendar.MONTH,
- * 13)</code> sets the calendar to September 30, 2000. <strong>Add rule
- * 1</strong> sets the <code>MONTH</code> field to September, since
- * adding 13 months to August gives September of the next year. Since
- * <code>DAY_OF_MONTH</code> cannot be 31 in September in a
- * <code>GregorianCalendar</code>, <strong>add rule 2</strong> sets the
- * <code>DAY_OF_MONTH</code> to 30, the closest possible value. Although
- * it is a smaller field, <code>DAY_OF_WEEK</code> is not adjusted by
- * rule 2, since it is expected to change when the month changes in a
- * <code>GregorianCalendar</code>.</p>
- *
- * <p><strong><code>roll(f, delta)</code></strong> adds
- * <code>delta</code> to field <code>f</code> without changing larger
- * fields. This is equivalent to calling <code>add(f, delta)</code> with
- * the following adjustment:</p>
- *
- * <blockquote>
- *   <p><strong>Roll rule</strong>. Larger fields are unchanged after the
- *   call. A larger field represents a larger unit of
- *   time. <code>DAY_OF_MONTH</code> is a larger field than
- *   <code>HOUR</code>.</p>
- * </blockquote>
- *
- * <p><em>Example</em>: Consider a <code>GregorianCalendar</code>
- * originally set to August 31, 1999. Calling <code>roll(Calendar.MONTH,
- * 8)</code> sets the calendar to April 30, <strong>1999</strong>.  Add
- * rule 1 sets the <code>MONTH</code> field to April. Using a
- * <code>GregorianCalendar</code>, the <code>DAY_OF_MONTH</code> cannot
- * be 31 in the month April. Add rule 2 sets it to the closest possible
- * value, 30. Finally, the <strong>roll rule</strong> maintains the
- * <code>YEAR</code> field value of 1999.</p>
- *
- * <p><em>Example</em>: Consider a <code>GregorianCalendar</code>
- * originally set to Sunday June 6, 1999. Calling
- * <code>roll(Calendar.WEEK_OF_MONTH, -1)</code> sets the calendar to
- * Tuesday June 1, 1999, whereas calling
- * <code>add(Calendar.WEEK_OF_MONTH, -1)</code> sets the calendar to
- * Sunday May 30, 1999. This is because the roll rule imposes an
- * additional constraint: The <code>MONTH</code> must not change when the
- * <code>WEEK_OF_MONTH</code> is rolled. Taken together with add rule 1,
- * the resultant date must be between Tuesday June 1 and Saturday June
- * 5. According to add rule 2, the <code>DAY_OF_WEEK</code>, an invariant
- * when changing the <code>WEEK_OF_MONTH</code>, is set to Tuesday, the
- * closest possible value to Sunday (where Sunday is the first day of the
- * week).</p>
- *
- * <p><strong>Usage model</strong>. To motivate the behavior of
- * <code>add()</code> and <code>roll()</code>, consider a user interface
- * component with increment and decrement buttons for the month, day, and
- * year, and an underlying <code>GregorianCalendar</code>. If the
- * interface reads January 31, 1999 and the user presses the month
- * increment button, what should it read? If the underlying
- * implementation uses <code>set()</code>, it might read March 3, 1999. A
- * better result would be February 28, 1999. Furthermore, if the user
- * presses the month increment button again, it should read March 31,
- * 1999, not March 28, 1999. By saving the original date and using either
- * <code>add()</code> or <code>roll()</code>, depending on whether larger
- * fields should be affected, the user interface can behave as most users
- * will intuitively expect.</p>
- *
- * <p><b>Note:</b> You should always use {@link #roll roll} and {@link #add add} rather
- * than attempting to perform arithmetic operations directly on the fields
- * of a <tt>Calendar</tt>.  It is quite possible for <tt>Calendar</tt> subclasses
- * to have fields with non-linear behavior, for example missing months
- * or days during non-leap years.  The subclasses' <tt>add</tt> and <tt>roll</tt>
- * methods will take this into account, while simple arithmetic manipulations
- * may give invalid results.
- *
- * <p><big><big><b>Calendar Architecture in ICU4J</b></big></big></p>
- *
- * <p>Recently the implementation of <code>Calendar</code> has changed
- * significantly in order to better support subclassing. The original
- * <code>Calendar</code> class was designed to support subclassing, but
- * it had only one implemented subclass, <code>GregorianCalendar</code>.
- * With the implementation of several new calendar subclasses, including
- * the <code>BuddhistCalendar</code>, <code>ChineseCalendar</code>,
- * <code>HebrewCalendar</code>, <code>IslamicCalendar</code>, and
- * <code>JapaneseCalendar</code>, the subclassing API has been reworked
- * thoroughly. This section details the new subclassing API and other
- * ways in which <code>com.ibm.icu.util.Calendar</code> differs from
- * <code>java.util.Calendar</code>.
- * </p>
- *
- * <p><big><b>Changes</b></big></p>
- *
- * <p>Overview of changes between the classic <code>Calendar</code>
- * architecture and the new architecture.
- *
- * <ul>
- *
- *   <li>The <code>fields[]</code> array is <code>private</code> now
- *     instead of <code>protected</code>.  Subclasses must access it
- *     using the methods {@link #internalSet} and
- *     {@link #internalGet}.  <b>Motivation:</b> Subclasses should
- *     not directly access data members.</li>
- *
- *   <li>The <code>time</code> long word is <code>private</code> now
- *     instead of <code>protected</code>.  Subclasses may access it using
- *     the method {@link #internalGetTimeInMillis}, which does not
- *     provoke an update. <b>Motivation:</b> Subclasses should not
- *     directly access data members.</li>
- *
- *   <li>The scope of responsibility of subclasses has been drastically
- *     reduced. As much functionality as possible is implemented in the
- *     <code>Calendar</code> base class. As a result, it is much easier
- *     to subclass <code>Calendar</code>. <b>Motivation:</b> Subclasses
- *     should not have to reimplement common code. Certain behaviors are
- *     common across calendar systems: The definition and behavior of
- *     week-related fields and time fields, the arithmetic
- *     ({@link #add(int, int) add} and {@link #roll(int, int) roll}) behavior of many
- *     fields, and the field validation system.</li>
- *
- *   <li>The subclassing API has been completely redesigned.</li>
- *
- *   <li>The <code>Calendar</code> base class contains some Gregorian
- *     calendar algorithmic support that subclasses can use (specifically
- *     in {@link #handleComputeFields}).  Subclasses can use the
- *     methods <code>getGregorianXxx()</code> to obtain precomputed
- *     values. <b>Motivation:</b> This is required by all
- *     <code>Calendar</code> subclasses in order to implement consistent
- *     time zone behavior, and Gregorian-derived systems can use the
- *     already computed data.</li>
- *
- *   <li>The <code>FIELD_COUNT</code> constant has been removed. Use
- *     {@link #getFieldCount}.  In addition, framework API has been
- *     added to allow subclasses to define additional fields.
- *     <b>Motivation: </b>The number of fields is not constant across
- *     calendar systems.</li>
- *
- *   <li>The range of handled dates has been narrowed from +/-
- *     ~300,000,000 years to +/- ~5,000,000 years. In practical terms
- *     this should not affect clients. However, it does mean that client
- *     code cannot be guaranteed well-behaved results with dates such as
- *     <code>Date(Long.MIN_VALUE)</code> or
- *     <code>Date(Long.MAX_VALUE)</code>. Instead, the
- *     <code>Calendar</code> protected constants should be used.
- *     <b>Motivation:</b> With
- *     the addition of the {@link #JULIAN_DAY} field, Julian day
- *     numbers must be restricted to a 32-bit <code>int</code>.  This
- *     restricts the overall supported range. Furthermore, restricting
- *     the supported range simplifies the computations by removing
- *     special case code that was used to accomodate arithmetic overflow
- *     at millis near <code>Long.MIN_VALUE</code> and
- *     <code>Long.MAX_VALUE</code>.</li>
- *
- *   <li>New fields are implemented: {@link #JULIAN_DAY} defines
- *     single-field specification of the
- *     date. {@link #MILLISECONDS_IN_DAY} defines a single-field
- *     specification of the wall time. {@link #DOW_LOCAL} and
- *     {@link #YEAR_WOY} implement localized day-of-week and
- *     week-of-year behavior.</li>
- *
- *   <li>Subclasses can access protected millisecond constants
- *   defined in <code>Calendar</code>.</li>
- *
- *   <li>New API has been added to support calendar-specific subclasses
- *     of <code>DateFormat</code>.</li>
- *
- *   <li>Several subclasses have been implemented, representing
- *     various international calendar systems.</li>
- *
- * </ul>
- *
- * <p><big><b>Subclass API</b></big></p>
- *
- * <p>The original <code>Calendar</code> API was based on the experience
- * of implementing a only a single subclass,
- * <code>GregorianCalendar</code>. As a result, all of the subclassing
- * kinks had not been worked out. The new subclassing API has been
- * refined based on several implemented subclasses. This includes methods
- * that must be overridden and methods for subclasses to call. Subclasses
- * no longer have direct access to <code>fields</code> and
- * <code>stamp</code>. Instead, they have new API to access
- * these. Subclasses are able to allocate the <code>fields</code> array
- * through a protected framework method; this allows subclasses to
- * specify additional fields. </p>
- *
- * <p>More functionality has been moved into the base class. The base
- * class now contains much of the computational machinery to support the
- * Gregorian calendar. This is based on two things: (1) Many calendars
- * are based on the Gregorian calendar (such as the Buddhist and Japanese
- * imperial calendars). (2) <em>All</em> calendars require basic
- * Gregorian support in order to handle timezone computations. </p>
- *
- * <p>Common computations have been moved into
- * <code>Calendar</code>. Subclasses no longer compute the week related
- * fields and the time related fields. These are commonly handled for all
- * calendars by the base class. </p>
- *
- * <p><b>Subclass computation of time <tt>=&gt;</tt> fields</b>
- *
- * <p>The {@link #ERA}, {@link #YEAR},
- * {@link #EXTENDED_YEAR}, {@link #MONTH},
- * {@link #DAY_OF_MONTH}, and {@link #DAY_OF_YEAR} fields are
- * computed by the subclass, based on the Julian day. All other fields
- * are computed by <code>Calendar</code>.
- *
- * <ul>
- *
- *   <li>Subclasses should implement {@link #handleComputeFields}
- *     to compute the {@link #ERA}, {@link #YEAR},
- *     {@link #EXTENDED_YEAR}, {@link #MONTH},
- *     {@link #DAY_OF_MONTH}, and {@link #DAY_OF_YEAR} fields,
- *     based on the value of the {@link #JULIAN_DAY} field. If there
- *     are calendar-specific fields not defined by <code>Calendar</code>,
- *     they must also be computed. These are the only fields that the
- *     subclass should compute. All other fields are computed by the base
- *     class, so time and week fields behave in a consistent way across
- *     all calendars. The default version of this method in
- *     <code>Calendar</code> implements a proleptic Gregorian
- *     calendar. Within this method, subclasses may call
- *     <code>getGregorianXxx()</code> to obtain the Gregorian calendar
- *     month, day of month, and extended year for the given date.</li>
- *
- * </ul>
- *
- * <p><b>Subclass computation of fields <tt>=&gt;</tt> time</b>
- *
- * <p>The interpretation of most field values is handled entirely by
- * <code>Calendar</code>. <code>Calendar</code> determines which fields
- * are set, which are not, which are set more recently, and so on. In
- * addition, <code>Calendar</code> handles the computation of the time
- * from the time fields and handles the week-related fields. The only
- * thing the subclass must do is determine the extended year, based on
- * the year fields, and then, given an extended year and a month, it must
- * return a Julian day number.
- *
- * <ul>
- *
- *   <li>Subclasses should implement {@link #handleGetExtendedYear}
- *     to return the extended year for this calendar system, based on the
- *     {@link #YEAR}, {@link #EXTENDED_YEAR}, and any fields that
- *     the calendar system uses that are larger than a year, such as
- *     {@link #ERA}.</li>
- *
- *   <li>Subclasses should implement {@link #handleComputeMonthStart}
- *     to return the Julian day number
- *     associated with a month and extended year. This is the Julian day
- *     number of the day before the first day of the month. The month
- *     number is zero-based. This computation should not depend on any
- *     field values.</li>
- *
- * </ul>
- *
- * <p><b>Other methods</b>
- *
- * <ul>
- *
- *   <li>Subclasses should implement {@link #handleGetMonthLength}
- *     to return the number of days in a
- *     given month of a given extended year. The month number, as always,
- *     is zero-based.</li>
- *
- *   <li>Subclasses should implement {@link #handleGetYearLength}
- *     to return the number of days in the given
- *     extended year. This method is used by
- *     <tt>computeWeekFields</tt> to compute the
- *     {@link #WEEK_OF_YEAR} and {@link #YEAR_WOY} fields.</li>
- *
- *   <li>Subclasses should implement {@link #handleGetLimit}
- *     to return the protected values of a field, depending on the value of
- *     <code>limitType</code>. This method only needs to handle the
- *     fields {@link #ERA}, {@link #YEAR}, {@link #MONTH},
- *     {@link #WEEK_OF_YEAR}, {@link #WEEK_OF_MONTH},
- *     {@link #DAY_OF_MONTH}, {@link #DAY_OF_YEAR},
- *     {@link #DAY_OF_WEEK_IN_MONTH}, {@link #YEAR_WOY}, and
- *     {@link #EXTENDED_YEAR}.  Other fields are invariant (with
- *     respect to calendar system) and are handled by the base
- *     class.</li>
- *
- *   <li>Optionally, subclasses may override {@link #validateField}
- *     to check any subclass-specific fields. If the
- *     field's value is out of range, the method should throw an
- *     <code>IllegalArgumentException</code>. The method may call
- *     <code>super.validateField(field)</code> to handle fields in a
- *     generic way, that is, to compare them to the range
- *     <code>getMinimum(field)</code>..<code>getMaximum(field)</code>.</li>
- *
- *   <li>Optionally, subclasses may override
- *     {@link #handleCreateFields} to create an <code>int[]</code>
- *     array large enough to hold the calendar's fields. This is only
- *     necessary if the calendar defines additional fields beyond those
- *     defined by <code>Calendar</code>. The length of the result must be
- *     be between the base and maximum field counts.</li>
- *
- *   <li>Optionally, subclasses may override
- *     {@link #handleGetDateFormat} to create a
- *     <code>DateFormat</code> appropriate to this calendar. This is only
- *     required if a calendar subclass redefines the use of a field (for
- *     example, changes the {@link #ERA} field from a symbolic field
- *     to a numeric one) or defines an additional field.</li>
- *
- *   <li>Optionally, subclasses may override {@link #roll roll} and
- *     {@link #add add} to handle fields that are discontinuous. For
- *     example, in the Hebrew calendar the month &quot;Adar I&quot; only
- *     occurs in leap years; in other years the calendar jumps from
- *     Shevat (month #4) to Adar (month #6). The {@link
- *     HebrewCalendar#add HebrewCalendar.add} and {@link
- *     HebrewCalendar#roll HebrewCalendar.roll} methods take this into
- *     account, so that adding 1 month to Shevat gives the proper result
- *     (Adar) in a non-leap year. The protected utility method {@link
- *     #pinField pinField} is often useful when implementing these two
- *     methods. </li>
- *
- * </ul>
- *
- * <p><big><b>Normalized behavior</b></big>
- *
- * <p>The behavior of certain fields has been made consistent across all
- * calendar systems and implemented in <code>Calendar</code>.
- *
- * <ul>
- *
- *   <li>Time is normalized. Even though some calendar systems transition
- *     between days at sunset or at other times, all ICU4J calendars
- *     transition between days at <em>local zone midnight</em>.  This
- *     allows ICU4J to centralize the time computations in
- *     <code>Calendar</code> and to maintain basic correpsondences
- *     between calendar systems. Affected fields: {@link #AM_PM},
- *     {@link #HOUR}, {@link #HOUR_OF_DAY}, {@link #MINUTE},
- *     {@link #SECOND}, {@link #MILLISECOND},
- *     {@link #ZONE_OFFSET}, and {@link #DST_OFFSET}.</li>
- *
- *   <li>DST behavior is normalized. Daylight savings time behavior is
- *     computed the same for all calendar systems, and depends on the
- *     value of several <code>GregorianCalendar</code> fields: the
- *     {@link #YEAR}, {@link #MONTH}, and
- *     {@link #DAY_OF_MONTH}. As a result, <code>Calendar</code>
- *     always computes these fields, even for non-Gregorian calendar
- *     systems. These fields are available to subclasses.</li>
- *
- *   <li>Weeks are normalized. Although locales define the week
- *     differently, in terms of the day on which it starts, and the
- *     designation of week number one of a month or year, they all use a
- *     common mechanism. Furthermore, the day of the week has a simple
- *     and consistent definition throughout history. For example,
- *     although the Gregorian calendar introduced a discontinuity when
- *     first instituted, the day of week was not disrupted. For this
- *     reason, the fields {@link #DAY_OF_WEEK}, <code>WEEK_OF_YEAR,
- *     WEEK_OF_MONTH</code>, {@link #DAY_OF_WEEK_IN_MONTH},
- *     {@link #DOW_LOCAL}, {@link #YEAR_WOY} are all computed in
- *     a consistent way in the base class, based on the
- *     {@link #EXTENDED_YEAR}, {@link #DAY_OF_YEAR},
- *     {@link #MONTH}, and {@link #DAY_OF_MONTH}, which are
- *     computed by the subclass.</li>
- *
- * </ul>
- *
- * <p><big><b>Supported range</b></big>
- *
- * <p>The allowable range of <code>Calendar</code> has been
- * narrowed. <code>GregorianCalendar</code> used to attempt to support
- * the range of dates with millisecond values from
- * <code>Long.MIN_VALUE</code> to <code>Long.MAX_VALUE</code>. This
- * introduced awkward constructions (hacks) which slowed down
- * performance. It also introduced non-uniform behavior at the
- * boundaries. The new <code>Calendar</code> protocol specifies the
- * maximum range of supportable dates as those having Julian day numbers
- * of <code>-0x7F000000</code> to <code>+0x7F000000</code>. This
- * corresponds to years from ~5,000,000 BCE to ~5,000,000 CE. Programmers
- * should use the protected constants in <code>Calendar</code> to
- * specify an extremely early or extremely late date.</p>
- *
- * <p><big><b>General notes</b></big>
- *
- * <ul>
- *
- *   <li>Calendars implementations are <em>proleptic</em>. For example,
- *     even though the Gregorian calendar was not instituted until the
- *     16th century, the <code>GregorianCalendar</code> class supports
- *     dates before the historical onset of the calendar by extending the
- *     calendar system backward in time. Similarly, the
- *     <code>HebrewCalendar</code> extends backward before the start of
- *     its epoch into zero and negative years. Subclasses do not throw
- *     exceptions because a date precedes the historical start of a
- *     calendar system. Instead, they implement
- *     {@link #handleGetLimit} to return appropriate limits on
- *     {@link #YEAR}, {@link #ERA}, etc. fields. Then, if the
- *     calendar is set to not be lenient, out-of-range field values will
- *     trigger an exception.</li>
- *
- *   <li>Calendar system subclasses compute a <em>extended
- *     year</em>. This differs from the {@link #YEAR} field in that
- *     it ranges over all integer values, including zero and negative
- *     values, and it encapsulates the information of the
- *     {@link #YEAR} field and all larger fields.  Thus, for the
- *     Gregorian calendar, the {@link #EXTENDED_YEAR} is computed as
- *     <code>ERA==AD ? YEAR : 1-YEAR</code>. Another example is the Mayan
- *     long count, which has years (<code>KUN</code>) and nested cycles
- *     of years (<code>KATUN</code> and <code>BAKTUN</code>). The Mayan
- *     {@link #EXTENDED_YEAR} is computed as <code>TUN + 20 * (KATUN
- *     + 20 * BAKTUN)</code>. The <code>Calendar</code> base class uses
- *     the {@link #EXTENDED_YEAR} field to compute the week-related
- *     fields.</li>
- *
- * </ul>
- *
- * @see          Date
- * @see          GregorianCalendar
- * @see          TimeZone
- * @see          DateFormat
- * @author Mark Davis, David Goldsmith, Chen-Lieh Huang, Alan Liu, Laura Werner
- * @stable ICU 2.0
- */
-public class Calendar implements Serializable, Cloneable, Comparable<Calendar> {
-    private static final long serialVersionUID = 1L;
-    
-    /**
-     * @internal
-     */
-    public final java.util.Calendar calendar;
-        
-    /**
-     * @internal
-     * @param delegate the Calendar to which to delegate
-     */
-    public Calendar(java.util.Calendar delegate) {
-        this.calendar = delegate;
-    }
-
-    // Data flow in Calendar
-    // ---------------------
-
-    // The current time is represented in two ways by Calendar: as UTC
-    // milliseconds from the epoch start (1 January 1970 0:00 UTC), and as local
-    // fields such as MONTH, HOUR, AM_PM, etc.  It is possible to compute the
-    // millis from the fields, and vice versa.  The data needed to do this
-    // conversion is encapsulated by a TimeZone object owned by the Calendar.
-    // The data provided by the TimeZone object may also be overridden if the
-    // user sets the ZONE_OFFSET and/or DST_OFFSET fields directly. The class
-    // keeps track of what information was most recently set by the caller, and
-    // uses that to compute any other information as needed.
-
-    // If the user sets the fields using set(), the data flow is as follows.
-    // This is implemented by the Calendar subclass's computeTime() method.
-    // During this process, certain fields may be ignored.  The disambiguation
-    // algorithm for resolving which fields to pay attention to is described
-    // above.
-
-    //   local fields (YEAR, MONTH, DATE, HOUR, MINUTE, etc.)
-    //           |
-    //           | Using Calendar-specific algorithm
-    //           V
-    //   local standard millis
-    //           |
-    //           | Using TimeZone or user-set ZONE_OFFSET / DST_OFFSET
-    //           V
-    //   UTC millis (in time data member)
-
-    // If the user sets the UTC millis using setTime(), the data flow is as
-    // follows.  This is implemented by the Calendar subclass's computeFields()
-    // method.
-
-    //   UTC millis (in time data member)
-    //           |
-    //           | Using TimeZone getOffset()
-    //           V
-    //   local standard millis
-    //           |
-    //           | Using Calendar-specific algorithm
-    //           V
-    //   local fields (YEAR, MONTH, DATE, HOUR, MINUTE, etc.)
-
-    // In general, a round trip from fields, through local and UTC millis, and
-    // back out to fields is made when necessary.  This is implemented by the
-    // complete() method.  Resolving a partial set of fields into a UTC millis
-    // value allows all remaining fields to be generated from that value.  If
-    // the Calendar is lenient, the fields are also renormalized to standard
-    // ranges when they are regenerated.
-
-    /**
-     * Field number for <code>get</code> and <code>set</code> indicating the
-     * era, e.g., AD or BC in the Julian calendar. This is a calendar-specific
-     * value; see subclass documentation.
-     * @see GregorianCalendar#AD
-     * @see GregorianCalendar#BC
-     * @stable ICU 2.0
-     */
-    public final static int ERA = 0;
-
-    /**
-     * Field number for <code>get</code> and <code>set</code> indicating the
-     * year. This is a calendar-specific value; see subclass documentation.
-     * @stable ICU 2.0
-     */
-    public final static int YEAR = 1;
-
-    /**
-     * Field number for <code>get</code> and <code>set</code> indicating the
-     * month. This is a calendar-specific value. The first month of the year is
-     * <code>JANUARY</code>; the last depends on the number of months in a year.
-     * @see #JANUARY
-     * @see #FEBRUARY
-     * @see #MARCH
-     * @see #APRIL
-     * @see #MAY
-     * @see #JUNE
-     * @see #JULY
-     * @see #AUGUST
-     * @see #SEPTEMBER
-     * @see #OCTOBER
-     * @see #NOVEMBER
-     * @see #DECEMBER
-     * @see #UNDECIMBER
-     * @stable ICU 2.0
-     */
-    public final static int MONTH = 2;
-
-    /**
-     * Field number for <code>get</code> and <code>set</code> indicating the
-     * week number within the current year.  The first week of the year, as
-     * defined by {@link #getFirstDayOfWeek()} and
-     * {@link #getMinimalDaysInFirstWeek()}, has value 1.  Subclasses define
-     * the value of {@link #WEEK_OF_YEAR} for days before the first week of
-     * the year.
-     * @see #getFirstDayOfWeek
-     * @see #getMinimalDaysInFirstWeek
-     * @stable ICU 2.0
-     */
-    public final static int WEEK_OF_YEAR = 3;
-
-    /**
-     * Field number for <code>get</code> and <code>set</code> indicating the
-     * week number within the current month.  The first week of the month, as
-     * defined by {@link #getFirstDayOfWeek()} and
-     * {@link #getMinimalDaysInFirstWeek()}, has value 1.  Subclasses define
-     * the value of {@link #WEEK_OF_MONTH} for days before the first week of
-     * the month.
-     * @see #getFirstDayOfWeek
-     * @see #getMinimalDaysInFirstWeek
-     * @stable ICU 2.0
-     */
-    public final static int WEEK_OF_MONTH = 4;
-
-    /**
-     * Field number for <code>get</code> and <code>set</code> indicating the
-     * day of the month. This is a synonym for {@link #DAY_OF_MONTH}.
-     * The first day of the month has value 1.
-     * @see #DAY_OF_MONTH
-     * @stable ICU 2.0
-     */
-    public final static int DATE = 5;
-
-    /**
-     * Field number for <code>get</code> and <code>set</code> indicating the
-     * day of the month. This is a synonym for {@link #DATE}.
-     * The first day of the month has value 1.
-     * @see #DATE
-     * @stable ICU 2.0
-     */
-    public final static int DAY_OF_MONTH = 5;
-
-    /**
-     * Field number for <code>get</code> and <code>set</code> indicating the day
-     * number within the current year.  The first day of the year has value 1.
-     * @stable ICU 2.0
-     */
-    public final static int DAY_OF_YEAR = 6;
-
-    /**
-     * Field number for <code>get</code> and <code>set</code> indicating the day
-     * of the week.  This field takes values {@link #SUNDAY},
-     * {@link #MONDAY}, {@link #TUESDAY}, {@link #WEDNESDAY},
-     * {@link #THURSDAY}, {@link #FRIDAY}, and {@link #SATURDAY}.
-     * @see #SUNDAY
-     * @see #MONDAY
-     * @see #TUESDAY
-     * @see #WEDNESDAY
-     * @see #THURSDAY
-     * @see #FRIDAY
-     * @see #SATURDAY
-     * @stable ICU 2.0
-     */
-    public final static int DAY_OF_WEEK = 7;
-
-    /**
-     * Field number for <code>get</code> and <code>set</code> indicating the
-     * ordinal number of the day of the week within the current month. Together
-     * with the {@link #DAY_OF_WEEK} field, this uniquely specifies a day
-     * within a month.  Unlike {@link #WEEK_OF_MONTH} and
-     * {@link #WEEK_OF_YEAR}, this field's value does <em>not</em> depend on
-     * {@link #getFirstDayOfWeek()} or
-     * {@link #getMinimalDaysInFirstWeek()}.  <code>DAY_OF_MONTH 1</code>
-     * through <code>7</code> always correspond to <code>DAY_OF_WEEK_IN_MONTH
-     * 1</code>; <code>8</code> through <code>15</code> correspond to
-     * <code>DAY_OF_WEEK_IN_MONTH 2</code>, and so on.
-     * <code>DAY_OF_WEEK_IN_MONTH 0</code> indicates the week before
-     * <code>DAY_OF_WEEK_IN_MONTH 1</code>.  Negative values count back from the
-     * end of the month, so the last Sunday of a month is specified as
-     * <code>DAY_OF_WEEK = SUNDAY, DAY_OF_WEEK_IN_MONTH = -1</code>.  Because
-     * negative values count backward they will usually be aligned differently
-     * within the month than positive values.  For example, if a month has 31
-     * days, <code>DAY_OF_WEEK_IN_MONTH -1</code> will overlap
-     * <code>DAY_OF_WEEK_IN_MONTH 5</code> and the end of <code>4</code>.
-     * @see #DAY_OF_WEEK
-     * @see #WEEK_OF_MONTH
-     * @stable ICU 2.0
-     */
-    public final static int DAY_OF_WEEK_IN_MONTH = 8;
-
-    /**
-     * Field number for <code>get</code> and <code>set</code> indicating
-     * whether the <code>HOUR</code> is before or after noon.
-     * E.g., at 10:04:15.250 PM the <code>AM_PM</code> is <code>PM</code>.
-     * @see #AM
-     * @see #PM
-     * @see #HOUR
-     * @stable ICU 2.0
-     */
-    public final static int AM_PM = 9;
-
-    /**
-     * Field number for <code>get</code> and <code>set</code> indicating the
-     * hour of the morning or afternoon. <code>HOUR</code> is used for the 12-hour
-     * clock.
-     * E.g., at 10:04:15.250 PM the <code>HOUR</code> is 10.
-     * @see #AM_PM
-     * @see #HOUR_OF_DAY
-     * @stable ICU 2.0
-     */
-    public final static int HOUR = 10;
-
-    /**
-     * Field number for <code>get</code> and <code>set</code> indicating the
-     * hour of the day. <code>HOUR_OF_DAY</code> is used for the 24-hour clock.
-     * E.g., at 10:04:15.250 PM the <code>HOUR_OF_DAY</code> is 22.
-     * @see #HOUR
-     * @stable ICU 2.0
-     */
-    public final static int HOUR_OF_DAY = 11;
-
-    /**
-     * Field number for <code>get</code> and <code>set</code> indicating the
-     * minute within the hour.
-     * E.g., at 10:04:15.250 PM the <code>MINUTE</code> is 4.
-     * @stable ICU 2.0
-     */
-    public final static int MINUTE = 12;
-
-    /**
-     * Field number for <code>get</code> and <code>set</code> indicating the
-     * second within the minute.
-     * E.g., at 10:04:15.250 PM the <code>SECOND</code> is 15.
-     * @stable ICU 2.0
-     */
-    public final static int SECOND = 13;
-
-    /**
-     * Field number for <code>get</code> and <code>set</code> indicating the
-     * millisecond within the second.
-     * E.g., at 10:04:15.250 PM the <code>MILLISECOND</code> is 250.
-     * @stable ICU 2.0
-     */
-    public final static int MILLISECOND = 14;
-
-    /**
-     * Field number for <code>get</code> and <code>set</code> indicating the
-     * raw offset from GMT in milliseconds.
-     * @stable ICU 2.0
-     */
-    public final static int ZONE_OFFSET = 15;
-
-    /**
-     * Field number for <code>get</code> and <code>set</code> indicating the
-     * daylight savings offset in milliseconds.
-     * @stable ICU 2.0
-     */
-    public final static int DST_OFFSET = 16;
-
-    /**
-     * {@icu} Field number for <code>get()</code> and <code>set()</code>
-     * indicating the extended year corresponding to the
-     * {@link #WEEK_OF_YEAR} field.  This may be one greater or less
-     * than the value of {@link #EXTENDED_YEAR}.
-     * @stable ICU 2.0
-     */
-    public static final int YEAR_WOY = 17;
-
-    /**
-     * {@icu} Field number for <code>get()</code> and <code>set()</code>
-     * indicating the localized day of week.  This will be a value from 1
-     * to 7 inclusive, with 1 being the localized first day of the week.
-     * @stable ICU 2.0
-     */
-    public static final int DOW_LOCAL = 18;
-
-    /**
-     * {@icu} Field number for <code>get()</code> and <code>set()</code>
-     * indicating the extended year.  This is a single number designating
-     * the year of this calendar system, encompassing all supra-year
-     * fields.  For example, for the Julian calendar system, year numbers
-     * are positive, with an era of BCE or CE.  An extended year value for
-     * the Julian calendar system assigns positive values to CE years and
-     * negative values to BCE years, with 1 BCE being year 0.
-     * @stable ICU 2.0
-     */
-    public static final int EXTENDED_YEAR = 19;
-
-    /**
-     * {@icu} Field number for <code>get()</code> and <code>set()</code>
-     * indicating the modified Julian day number.  This is different from
-     * the conventional Julian day number in two regards.  First, it
-     * demarcates days at local zone midnight, rather than noon GMT.
-     * Second, it is a local number; that is, it depends on the local time
-     * zone.  It can be thought of as a single number that encompasses all
-     * the date-related fields.
-     * @stable ICU 2.0
-     */
-    public static final int JULIAN_DAY = 20;
-
-    /**
-     * {@icu} Field number for <code>get()</code> and <code>set()</code>
-     * indicating the milliseconds in the day.  This ranges from 0 to
-     * 23:59:59.999 (regardless of DST).  This field behaves
-     * <em>exactly</em> like a composite of all time-related fields, not
-     * including the zone fields.  As such, it also reflects
-     * discontinuities of those fields on DST transition days.  On a day of
-     * DST onset, it will jump forward.  On a day of DST cessation, it will
-     * jump backward.  This reflects the fact that is must be combined with
-     * the DST_OFFSET field to obtain a unique local time value.
-     * @stable ICU 2.0
-     */
-    public static final int MILLISECONDS_IN_DAY = 21;
-
-    /**
-     * {@icu} Field indicating whether or not the current month is a leap month.
-     * Should have a value of 0 for non-leap months, and 1 for leap months.
-     * @draft ICU 4.4
-     * @provisional This API might change or be removed in a future release.
-     */
-    public static final int IS_LEAP_MONTH = 22;
-
-    /**
-     * Value of the <code>DAY_OF_WEEK</code> field indicating
-     * Sunday.
-     * @stable ICU 2.0
-     */
-    public final static int SUNDAY = 1;
-
-    /**
-     * Value of the <code>DAY_OF_WEEK</code> field indicating
-     * Monday.
-     * @stable ICU 2.0
-     */
-    public final static int MONDAY = 2;
-
-    /**
-     * Value of the <code>DAY_OF_WEEK</code> field indicating
-     * Tuesday.
-     * @stable ICU 2.0
-     */
-    public final static int TUESDAY = 3;
-
-    /**
-     * Value of the <code>DAY_OF_WEEK</code> field indicating
-     * Wednesday.
-     * @stable ICU 2.0
-     */
-    public final static int WEDNESDAY = 4;
-
-    /**
-     * Value of the <code>DAY_OF_WEEK</code> field indicating
-     * Thursday.
-     * @stable ICU 2.0
-     */
-    public final static int THURSDAY = 5;
-
-    /**
-     * Value of the <code>DAY_OF_WEEK</code> field indicating
-     * Friday.
-     * @stable ICU 2.0
-     */
-    public final static int FRIDAY = 6;
-
-    /**
-     * Value of the <code>DAY_OF_WEEK</code> field indicating
-     * Saturday.
-     * @stable ICU 2.0
-     */
-    public final static int SATURDAY = 7;
-
-    /**
-     * Value of the <code>MONTH</code> field indicating the
-     * first month of the year.
-     * @stable ICU 2.0
-     */
-    public final static int JANUARY = 0;
-
-    /**
-     * Value of the <code>MONTH</code> field indicating the
-     * second month of the year.
-     * @stable ICU 2.0
-     */
-    public final static int FEBRUARY = 1;
-
-    /**
-     * Value of the <code>MONTH</code> field indicating the
-     * third month of the year.
-     * @stable ICU 2.0
-     */
-    public final static int MARCH = 2;
-
-    /**
-     * Value of the <code>MONTH</code> field indicating the
-     * fourth month of the year.
-     * @stable ICU 2.0
-     */
-    public final static int APRIL = 3;
-
-    /**
-     * Value of the <code>MONTH</code> field indicating the
-     * fifth month of the year.
-     * @stable ICU 2.0
-     */
-    public final static int MAY = 4;
-
-    /**
-     * Value of the <code>MONTH</code> field indicating the
-     * sixth month of the year.
-     * @stable ICU 2.0
-     */
-    public final static int JUNE = 5;
-
-    /**
-     * Value of the <code>MONTH</code> field indicating the
-     * seventh month of the year.
-     * @stable ICU 2.0
-     */
-    public final static int JULY = 6;
-
-    /**
-     * Value of the <code>MONTH</code> field indicating the
-     * eighth month of the year.
-     * @stable ICU 2.0
-     */
-    public final static int AUGUST = 7;
-
-    /**
-     * Value of the <code>MONTH</code> field indicating the
-     * ninth month of the year.
-     * @stable ICU 2.0
-     */
-    public final static int SEPTEMBER = 8;
-
-    /**
-     * Value of the <code>MONTH</code> field indicating the
-     * tenth month of the year.
-     * @stable ICU 2.0
-     */
-    public final static int OCTOBER = 9;
-
-    /**
-     * Value of the <code>MONTH</code> field indicating the
-     * eleventh month of the year.
-     * @stable ICU 2.0
-     */
-    public final static int NOVEMBER = 10;
-
-    /**
-     * Value of the <code>MONTH</code> field indicating the
-     * twelfth month of the year.
-     * @stable ICU 2.0
-     */
-    public final static int DECEMBER = 11;
-
-    /**
-     * Value of the <code>MONTH</code> field indicating the
-     * thirteenth month of the year. Although {@link GregorianCalendar}
-     * does not use this value, lunar calendars do.
-     * @stable ICU 2.0
-     */
-    public final static int UNDECIMBER = 12;
-
-    /**
-     * Value of the <code>AM_PM</code> field indicating the
-     * period of the day from midnight to just before noon.
-     * @stable ICU 2.0
-     */
-    public final static int AM = 0;
-
-    /**
-     * Value of the <code>AM_PM</code> field indicating the
-     * period of the day from noon to just before midnight.
-     * @stable ICU 2.0
-     */
-    public final static int PM = 1;
-
-    /**
-     * {@icu} Value returned by getDayOfWeekType(int dayOfWeek) to indicate a
-     * weekday.
-     * @see #WEEKEND
-     * @see #WEEKEND_ONSET
-     * @see #WEEKEND_CEASE
-     * @see #getDayOfWeekType
-     * @stable ICU 2.0
-     */
-    public static final int WEEKDAY = 0;
-
-    /**
-     * {@icu} Value returned by getDayOfWeekType(int dayOfWeek) to indicate a
-     * weekend day.
-     * @see #WEEKDAY
-     * @see #WEEKEND_ONSET
-     * @see #WEEKEND_CEASE
-     * @see #getDayOfWeekType
-     * @stable ICU 2.0
-     */
-    public static final int WEEKEND = 1;
-
-    /**
-     * {@icu} Value returned by getDayOfWeekType(int dayOfWeek) to indicate a
-     * day that starts as a weekday and transitions to the weekend.
-     * Call getWeekendTransition() to get the point of transition.
-     * @see #WEEKDAY
-     * @see #WEEKEND
-     * @see #WEEKEND_CEASE
-     * @see #getDayOfWeekType
-     * @stable ICU 2.0
-     */
-    public static final int WEEKEND_ONSET = 2;
-
-    /**
-     * {@icu} Value returned by getDayOfWeekType(int dayOfWeek) to indicate a
-     * day that starts as the weekend and transitions to a weekday.
-     * Call getWeekendTransition() to get the point of transition.
-     * @see #WEEKDAY
-     * @see #WEEKEND
-     * @see #WEEKEND_ONSET
-     * @see #getDayOfWeekType
-     * @stable ICU 2.0
-     */
-    public static final int WEEKEND_CEASE = 3;
-
-    /**
-     * Constructs a Calendar with the default time zone
-     * and locale.
-     * @see     TimeZone#getDefault
-     * @stable ICU 2.0
-     */
-    protected Calendar()
-    {
-        this(TimeZone.getDefault(), ULocale.getDefault());
-    }
-
-    /**
-     * Constructs a calendar with the specified time zone and locale.
-     * @param zone the time zone to use
-     * @param aLocale the locale for the week data
-     * @stable ICU 2.0
-     */
-    protected Calendar(TimeZone zone, Locale aLocale)
-    {
-        this(zone, ULocale.forLocale(aLocale));
-    }
-
-    /**
-     * Constructs a calendar with the specified time zone and locale.
-     * @param zone the time zone to use
-     * @param locale the ulocale for the week data
-     * @stable ICU 3.2
-     */
-    protected Calendar(TimeZone zone, ULocale locale)
-    {
-        calendar = java.util.Calendar.getInstance(zone.timeZone, locale.toLocale());
-    }
-
-    /**
-     * Returns a calendar using the default time zone and locale.
-     * @return a Calendar.
-     * @stable ICU 2.0
-     */
-    public static synchronized Calendar getInstance()
-    {
-        return new Calendar(java.util.Calendar.getInstance());
-    }
-
-    /**
-     * Returns a calendar using the specified time zone and default locale.
-     * @param zone the time zone to use
-     * @return a Calendar.
-     * @stable ICU 2.0
-     */
-    public static synchronized Calendar getInstance(TimeZone zone)
-    {
-        return new Calendar(java.util.Calendar.getInstance(zone.timeZone));
-    }
-
-    /**
-     * Returns a calendar using the default time zone and specified locale.
-     * @param aLocale the locale for the week data
-     * @return a Calendar.
-     * @stable ICU 2.0
-     */
-    public static synchronized Calendar getInstance(Locale aLocale)
-    {
-        return new Calendar(java.util.Calendar.getInstance(aLocale));
-    }
-
-    /**
-     * Returns a calendar using the default time zone and specified locale.
-     * @param locale the ulocale for the week data
-     * @return a Calendar.
-     * @stable ICU 3.2
-     */
-    public static synchronized Calendar getInstance(ULocale locale)
-    {
-        return new Calendar(java.util.Calendar.getInstance(locale.toLocale()));
-    }
-
-    /**
-     * Returns a calendar with the specified time zone and locale.
-     * @param zone the time zone to use
-     * @param aLocale the locale for the week data
-     * @return a Calendar.
-     * @stable ICU 2.0
-     */
-    public static synchronized Calendar getInstance(TimeZone zone,
-                                                    Locale aLocale) {
-        return new Calendar(java.util.Calendar.getInstance(zone.timeZone, aLocale));
-    }
-
-    /**
-     * Returns a calendar with the specified time zone and locale.
-     * @param zone the time zone to use
-     * @param locale the ulocale for the week data
-     * @return a Calendar.
-     * @stable ICU 3.2
-     */
-    public static synchronized Calendar getInstance(TimeZone zone,
-                                                    ULocale locale) {
-        return new Calendar(java.util.Calendar.getInstance(zone.timeZone, locale.toLocale()));
-    }
-
-    /**
-     * Returns the list of locales for which Calendars are installed.
-     * @return the list of locales for which Calendars are installed.
-     * @stable ICU 2.0
-     */
-    public static Locale[] getAvailableLocales()
-    {
-        return java.util.Calendar.getAvailableLocales();
-    }
-
-    /**
-     * {@icu} Returns the list of locales for which Calendars are installed.
-     * @return the list of locales for which Calendars are installed.
-     * @draft ICU 3.2 (retain)
-     * @provisional This API might change or be removed in a future release.
-     */
-    public static ULocale[] getAvailableULocales()
-    {
-        if (availableLocales == null) {
-            synchronized (Calendar.class) {
-                if (availableLocales == null) {
-                    Locale[] locales = Locale.getAvailableLocales();
-                    availableLocales = new ULocale[locales.length];
-                    for (int i = 0; i < locales.length; i++) {
-                        availableLocales[i] = ULocale.forLocale(locales[i]);
-                    }
-                }
-            }
-        }
-        return availableLocales.clone();
-    }
-    private static volatile ULocale[] availableLocales;
-
-    /**
-     * {@icu} Given a key and a locale, returns an array of string values in a preferred
-     * order that would make a difference. These are all and only those values where
-     * the open (creation) of the service with the locale formed from the input locale
-     * plus input keyword and that value has different behavior than creation with the
-     * input locale alone.
-     * @param key           one of the keys supported by this service.  For now, only
-     *                      "calendar" is supported.
-     * @param locale        the locale
-     * @param commonlyUsed  if set to true it will return only commonly used values
-     *                      with the given locale in preferred order.  Otherwise,
-     *                      it will return all the available values for the locale.
-     * @return an array of string values for the given key and the locale.
-     * @stable ICU 4.2
-     */
-    public static final String[] getKeywordValuesForLocale(String key, ULocale locale,
-                                                           boolean commonlyUsed) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Returns this Calendar's current time.
-     * @return the current time.
-     * @stable ICU 2.0
-     */
-    public final Date getTime() {
-        return calendar.getTime();
-    }
-
-    /**
-     * Sets this Calendar's current time with the given Date.
-     * 
-     * <p>Note: Calling <code>setTime</code> with
-     * <code>Date(Long.MAX_VALUE)</code> or <code>Date(Long.MIN_VALUE)</code>
-     * may yield incorrect field values from {@link #get(int)}.
-     * @param date the given Date.
-     * @stable ICU 2.0
-     */
-    public final void setTime(Date date) {
-        calendar.setTime(date);
-    }
-
-    /**
-     * Returns this Calendar's current time as a long.
-     * @return the current time as UTC milliseconds from the epoch.
-     * @stable ICU 2.0
-     */
-    public long getTimeInMillis() {
-        return calendar.getTimeInMillis();
-    }
-
-    /**
-     * Sets this Calendar's current time from the given long value.
-     * @param millis the new time in UTC milliseconds from the epoch.
-     * @stable ICU 2.0
-     */
-    public void setTimeInMillis( long millis ) {
-        calendar.setTimeInMillis(millis);
-    }
-
-    /**
-     * Returns the value for a given time field.
-     * @param field the given time field.
-     * @return the value for the given time field.
-     * @stable ICU 2.0
-     */
-    public final int get(int field)
-    {
-        return calendar.get(getJDKField(field));
-    }
-
-    /**
-     * Sets the time field with the given value.
-     * @param field the given time field.
-     * @param value the value to be set for the given time field.
-     * @stable ICU 2.0
-     */
-    public final void set(int field, int value)
-    {
-        calendar.set(getJDKField(field), value);
-    }
-
-    /**
-     * Sets the values for the fields year, month, and date.
-     * Previous values of other fields are retained.  If this is not desired,
-     * call {@link #clear()} first.
-     * @param year the value used to set the YEAR time field.
-     * @param month the value used to set the MONTH time field.
-     * Month value is 0-based. e.g., 0 for January.
-     * @param date the value used to set the DATE time field.
-     * @stable ICU 2.0
-     */
-    public final void set(int year, int month, int date)
-    {
-        calendar.set(getJDKField(YEAR), year);
-        calendar.set(getJDKField(MONTH), month);
-        calendar.set(getJDKField(DATE), date);
-    }
-
-    /**
-     * Sets the values for the fields year, month, date, hour, and minute.
-     * Previous values of other fields are retained.  If this is not desired,
-     * call {@link #clear()} first.
-     * @param year the value used to set the YEAR time field.
-     * @param month the value used to set the MONTH time field.
-     * Month value is 0-based. e.g., 0 for January.
-     * @param date the value used to set the DATE time field.
-     * @param hour the value used to set the HOUR_OF_DAY time field.
-     * @param minute the value used to set the MINUTE time field.
-     * @stable ICU 2.0
-     */
-    public final void set(int year, int month, int date, int hour, int minute)
-    {
-        calendar.set(getJDKField(YEAR), year);
-        calendar.set(getJDKField(MONTH), month);
-        calendar.set(getJDKField(DATE), date);
-        calendar.set(getJDKField(HOUR_OF_DAY), hour);
-        calendar.set(getJDKField(MINUTE), minute);
-    }
-
-    /**
-     * Sets the values for the fields year, month, date, hour, minute, and second.
-     * Previous values of other fields are retained.  If this is not desired,
-     * call {@link #clear} first.
-     * @param year the value used to set the YEAR time field.
-     * @param month the value used to set the MONTH time field.
-     * Month value is 0-based. e.g., 0 for January.
-     * @param date the value used to set the DATE time field.
-     * @param hour the value used to set the HOUR_OF_DAY time field.
-     * @param minute the value used to set the MINUTE time field.
-     * @param second the value used to set the SECOND time field.
-     * @stable ICU 2.0
-     */
-    public final void set(int year, int month, int date, int hour, int minute,
-                          int second)
-    {
-        calendar.set(getJDKField(YEAR), year);
-        calendar.set(getJDKField(MONTH), month);
-        calendar.set(getJDKField(DATE), date);
-        calendar.set(getJDKField(HOUR_OF_DAY), hour);
-        calendar.set(getJDKField(MINUTE), minute);
-        calendar.set(getJDKField(SECOND), second);
-    }
-
-    /**
-     * Clears the values of all the time fields.
-     * @stable ICU 2.0
-     */
-    public final void clear()
-    {
-        calendar.clear();
-    }
-
-    /**
-     * Clears the value in the given time field.
-     * @param field the time field to be cleared.
-     * @stable ICU 2.0
-     */
-    public final void clear(int field)
-    {
-        calendar.clear(getJDKField(field));
-    }
-
-    /**
-     * Determines if the given time field has a value set.
-     * @return true if the given time field has a value set; false otherwise.
-     * @stable ICU 2.0
-     */
-    public final boolean isSet(int field)
-    {
-        return calendar.isSet(getJDKField(field));
-    }
-
-    /**
-     * Compares this calendar to the specified object.
-     * The result is <code>true</code> if and only if the argument is
-     * not <code>null</code> and is a <code>Calendar</code> object that
-     * represents the same calendar as this object.
-     * @param obj the object to compare with.
-     * @return <code>true</code> if the objects are the same;
-     * <code>false</code> otherwise.
-     * @stable ICU 2.0
-     */
-    public boolean equals(Object obj) {
-        try {
-            return calendar.equals(((Calendar)obj).calendar);
-        } catch (Exception e) {
-            return false;
-        }
-    }
-
-    /**
-     * {@icu} Returns true if the given Calendar object is equivalent to this
-     * one.  An equivalent Calendar will behave exactly as this one
-     * does, but it may be set to a different time.  By contrast, for
-     * the equals() method to return true, the other Calendar must
-     * be set to the same time.
-     *
-     * @param other the Calendar to be compared with this Calendar
-     * @stable ICU 2.4
-     */
-    public boolean isEquivalentTo(Calendar other) {
-        return calendar.getClass() == other.calendar.getClass() &&
-            calendar.isLenient() == other.calendar.isLenient() &&
-            calendar.getFirstDayOfWeek() == other.calendar.getFirstDayOfWeek() &&
-            calendar.getMinimalDaysInFirstWeek() == other.calendar.getMinimalDaysInFirstWeek() &&
-            calendar.getTimeZone().equals(other.calendar.getTimeZone());
-    }
-
-    /**
-     * Returns a hash code for this calendar.
-     * @return a hash code value for this object.
-     * @stable ICU 2.0
-     */
-    public int hashCode() {
-        return calendar.hashCode();
-    }
-
-    /**
-     * Returns the difference in milliseconds between the moment this
-     * calendar is set to and the moment the given calendar or Date object
-     * is set to.
-     */
-    private long compare(Object that) {
-        long thatMs;
-        if (that instanceof Calendar) {
-            thatMs = ((Calendar)that).getTimeInMillis();
-        } else if (that instanceof Date) {
-            thatMs = ((Date)that).getTime();
-        } else {
-            throw new IllegalArgumentException(that + "is not a Calendar or Date");
-        }
-        return getTimeInMillis() - thatMs;
-    }
-
-    /**
-     * Compares the time field records.
-     * Equivalent to comparing result of conversion to UTC.
-     * @param when the Calendar to be compared with this Calendar.
-     * @return true if the current time of this Calendar is before
-     * the time of Calendar when; false otherwise.
-     * @stable ICU 2.0
-     */
-    public boolean before(Object when) {
-        return compare(when) < 0;
-    }
-
-    /**
-     * Compares the time field records.
-     * Equivalent to comparing result of conversion to UTC.
-     * @param when the Calendar to be compared with this Calendar.
-     * @return true if the current time of this Calendar is after
-     * the time of Calendar when; false otherwise.
-     * @stable ICU 2.0
-     */
-    public boolean after(Object when) {
-        return compare(when) > 0;
-    }
-
-    /**
-     * Returns the maximum value that this field could have, given the
-     * current date.  For example, with the Gregorian date February 3, 1997
-     * and the {@link #DAY_OF_MONTH DAY_OF_MONTH} field, the actual maximum
-     * is 28; for February 3, 1996 it is 29.
-     *
-     * <p>The actual maximum computation ignores smaller fields and the
-     * current value of like-sized fields.  For example, the actual maximum
-     * of the DAY_OF_YEAR or MONTH depends only on the year and supra-year
-     * fields.  The actual maximum of the DAY_OF_MONTH depends, in
-     * addition, on the MONTH field and any other fields at that
-     * granularity (such as IS_LEAP_MONTH).  The
-     * DAY_OF_WEEK_IN_MONTH field does not depend on the current
-     * DAY_OF_WEEK; it returns the maximum for any day of week in the
-     * current month.  Likewise for the WEEK_OF_MONTH and WEEK_OF_YEAR
-     * fields.
-     *
-     * @param field the field whose maximum is desired
-     * @return the maximum of the given field for the current date of this calendar
-     * @see #getMaximum
-     * @see #getLeastMaximum
-     * @stable ICU 2.0
-     */
-    public int getActualMaximum(int field) {
-        return calendar.getActualMaximum(getJDKField(field));
-    }
-
-    /**
-     * Returns the minimum value that this field could have, given the current date.
-     * For most fields, this is the same as {@link #getMinimum getMinimum}
-     * and {@link #getGreatestMinimum getGreatestMinimum}.  However, some fields,
-     * especially those related to week number, are more complicated.
-     * <p>
-     * For example, assume {@link #getMinimalDaysInFirstWeek getMinimalDaysInFirstWeek}
-     * returns 4 and {@link #getFirstDayOfWeek getFirstDayOfWeek} returns SUNDAY.
-     * If the first day of the month is Sunday, Monday, Tuesday, or Wednesday
-     * there will be four or more days in the first week, so it will be week number 1,
-     * and <code>getActualMinimum(WEEK_OF_MONTH)</code> will return 1.  However,
-     * if the first of the month is a Thursday, Friday, or Saturday, there are
-     * <em>not</em> four days in that week, so it is week number 0, and
-     * <code>getActualMinimum(WEEK_OF_MONTH)</code> will return 0.
-     * <p>
-     * @param field the field whose actual minimum value is desired.
-     * @return the minimum of the given field for the current date of this calendar
-     *
-     * @see #getMinimum
-     * @see #getGreatestMinimum
-     * @stable ICU 2.0
-     */
-    public int getActualMinimum(int field) {
-        return calendar.getActualMinimum(getJDKField(field));
-    }
-
-    /**
-     * Rolls (up/down) a single unit of time on the given field.  If the
-     * field is rolled past its maximum allowable value, it will "wrap" back
-     * to its minimum and continue rolling. For
-     * example, to roll the current date up by one day, you can call:
-     * <p>
-     * <code>roll({@link #DATE}, true)</code>
-     * <p>
-     * When rolling on the {@link #YEAR} field, it will roll the year
-     * value in the range between 1 and the value returned by calling
-     * {@link #getMaximum getMaximum}({@link #YEAR}).
-     * <p>
-     * When rolling on certain fields, the values of other fields may conflict and
-     * need to be changed.  For example, when rolling the <code>MONTH</code> field
-     * for the Gregorian date 1/31/96 upward, the <code>DAY_OF_MONTH</code> field
-     * must be adjusted so that the result is 2/29/96 rather than the invalid
-     * 2/31/96.
-     * <p>
-     * <b>Note:</b> Calling <tt>roll(field, true)</tt> N times is <em>not</em>
-     * necessarily equivalent to calling <tt>roll(field, N)</tt>.  For example,
-     * imagine that you start with the date Gregorian date January 31, 1995.  If you call
-     * <tt>roll(Calendar.MONTH, 2)</tt>, the result will be March 31, 1995.
-     * But if you call <tt>roll(Calendar.MONTH, true)</tt>, the result will be
-     * February 28, 1995.  Calling it one more time will give March 28, 1995, which
-     * is usually not the desired result.
-     * <p>
-     * <b>Note:</b> You should always use <tt>roll</tt> and <tt>add</tt> rather
-     * than attempting to perform arithmetic operations directly on the fields
-     * of a <tt>Calendar</tt>.  It is quite possible for <tt>Calendar</tt> subclasses
-     * to have fields with non-linear behavior, for example missing months
-     * or days during non-leap years.  The subclasses' <tt>add</tt> and <tt>roll</tt>
-     * methods will take this into account, while simple arithmetic manipulations
-     * may give invalid results.
-     * <p>
-     * @param field the calendar field to roll.
-     *
-     * @param up    indicates if the value of the specified time field is to be
-     *              rolled up or rolled down. Use <code>true</code> if rolling up,
-     *              <code>false</code> otherwise.
-     *
-     * @exception   IllegalArgumentException if the field is invalid or refers
-     *              to a field that cannot be handled by this method.
-     * @see #roll(int, int)
-     * @see #add
-     * @stable ICU 2.0
-     */
-    public final void roll(int field, boolean up)
-    {
-        calendar.roll(getJDKField(field), up);
-    }
-
-    /**
-     * Rolls (up/down) a specified amount time on the given field.  For
-     * example, to roll the current date up by three days, you can call
-     * <code>roll(Calendar.DATE, 3)</code>.  If the
-     * field is rolled past its maximum allowable value, it will "wrap" back
-     * to its minimum and continue rolling.
-     * For example, calling <code>roll(Calendar.DATE, 10)</code>
-     * on a Gregorian calendar set to 4/25/96 will result in the date 4/5/96.
-     * <p>
-     * When rolling on certain fields, the values of other fields may conflict and
-     * need to be changed.  For example, when rolling the {@link #MONTH MONTH} field
-     * for the Gregorian date 1/31/96 by +1, the {@link #DAY_OF_MONTH DAY_OF_MONTH} field
-     * must be adjusted so that the result is 2/29/96 rather than the invalid
-     * 2/31/96.
-     * <p>
-     * {@icunote} the ICU implementation of this method is able to roll
-     * all fields except for {@link #ERA ERA}, {@link #DST_OFFSET DST_OFFSET},
-     * and {@link #ZONE_OFFSET ZONE_OFFSET}.  Subclasses may, of course, add support for
-     * additional fields in their overrides of <code>roll</code>.
-     * <p>
-     * <b>Note:</b> You should always use <tt>roll</tt> and <tt>add</tt> rather
-     * than attempting to perform arithmetic operations directly on the fields
-     * of a <tt>Calendar</tt>.  It is quite possible for <tt>Calendar</tt> subclasses
-     * to have fields with non-linear behavior, for example missing months
-     * or days during non-leap years.  The subclasses' <tt>add</tt> and <tt>roll</tt>
-     * methods will take this into account, while simple arithmetic manipulations
-     * may give invalid results.
-     * <p>
-     * <b>Subclassing:</b><br>
-     * This implementation of <code>roll</code> assumes that the behavior of the
-     * field is continuous between its minimum and maximum, which are found by
-     * calling {@link #getActualMinimum getActualMinimum} and {@link #getActualMaximum getActualMaximum}.
-     * For most such fields, simple addition, subtraction, and modulus operations
-     * are sufficient to perform the roll.  For week-related fields,
-     * the results of {@link #getFirstDayOfWeek getFirstDayOfWeek} and
-     * {@link #getMinimalDaysInFirstWeek getMinimalDaysInFirstWeek} are also necessary.
-     * Subclasses can override these two methods if their values differ from the defaults.
-     * <p>
-     * Subclasses that have fields for which the assumption of continuity breaks
-     * down must overide <code>roll</code> to handle those fields specially.
-     * For example, in the Hebrew calendar the month "Adar I"
-     * only occurs in leap years; in other years the calendar jumps from
-     * Shevat (month #4) to Adar (month #6).  The
-     * {@link HebrewCalendar#roll HebrewCalendar.roll} method takes this into account,
-     * so that rolling the month of Shevat by one gives the proper result (Adar) in a
-     * non-leap year.
-     * <p>
-     * @param field     the calendar field to roll.
-     * @param amount    the amount by which the field should be rolled.
-     *
-     * @exception   IllegalArgumentException if the field is invalid or refers
-     *              to a field that cannot be handled by this method.
-     * @see #roll(int, boolean)
-     * @see #add
-     * @stable ICU 2.0
-     */
-    public void roll(int field, int amount) {
-        calendar.roll(getJDKField(field), amount);
-    }
-
-    /**
-     * Add a signed amount to a specified field, using this calendar's rules.
-     * For example, to add three days to the current date, you can call
-     * <code>add(Calendar.DATE, 3)</code>.
-     * <p>
-     * When adding to certain fields, the values of other fields may conflict and
-     * need to be changed.  For example, when adding one to the {@link #MONTH MONTH} field
-     * for the Gregorian date 1/31/96, the {@link #DAY_OF_MONTH DAY_OF_MONTH} field
-     * must be adjusted so that the result is 2/29/96 rather than the invalid
-     * 2/31/96.
-     * <p>
-     * {@icunote} The ICU implementation of this method is able to add to
-     * all fields except for {@link #ERA ERA}, {@link #DST_OFFSET DST_OFFSET},
-     * and {@link #ZONE_OFFSET ZONE_OFFSET}.  Subclasses may, of course, add support for
-     * additional fields in their overrides of <code>add</code>.
-     * <p>
-     * <b>Note:</b> You should always use <tt>roll</tt> and <tt>add</tt> rather
-     * than attempting to perform arithmetic operations directly on the fields
-     * of a <tt>Calendar</tt>.  It is quite possible for <tt>Calendar</tt> subclasses
-     * to have fields with non-linear behavior, for example missing months
-     * or days during non-leap years.  The subclasses' <tt>add</tt> and <tt>roll</tt>
-     * methods will take this into account, while simple arithmetic manipulations
-     * may give invalid results.
-     * <p>
-     * <b>Subclassing:</b><br>
-     * This implementation of <code>add</code> assumes that the behavior of the
-     * field is continuous between its minimum and maximum, which are found by
-     * calling {@link #getActualMinimum getActualMinimum} and
-     * {@link #getActualMaximum getActualMaximum}.
-     * For such fields, simple arithmetic operations are sufficient to
-     * perform the add.
-     * <p>
-     * Subclasses that have fields for which this assumption of continuity breaks
-     * down must overide <code>add</code> to handle those fields specially.
-     * For example, in the Hebrew calendar the month "Adar I"
-     * only occurs in leap years; in other years the calendar jumps from
-     * Shevat (month #4) to Adar (month #6).  The
-     * {@link HebrewCalendar#add HebrewCalendar.add} method takes this into account,
-     * so that adding one month
-     * to a date in Shevat gives the proper result (Adar) in a non-leap year.
-     * <p>
-     * @param field     the time field.
-     * @param amount    the amount to add to the field.
-     *
-     * @exception   IllegalArgumentException if the field is invalid or refers
-     *              to a field that cannot be handled by this method.
-     * @see #roll(int, int)
-     * @stable ICU 2.0
-     */
-    public void add(int field, int amount) {
-        calendar.add(getJDKField(field), amount);
-    }
-
-    private static String _getDisplayName(Calendar cal) {
-        String type = cal.getType();
-        if (type.equals("japanese")) {
-            return "Japanese Calendar";
-        } else if (type.equals("buddhist")) {
-            return "Buddhist Calendar";
-        }
-        return "Gregorian Calendar";
-    }
-
-    /**
-     * Returns the name of this calendar in the language of the given locale.
-     * @stable ICU 2.0
-     */
-    public String getDisplayName(Locale loc) {
-        return _getDisplayName(this);
-    }
-
-    /**
-     * Returns the name of this calendar in the language of the given locale.
-     * @stable ICU 3.2
-     */
-    public String getDisplayName(ULocale loc) {
-        return _getDisplayName(this);
-    }
-
-    /**
-     * Compares the times (in millis) represented by two
-     * <code>Calendar</code> objects.
-     *
-     * @param that the <code>Calendar</code> to compare to this.
-     * @return <code>0</code> if the time represented by
-     * this <code>Calendar</code> is equal to the time represented
-     * by that <code>Calendar</code>, a value less than
-     * <code>0</code> if the time represented by this is before
-     * the time represented by that, and a value greater than
-     * <code>0</code> if the time represented by this
-     * is after the time represented by that.
-     * @throws NullPointerException if that
-     * <code>Calendar</code> is null.
-     * @throws IllegalArgumentException if the time of that
-     * <code>Calendar</code> can't be obtained because of invalid
-     * calendar values.
-     * @stable ICU 3.4
-     */
-    public int compareTo(Calendar that) {
-        return calendar.compareTo(that.calendar);
-    }
-
-    //-------------------------------------------------------------------------
-    // Interface for creating custon DateFormats for different types of Calendars
-    //-------------------------------------------------------------------------
-
-    /**
-     * {@icu} Returns a <code>DateFormat</code> appropriate to this calendar.
-     * Subclasses wishing to specialize this behavior should override
-     * {@link #handleGetDateFormat}.
-     * @stable ICU 2.0
-     */
-    public DateFormat getDateTimeFormat(int dateStyle, int timeStyle, Locale loc) {
-        if (dateStyle != DateFormat.NONE) {
-            if (timeStyle == DateFormat.NONE) {
-                return DateFormat.getDateInstance((Calendar)this.clone(), dateStyle, loc);
-            } else {
-                return DateFormat.getDateTimeInstance((Calendar)this.clone(), dateStyle, timeStyle, loc);
-            }
-        } else if (timeStyle != DateFormat.NONE) {
-            return DateFormat.getTimeInstance((Calendar)this.clone(), timeStyle, loc);
-        } else {
-            return null;
-        }
-    }
-
-    /**
-     * {@icu} Returns a <code>DateFormat</code> appropriate to this calendar.
-     * Subclasses wishing to specialize this behavior should override
-     * {@link #handleGetDateFormat}.
-     * @stable ICU 3.2
-     */
-    public DateFormat getDateTimeFormat(int dateStyle, int timeStyle, ULocale loc) {
-        return getDateTimeFormat(dateStyle, timeStyle, loc.toLocale());
-    }
-
-    //-------------------------------------------------------------------------
-    // Constants
-    //-------------------------------------------------------------------------
-
-    /**
-     * {@icu} Returns the difference between the given time and the time this
-     * calendar object is set to.  If this calendar is set
-     * <em>before</em> the given time, the returned value will be
-     * positive.  If this calendar is set <em>after</em> the given
-     * time, the returned value will be negative.  The
-     * <code>field</code> parameter specifies the units of the return
-     * value.  For example, if <code>fieldDifference(when,
-     * Calendar.MONTH)</code> returns 3, then this calendar is set to
-     * 3 months before <code>when</code>, and possibly some additional
-     * time less than one month.
-     *
-     * <p>As a side effect of this call, this calendar is advanced
-     * toward <code>when</code> by the given amount.  That is, calling
-     * this method has the side effect of calling <code>add(field,
-     * n)</code>, where <code>n</code> is the return value.
-     *
-     * <p>Usage: To use this method, call it first with the largest
-     * field of interest, then with progressively smaller fields.  For
-     * example:
-     *
-     * <pre>
-     * int y = cal.fieldDifference(when, Calendar.YEAR);
-     * int m = cal.fieldDifference(when, Calendar.MONTH);
-     * int d = cal.fieldDifference(when, Calendar.DATE);</pre>
-     *
-     * computes the difference between <code>cal</code> and
-     * <code>when</code> in years, months, and days.
-     *
-     * <p>Note: <code>fieldDifference()</code> is
-     * <em>asymmetrical</em>.  That is, in the following code:
-     *
-     * <pre>
-     * cal.setTime(date1);
-     * int m1 = cal.fieldDifference(date2, Calendar.MONTH);
-     * int d1 = cal.fieldDifference(date2, Calendar.DATE);
-     * cal.setTime(date2);
-     * int m2 = cal.fieldDifference(date1, Calendar.MONTH);
-     * int d2 = cal.fieldDifference(date1, Calendar.DATE);</pre>
-     *
-     * one might expect that <code>m1 == -m2 && d1 == -d2</code>.
-     * However, this is not generally the case, because of
-     * irregularities in the underlying calendar system (e.g., the
-     * Gregorian calendar has a varying number of days per month).
-     *
-     * @param when the date to compare this calendar's time to
-     * @param field the field in which to compute the result
-     * @return the difference, either positive or negative, between
-     * this calendar's time and <code>when</code>, in terms of
-     * <code>field</code>.
-     * @stable ICU 2.0
-     */
-    public int fieldDifference(Date when, int field) {
-        int min = 0;
-        long startMs = getTimeInMillis();
-        long targetMs = when.getTime();
-        // Always add from the start millis.  This accomodates
-        // operations like adding years from February 29, 2000 up to
-        // February 29, 2004.  If 1, 1, 1, 1 is added to the year
-        // field, the DOM gets pinned to 28 and stays there, giving an
-        // incorrect DOM difference of 1.  We have to add 1, reset, 2,
-        // reset, 3, reset, 4.
-        if (startMs < targetMs) {
-            int max = 1;
-            // Find a value that is too large
-            for (;;) {
-                setTimeInMillis(startMs);
-                add(field, max);
-                long ms = getTimeInMillis();
-                if (ms == targetMs) {
-                    return max;
-                } else if (ms > targetMs) {
-                    break;
-                } else {
-                    max <<= 1;
-                    if (max < 0) {
-                        // Field difference too large to fit into int
-                        throw new RuntimeException();
-                    }
-                }
-            }
-            // Do a binary search
-            while ((max - min) > 1) {
-                int t = (min + max) / 2;
-                setTimeInMillis(startMs);
-                add(field, t);
-                long ms = getTimeInMillis();
-                if (ms == targetMs) {
-                    return t;
-                } else if (ms > targetMs) {
-                    max = t;
-                } else {
-                    min = t;
-                }
-            }
-        } else if (startMs > targetMs) {
-            //Eclipse stated the following is "dead code"
-            /*if (false) {
-                // This works, and makes the code smaller, but costs
-                // an extra object creation and an extra couple cycles
-                // of calendar computation.
-                setTimeInMillis(targetMs);
-                min = -fieldDifference(new Date(startMs), field);
-            }*/
-            int max = -1;
-            // Find a value that is too small
-            for (;;) {
-                setTimeInMillis(startMs);
-                add(field, max);
-                long ms = getTimeInMillis();
-                if (ms == targetMs) {
-                    return max;
-                } else if (ms < targetMs) {
-                    break;
-                } else {
-                    max <<= 1;
-                    if (max == 0) {
-                        // Field difference too large to fit into int
-                        throw new RuntimeException();
-                    }
-                }
-            }
-            // Do a binary search
-            while ((min - max) > 1) {
-                int t = (min + max) / 2;
-                setTimeInMillis(startMs);
-                add(field, t);
-                long ms = getTimeInMillis();
-                if (ms == targetMs) {
-                    return t;
-                } else if (ms < targetMs) {
-                    max = t;
-                } else {
-                    min = t;
-                }
-            }
-        }
-        // Set calendar to end point
-        setTimeInMillis(startMs);
-        add(field, min);
-        return min;
-    }
-
-    /**
-     * Sets the time zone with the given time zone value.
-     * @param value the given time zone.
-     * @stable ICU 2.0
-     */
-    public void setTimeZone(TimeZone value)
-    {
-        calendar.setTimeZone(value.timeZone);
-    }
-
-    /**
-     * Returns the time zone.
-     * @return the time zone object associated with this calendar.
-     * @stable ICU 2.0
-     */
-    public TimeZone getTimeZone()
-    {
-        return new TimeZone(calendar.getTimeZone());
-    }
-
-    /**
-     * Specify whether or not date/time interpretation is to be lenient.  With
-     * lenient interpretation, a date such as "February 942, 1996" will be
-     * treated as being equivalent to the 941st day after February 1, 1996.
-     * With strict interpretation, such dates will cause an exception to be
-     * thrown.
-     *
-     * @see DateFormat#setLenient
-     * @stable ICU 2.0
-     */
-    public void setLenient(boolean lenient)
-    {
-        calendar.setLenient(lenient);
-    }
-
-    /**
-     * Tell whether date/time interpretation is to be lenient.
-     * @stable ICU 2.0
-     */
-    public boolean isLenient()
-    {
-        return calendar.isLenient();
-    }
-
-    /**
-     * Sets what the first day of the week is; e.g., Sunday in US,
-     * Monday in France.
-     * @param value the given first day of the week.
-     * @stable ICU 2.0
-     */
-    public void setFirstDayOfWeek(int value)
-    {
-        calendar.setFirstDayOfWeek(value);
-    }
-
-    /**
-     * Returns what the first day of the week is; e.g., Sunday in US,
-     * Monday in France.
-     * @return the first day of the week.
-     * @stable ICU 2.0
-     */
-    public int getFirstDayOfWeek()
-    {
-        return calendar.getFirstDayOfWeek();
-    }
-
-    /**
-     * Sets what the minimal days required in the first week of the year are.
-     * For example, if the first week is defined as one that contains the first
-     * day of the first month of a year, call the method with value 1. If it
-     * must be a full week, use value 7.
-     * @param value the given minimal days required in the first week
-     * of the year.
-     * @stable ICU 2.0
-     */
-    public void setMinimalDaysInFirstWeek(int value)
-    {
-        calendar.setMinimalDaysInFirstWeek(value);
-    }
-
-    /**
-     * Returns what the minimal days required in the first week of the year are;
-     * e.g., if the first week is defined as one that contains the first day
-     * of the first month of a year, getMinimalDaysInFirstWeek returns 1. If
-     * the minimal days required must be a full week, getMinimalDaysInFirstWeek
-     * returns 7.
-     * @return the minimal days required in the first week of the year.
-     * @stable ICU 2.0
-     */
-    public int getMinimalDaysInFirstWeek()
-    {
-        return calendar.getMinimalDaysInFirstWeek();
-    }
-
-    /**
-     * Returns the minimum value for the given time field.
-     * e.g., for Gregorian DAY_OF_MONTH, 1.
-     * @param field the given time field.
-     * @return the minimum value for the given time field.
-     * @stable ICU 2.0
-     */
-    public final int getMinimum(int field) {
-        return calendar.getMinimum(getJDKField(field));
-    }
-
-    /**
-     * Returns the maximum value for the given time field.
-     * e.g. for Gregorian DAY_OF_MONTH, 31.
-     * @param field the given time field.
-     * @return the maximum value for the given time field.
-     * @stable ICU 2.0
-     */
-    public final int getMaximum(int field) {
-        return calendar.getMaximum(getJDKField(field));
-    }
-
-    /**
-     * Returns the highest minimum value for the given field if varies.
-     * Otherwise same as getMinimum(). For Gregorian, no difference.
-     * @param field the given time field.
-     * @return the highest minimum value for the given time field.
-     * @stable ICU 2.0
-     */
-    public final int getGreatestMinimum(int field) {
-        return calendar.getGreatestMinimum(getJDKField(field));
-    }
-
-    /**
-     * Returns the lowest maximum value for the given field if varies.
-     * Otherwise same as getMaximum(). e.g., for Gregorian DAY_OF_MONTH, 28.
-     * @param field the given time field.
-     * @return the lowest maximum value for the given time field.
-     * @stable ICU 2.0
-     */
-    public final int getLeastMaximum(int field) {
-        return calendar.getLeastMaximum(getJDKField(field));
-    }
-
-    //-------------------------------------------------------------------------
-    // Weekend support -- determining which days of the week are the weekend
-    // in a given locale
-    //-------------------------------------------------------------------------
-
-    /**
-     * {@icu} Returns whether the given day of the week is a weekday, a
-     * weekend day, or a day that transitions from one to the other,
-     * in this calendar system.  If a transition occurs at midnight,
-     * then the days before and after the transition will have the
-     * type WEEKDAY or WEEKEND.  If a transition occurs at a time
-     * other than midnight, then the day of the transition will have
-     * the type WEEKEND_ONSET or WEEKEND_CEASE.  In this case, the
-     * method getWeekendTransition() will return the point of
-     * transition.
-     * @param dayOfWeek either SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
-     * THURSDAY, FRIDAY, or SATURDAY
-     * @return either WEEKDAY, WEEKEND, WEEKEND_ONSET, or
-     * WEEKEND_CEASE
-     * @exception IllegalArgumentException if dayOfWeek is not
-     * between SUNDAY and SATURDAY, inclusive
-     * @see #WEEKDAY
-     * @see #WEEKEND
-     * @see #WEEKEND_ONSET
-     * @see #WEEKEND_CEASE
-     * @see #getWeekendTransition
-     * @see #isWeekend(Date)
-     * @see #isWeekend()
-     * @stable ICU 2.0
-     */
-    public int getDayOfWeekType(int dayOfWeek) {
-        // weekend always full saturday and sunday with com.ibm.icu.base
-        if (dayOfWeek < SUNDAY || dayOfWeek > 7) {
-            throw new IllegalArgumentException("illegal day of week: " + dayOfWeek);
-        } else if (dayOfWeek == SATURDAY || dayOfWeek == SUNDAY) {
-            return WEEKEND;
-        }
-        return WEEKDAY;}
-
-    /**
-     * {@icu} Returns the time during the day at which the weekend begins or end in this
-     * calendar system.  If getDayOfWeekType(dayOfWeek) == WEEKEND_ONSET return the time
-     * at which the weekend begins.  If getDayOfWeekType(dayOfWeek) == WEEKEND_CEASE
-     * return the time at which the weekend ends.  If getDayOfWeekType(dayOfWeek) has some
-     * other value, then throw an exception.
-     * @param dayOfWeek either SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
-     * THURSDAY, FRIDAY, or SATURDAY
-     * @return the milliseconds after midnight at which the
-     * weekend begins or ends
-     * @exception IllegalArgumentException if dayOfWeek is not
-     * WEEKEND_ONSET or WEEKEND_CEASE
-     * @see #getDayOfWeekType
-     * @see #isWeekend(Date)
-     * @see #isWeekend()
-     * @stable ICU 2.0
-     */
-    public int getWeekendTransition(int dayOfWeek) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Returns true if the given date and time is in the weekend in this calendar
-     * system.  Equivalent to calling setTime() followed by isWeekend().  Note: This
-     * method changes the time this calendar is set to.
-     * @param date the date and time
-     * @return true if the given date and time is part of the
-     * weekend
-     * @see #getDayOfWeekType
-     * @see #getWeekendTransition
-     * @see #isWeekend()
-     * @stable ICU 2.0
-     */
-    public boolean isWeekend(Date date) {
-        calendar.setTime(date);
-        return isWeekend();
-    }
-
-    /**
-     * {@icu} Returns true if this Calendar's current date and time is in the weekend in
-     * this calendar system.
-     * @return true if the given date and time is part of the
-     * weekend
-     * @see #getDayOfWeekType
-     * @see #getWeekendTransition
-     * @see #isWeekend(Date)
-     * @stable ICU 2.0
-     */
-    public boolean isWeekend() {
-        // weekend always full saturday and sunday with com.ibm.icu.base
-        int dow = calendar.get(Calendar.DAY_OF_WEEK);
-        if (dow == SATURDAY || dow == SUNDAY) {
-            return true;
-        }
-        return false;
-    }
-
-    //-------------------------------------------------------------------------
-    // End of weekend support
-    //-------------------------------------------------------------------------
-
-    /**
-     * Overrides Cloneable
-     * @stable ICU 2.0
-     */
-    public Object clone()
-    {
-        return new Calendar((java.util.Calendar)calendar.clone());
-    }
-
-    /**
-     * Returns a string representation of this calendar. This method
-     * is intended to be used only for debugging purposes, and the
-     * format of the returned string may vary between implementations.
-     * The returned string may be empty but may not be <code>null</code>.
-     *
-     * @return  a string representation of this calendar.
-     * @stable ICU 2.0
-     */
-    public String toString() {
-        return calendar.toString();
-    }
-
-    /**
-     * {@icu} Returns the number of fields defined by this calendar.  Valid field
-     * arguments to <code>set()</code> and <code>get()</code> are
-     * <code>0..getFieldCount()-1</code>.
-     * @stable ICU 2.0
-     */
-    public final int getFieldCount() {
-        return FIELD_COUNT;
-    }
-    private static final int FIELD_COUNT = IS_LEAP_MONTH + 1;
-
-    /**
-     * {@icu} Returns the current Calendar type.  Note, in 3.0 this function will return
-     * 'gregorian' in Calendar to emulate legacy behavior
-     * @return type of calendar (gregorian, etc)
-     * @stable ICU 3.8
-     */
-    public String getType() {
-        // JDK supports Gregorian, Japanese and Buddhist
-        String name = calendar.getClass().getSimpleName().toLowerCase(Locale.US);
-        if (name.contains("japanese")) {
-            return "japanese";
-        } else if (name.contains("buddhist")) {
-            return "buddhist";
-        }
-        return "gregorian";
-    }
-
-    // -------- BEGIN ULocale boilerplate --------
-
-    /**
-     * {@icu} Returns the locale that was used to create this object, or null.
-     * This may may differ from the locale requested at the time of
-     * this object's creation.  For example, if an object is created
-     * for locale <tt>en_US_CALIFORNIA</tt>, the actual data may be
-     * drawn from <tt>en</tt> (the <i>actual</i> locale), and
-     * <tt>en_US</tt> may be the most specific locale that exists (the
-     * <i>valid</i> locale).
-     *
-     * <p>Note: This method will be implemented in ICU 3.0; ICU 2.8
-     * contains a partial preview implementation.  The * <i>actual</i>
-     * locale is returned correctly, but the <i>valid</i> locale is
-     * not, in most cases.
-     * @param type type of information requested, either {@link
-     * com.ibm.icu.util.ULocale#VALID_LOCALE} or {@link
-     * com.ibm.icu.util.ULocale#ACTUAL_LOCALE}.
-     * @return the information specified by <i>type</i>, or null if
-     * this object was not constructed from locale data.
-     * @see com.ibm.icu.util.ULocale
-     * @see com.ibm.icu.util.ULocale#VALID_LOCALE
-     * @see com.ibm.icu.util.ULocale#ACTUAL_LOCALE
-     * @draft ICU 2.8 (retain)
-     * @provisional This API might change or be removed in a future release.
-     */
-    public final ULocale getLocale(ULocale.Type type) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    // -------- END ULocale boilerplate --------
-
-
-    private static int getJDKField(int icuField) {
-        switch (icuField) {
-        case ERA:
-            return java.util.Calendar.ERA;
-        case YEAR:
-            return java.util.Calendar.YEAR;
-        case MONTH:
-            return java.util.Calendar.MONTH;
-        case WEEK_OF_YEAR:
-            return java.util.Calendar.WEEK_OF_YEAR;
-        case WEEK_OF_MONTH:
-            return java.util.Calendar.WEEK_OF_MONTH;
-        case DATE:
-            return java.util.Calendar.DATE;
-//        case DAY_OF_MONTH:
-//            return java.util.Calendar.DAY_OF_MONTH;
-        case DAY_OF_YEAR:
-            return java.util.Calendar.DAY_OF_YEAR;
-        case DAY_OF_WEEK:
-            return java.util.Calendar.DAY_OF_WEEK;
-        case DAY_OF_WEEK_IN_MONTH:
-            return java.util.Calendar.DAY_OF_WEEK_IN_MONTH;
-        case AM_PM:
-            return java.util.Calendar.AM_PM;
-        case HOUR:
-            return java.util.Calendar.HOUR;
-        case HOUR_OF_DAY:
-            return java.util.Calendar.HOUR_OF_DAY;
-        case MINUTE:
-            return java.util.Calendar.MINUTE;
-        case SECOND:
-            return java.util.Calendar.SECOND;
-        case MILLISECOND:
-            return java.util.Calendar.MILLISECOND;
-        case ZONE_OFFSET:
-            return java.util.Calendar.ZONE_OFFSET;
-        case DST_OFFSET:
-            return java.util.Calendar.DST_OFFSET;
-
-        case YEAR_WOY:
-        case DOW_LOCAL:
-        case EXTENDED_YEAR:
-        case JULIAN_DAY:
-        case MILLISECONDS_IN_DAY:
-            // Unmappable
-            throw new UnsupportedOperationException("Calendar field type not supported by com.ibm.icu.base");
-        default:
-            // Illegal
-            throw new ArrayIndexOutOfBoundsException("Specified calendar field is out of range");
-        }
-    }
-}
+/*
+*   Copyright (C) 1996-2011, International Business Machines
+*   Corporation and others.  All Rights Reserved.
+*/
+
+package com.ibm.icu.util;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.Locale;
+
+import com.ibm.icu.text.DateFormat;
+import com.ibm.icu.util.ULocale.Category;
+
+/**
+ * {@icuenhanced java.util.Calendar}.{@icu _usage_}
+ *
+ * <p><code>Calendar</code> is an abstract base class for converting between
+ * a <code>Date</code> object and a set of integer fields such as
+ * <code>YEAR</code>, <code>MONTH</code>, <code>DAY</code>, <code>HOUR</code>,
+ * and so on. (A <code>Date</code> object represents a specific instant in
+ * time with millisecond precision. See
+ * {@link Date}
+ * for information about the <code>Date</code> class.)
+ *
+ * <p>Subclasses of <code>Calendar</code> interpret a <code>Date</code>
+ * according to the rules of a specific calendar system.  ICU4J contains
+ * several subclasses implementing different international calendar systems.
+ *
+ * <p>
+ * Like other locale-sensitive classes, <code>Calendar</code> provides a
+ * class method, <code>getInstance</code>, for getting a generally useful
+ * object of this type. <code>Calendar</code>'s <code>getInstance</code> method
+ * returns a calendar of a type appropriate to the locale, whose
+ * time fields have been initialized with the current date and time:
+ * <blockquote>
+ * <pre>Calendar rightNow = Calendar.getInstance()</pre>
+ * </blockquote>
+ *
+ * <p>When a <code>ULocale</code> is used by <code>getInstance</code>, its
+ * '<code>calendar</code>' tag and value are retrieved if present.  If a recognized
+ * value is supplied, a calendar is provided and configured as appropriate.
+ * Currently recognized tags are "buddhist", "chinese", "coptic", "ethiopic",
+ * "gregorian", "hebrew", "islamic", "islamic-civil", "japanese", and "roc".  For
+ * example: <blockquote>
+ * <pre>Calendar cal = Calendar.getInstance(new ULocale("en_US@calendar=japanese"));</pre>
+ * </blockquote> will return an instance of JapaneseCalendar (using en_US conventions for
+ * minimum days in first week, start day of week, et cetera).
+ *
+ * <p>A <code>Calendar</code> object can produce all the time field values
+ * needed to implement the date-time formatting for a particular language and
+ * calendar style (for example, Japanese-Gregorian, Japanese-Traditional).
+ * <code>Calendar</code> defines the range of values returned by certain fields,
+ * as well as their meaning.  For example, the first month of the year has value
+ * <code>MONTH</code> == <code>JANUARY</code> for all calendars.  Other values
+ * are defined by the concrete subclass, such as <code>ERA</code> and
+ * <code>YEAR</code>.  See individual field documentation and subclass
+ * documentation for details.
+ *
+ * <p>When a <code>Calendar</code> is <em>lenient</em>, it accepts a wider range
+ * of field values than it produces.  For example, a lenient
+ * <code>GregorianCalendar</code> interprets <code>MONTH</code> ==
+ * <code>JANUARY</code>, <code>DAY_OF_MONTH</code> == 32 as February 1.  A
+ * non-lenient <code>GregorianCalendar</code> throws an exception when given
+ * out-of-range field settings.  When calendars recompute field values for
+ * return by <code>get()</code>, they normalize them.  For example, a
+ * <code>GregorianCalendar</code> always produces <code>DAY_OF_MONTH</code>
+ * values between 1 and the length of the month.
+ *
+ * <p><code>Calendar</code> defines a locale-specific seven day week using two
+ * parameters: the first day of the week and the minimal days in first week
+ * (from 1 to 7).  These numbers are taken from the locale resource data when a
+ * <code>Calendar</code> is constructed.  They may also be specified explicitly
+ * through the API.
+ *
+ * <p>When setting or getting the <code>WEEK_OF_MONTH</code> or
+ * <code>WEEK_OF_YEAR</code> fields, <code>Calendar</code> must determine the
+ * first week of the month or year as a reference point.  The first week of a
+ * month or year is defined as the earliest seven day period beginning on
+ * <code>getFirstDayOfWeek()</code> and containing at least
+ * <code>getMinimalDaysInFirstWeek()</code> days of that month or year.  Weeks
+ * numbered ..., -1, 0 precede the first week; weeks numbered 2, 3,... follow
+ * it.  Note that the normalized numbering returned by <code>get()</code> may be
+ * different.  For example, a specific <code>Calendar</code> subclass may
+ * designate the week before week 1 of a year as week <em>n</em> of the previous
+ * year.
+ *
+ * <p> When computing a <code>Date</code> from time fields, two special
+ * circumstances may arise: there may be insufficient information to compute the
+ * <code>Date</code> (such as only year and month but no day in the month), or
+ * there may be inconsistent information (such as "Tuesday, July 15, 1996" --
+ * July 15, 1996 is actually a Monday).
+ *
+ * <p><strong>Insufficient information.</strong> The calendar will use default
+ * information to specify the missing fields. This may vary by calendar; for
+ * the Gregorian calendar, the default for a field is the same as that of the
+ * start of the epoch: i.e., YEAR = 1970, MONTH = JANUARY, DATE = 1, etc.
+ *
+ * <p><strong>Inconsistent information.</strong> If fields conflict, the calendar
+ * will give preference to fields set more recently. For example, when
+ * determining the day, the calendar will look for one of the following
+ * combinations of fields.  The most recent combination, as determined by the
+ * most recently set single field, will be used.
+ *
+ * <blockquote>
+ * <pre>
+ * MONTH + DAY_OF_MONTH
+ * MONTH + WEEK_OF_MONTH + DAY_OF_WEEK
+ * MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK
+ * DAY_OF_YEAR
+ * DAY_OF_WEEK + WEEK_OF_YEAR</pre>
+ * </blockquote>
+ *
+ * For the time of day:
+ *
+ * <blockquote>
+ * <pre>
+ * HOUR_OF_DAY
+ * AM_PM + HOUR</pre>
+ * </blockquote>
+ *
+ * <p><strong>Note:</strong> for some non-Gregorian calendars, different
+ * fields may be necessary for complete disambiguation. For example, a full
+ * specification of the historial Arabic astronomical calendar requires year,
+ * month, day-of-month <em>and</em> day-of-week in some cases.
+ *
+ * <p><strong>Note:</strong> There are certain possible ambiguities in
+ * interpretation of certain singular times, which are resolved in the
+ * following ways:
+ * <ol>
+ *     <li> 24:00:00 "belongs" to the following day. That is,
+ *          23:59 on Dec 31, 1969 &lt; 24:00 on Jan 1, 1970 &lt; 24:01:00 on Jan 1, 1970
+ *
+ *     <li> Although historically not precise, midnight also belongs to "am",
+ *          and noon belongs to "pm", so on the same day,
+ *          12:00 am (midnight) &lt; 12:01 am, and 12:00 pm (noon) &lt; 12:01 pm
+ * </ol>
+ *
+ * <p>The date or time format strings are not part of the definition of a
+ * calendar, as those must be modifiable or overridable by the user at
+ * runtime. Use {@link DateFormat}
+ * to format dates.
+ *
+ * <p><strong>Field manipulation methods</strong></p>
+ *
+ * <p><code>Calendar</code> fields can be changed using three methods:
+ * <code>set()</code>, <code>add()</code>, and <code>roll()</code>.</p>
+ *
+ * <p><strong><code>set(f, value)</code></strong> changes field
+ * <code>f</code> to <code>value</code>.  In addition, it sets an
+ * internal member variable to indicate that field <code>f</code> has
+ * been changed. Although field <code>f</code> is changed immediately,
+ * the calendar's milliseconds is not recomputed until the next call to
+ * <code>get()</code>, <code>getTime()</code>, or
+ * <code>getTimeInMillis()</code> is made. Thus, multiple calls to
+ * <code>set()</code> do not trigger multiple, unnecessary
+ * computations. As a result of changing a field using
+ * <code>set()</code>, other fields may also change, depending on the
+ * field, the field value, and the calendar system. In addition,
+ * <code>get(f)</code> will not necessarily return <code>value</code>
+ * after the fields have been recomputed. The specifics are determined by
+ * the concrete calendar class.</p>
+ *
+ * <p><em>Example</em>: Consider a <code>GregorianCalendar</code>
+ * originally set to August 31, 1999. Calling <code>set(Calendar.MONTH,
+ * Calendar.SEPTEMBER)</code> sets the calendar to September 31,
+ * 1999. This is a temporary internal representation that resolves to
+ * October 1, 1999 if <code>getTime()</code>is then called. However, a
+ * call to <code>set(Calendar.DAY_OF_MONTH, 30)</code> before the call to
+ * <code>getTime()</code> sets the calendar to September 30, 1999, since
+ * no recomputation occurs after <code>set()</code> itself.</p>
+ *
+ * <p><strong><code>add(f, delta)</code></strong> adds <code>delta</code>
+ * to field <code>f</code>.  This is equivalent to calling <code>set(f,
+ * get(f) + delta)</code> with two adjustments:</p>
+ *
+ * <blockquote>
+ *   <p><strong>Add rule 1</strong>. The value of field <code>f</code>
+ *   after the call minus the value of field <code>f</code> before the
+ *   call is <code>delta</code>, modulo any overflow that has occurred in
+ *   field <code>f</code>. Overflow occurs when a field value exceeds its
+ *   range and, as a result, the next larger field is incremented or
+ *   decremented and the field value is adjusted back into its range.</p>
+ *
+ *   <p><strong>Add rule 2</strong>. If a smaller field is expected to be
+ *   invariant, but &nbsp; it is impossible for it to be equal to its
+ *   prior value because of changes in its minimum or maximum after field
+ *   <code>f</code> is changed, then its value is adjusted to be as close
+ *   as possible to its expected value. A smaller field represents a
+ *   smaller unit of time. <code>HOUR</code> is a smaller field than
+ *   <code>DAY_OF_MONTH</code>. No adjustment is made to smaller fields
+ *   that are not expected to be invariant. The calendar system
+ *   determines what fields are expected to be invariant.</p>
+ * </blockquote>
+ *
+ * <p>In addition, unlike <code>set()</code>, <code>add()</code> forces
+ * an immediate recomputation of the calendar's milliseconds and all
+ * fields.</p>
+ *
+ * <p><em>Example</em>: Consider a <code>GregorianCalendar</code>
+ * originally set to August 31, 1999. Calling <code>add(Calendar.MONTH,
+ * 13)</code> sets the calendar to September 30, 2000. <strong>Add rule
+ * 1</strong> sets the <code>MONTH</code> field to September, since
+ * adding 13 months to August gives September of the next year. Since
+ * <code>DAY_OF_MONTH</code> cannot be 31 in September in a
+ * <code>GregorianCalendar</code>, <strong>add rule 2</strong> sets the
+ * <code>DAY_OF_MONTH</code> to 30, the closest possible value. Although
+ * it is a smaller field, <code>DAY_OF_WEEK</code> is not adjusted by
+ * rule 2, since it is expected to change when the month changes in a
+ * <code>GregorianCalendar</code>.</p>
+ *
+ * <p><strong><code>roll(f, delta)</code></strong> adds
+ * <code>delta</code> to field <code>f</code> without changing larger
+ * fields. This is equivalent to calling <code>add(f, delta)</code> with
+ * the following adjustment:</p>
+ *
+ * <blockquote>
+ *   <p><strong>Roll rule</strong>. Larger fields are unchanged after the
+ *   call. A larger field represents a larger unit of
+ *   time. <code>DAY_OF_MONTH</code> is a larger field than
+ *   <code>HOUR</code>.</p>
+ * </blockquote>
+ *
+ * <p><em>Example</em>: Consider a <code>GregorianCalendar</code>
+ * originally set to August 31, 1999. Calling <code>roll(Calendar.MONTH,
+ * 8)</code> sets the calendar to April 30, <strong>1999</strong>.  Add
+ * rule 1 sets the <code>MONTH</code> field to April. Using a
+ * <code>GregorianCalendar</code>, the <code>DAY_OF_MONTH</code> cannot
+ * be 31 in the month April. Add rule 2 sets it to the closest possible
+ * value, 30. Finally, the <strong>roll rule</strong> maintains the
+ * <code>YEAR</code> field value of 1999.</p>
+ *
+ * <p><em>Example</em>: Consider a <code>GregorianCalendar</code>
+ * originally set to Sunday June 6, 1999. Calling
+ * <code>roll(Calendar.WEEK_OF_MONTH, -1)</code> sets the calendar to
+ * Tuesday June 1, 1999, whereas calling
+ * <code>add(Calendar.WEEK_OF_MONTH, -1)</code> sets the calendar to
+ * Sunday May 30, 1999. This is because the roll rule imposes an
+ * additional constraint: The <code>MONTH</code> must not change when the
+ * <code>WEEK_OF_MONTH</code> is rolled. Taken together with add rule 1,
+ * the resultant date must be between Tuesday June 1 and Saturday June
+ * 5. According to add rule 2, the <code>DAY_OF_WEEK</code>, an invariant
+ * when changing the <code>WEEK_OF_MONTH</code>, is set to Tuesday, the
+ * closest possible value to Sunday (where Sunday is the first day of the
+ * week).</p>
+ *
+ * <p><strong>Usage model</strong>. To motivate the behavior of
+ * <code>add()</code> and <code>roll()</code>, consider a user interface
+ * component with increment and decrement buttons for the month, day, and
+ * year, and an underlying <code>GregorianCalendar</code>. If the
+ * interface reads January 31, 1999 and the user presses the month
+ * increment button, what should it read? If the underlying
+ * implementation uses <code>set()</code>, it might read March 3, 1999. A
+ * better result would be February 28, 1999. Furthermore, if the user
+ * presses the month increment button again, it should read March 31,
+ * 1999, not March 28, 1999. By saving the original date and using either
+ * <code>add()</code> or <code>roll()</code>, depending on whether larger
+ * fields should be affected, the user interface can behave as most users
+ * will intuitively expect.</p>
+ *
+ * <p><b>Note:</b> You should always use {@link #roll roll} and {@link #add add} rather
+ * than attempting to perform arithmetic operations directly on the fields
+ * of a <tt>Calendar</tt>.  It is quite possible for <tt>Calendar</tt> subclasses
+ * to have fields with non-linear behavior, for example missing months
+ * or days during non-leap years.  The subclasses' <tt>add</tt> and <tt>roll</tt>
+ * methods will take this into account, while simple arithmetic manipulations
+ * may give invalid results.
+ *
+ * <p><big><big><b>Calendar Architecture in ICU4J</b></big></big></p>
+ *
+ * <p>Recently the implementation of <code>Calendar</code> has changed
+ * significantly in order to better support subclassing. The original
+ * <code>Calendar</code> class was designed to support subclassing, but
+ * it had only one implemented subclass, <code>GregorianCalendar</code>.
+ * With the implementation of several new calendar subclasses, including
+ * the <code>BuddhistCalendar</code>, <code>ChineseCalendar</code>,
+ * <code>HebrewCalendar</code>, <code>IslamicCalendar</code>, and
+ * <code>JapaneseCalendar</code>, the subclassing API has been reworked
+ * thoroughly. This section details the new subclassing API and other
+ * ways in which <code>com.ibm.icu.util.Calendar</code> differs from
+ * <code>java.util.Calendar</code>.
+ * </p>
+ *
+ * <p><big><b>Changes</b></big></p>
+ *
+ * <p>Overview of changes between the classic <code>Calendar</code>
+ * architecture and the new architecture.
+ *
+ * <ul>
+ *
+ *   <li>The <code>fields[]</code> array is <code>private</code> now
+ *     instead of <code>protected</code>.  Subclasses must access it
+ *     using the methods {@link #internalSet} and
+ *     {@link #internalGet}.  <b>Motivation:</b> Subclasses should
+ *     not directly access data members.</li>
+ *
+ *   <li>The <code>time</code> long word is <code>private</code> now
+ *     instead of <code>protected</code>.  Subclasses may access it using
+ *     the method {@link #internalGetTimeInMillis}, which does not
+ *     provoke an update. <b>Motivation:</b> Subclasses should not
+ *     directly access data members.</li>
+ *
+ *   <li>The scope of responsibility of subclasses has been drastically
+ *     reduced. As much functionality as possible is implemented in the
+ *     <code>Calendar</code> base class. As a result, it is much easier
+ *     to subclass <code>Calendar</code>. <b>Motivation:</b> Subclasses
+ *     should not have to reimplement common code. Certain behaviors are
+ *     common across calendar systems: The definition and behavior of
+ *     week-related fields and time fields, the arithmetic
+ *     ({@link #add(int, int) add} and {@link #roll(int, int) roll}) behavior of many
+ *     fields, and the field validation system.</li>
+ *
+ *   <li>The subclassing API has been completely redesigned.</li>
+ *
+ *   <li>The <code>Calendar</code> base class contains some Gregorian
+ *     calendar algorithmic support that subclasses can use (specifically
+ *     in {@link #handleComputeFields}).  Subclasses can use the
+ *     methods <code>getGregorianXxx()</code> to obtain precomputed
+ *     values. <b>Motivation:</b> This is required by all
+ *     <code>Calendar</code> subclasses in order to implement consistent
+ *     time zone behavior, and Gregorian-derived systems can use the
+ *     already computed data.</li>
+ *
+ *   <li>The <code>FIELD_COUNT</code> constant has been removed. Use
+ *     {@link #getFieldCount}.  In addition, framework API has been
+ *     added to allow subclasses to define additional fields.
+ *     <b>Motivation: </b>The number of fields is not constant across
+ *     calendar systems.</li>
+ *
+ *   <li>The range of handled dates has been narrowed from +/-
+ *     ~300,000,000 years to +/- ~5,000,000 years. In practical terms
+ *     this should not affect clients. However, it does mean that client
+ *     code cannot be guaranteed well-behaved results with dates such as
+ *     <code>Date(Long.MIN_VALUE)</code> or
+ *     <code>Date(Long.MAX_VALUE)</code>. Instead, the
+ *     <code>Calendar</code> protected constants should be used.
+ *     <b>Motivation:</b> With
+ *     the addition of the {@link #JULIAN_DAY} field, Julian day
+ *     numbers must be restricted to a 32-bit <code>int</code>.  This
+ *     restricts the overall supported range. Furthermore, restricting
+ *     the supported range simplifies the computations by removing
+ *     special case code that was used to accomodate arithmetic overflow
+ *     at millis near <code>Long.MIN_VALUE</code> and
+ *     <code>Long.MAX_VALUE</code>.</li>
+ *
+ *   <li>New fields are implemented: {@link #JULIAN_DAY} defines
+ *     single-field specification of the
+ *     date. {@link #MILLISECONDS_IN_DAY} defines a single-field
+ *     specification of the wall time. {@link #DOW_LOCAL} and
+ *     {@link #YEAR_WOY} implement localized day-of-week and
+ *     week-of-year behavior.</li>
+ *
+ *   <li>Subclasses can access protected millisecond constants
+ *   defined in <code>Calendar</code>.</li>
+ *
+ *   <li>New API has been added to support calendar-specific subclasses
+ *     of <code>DateFormat</code>.</li>
+ *
+ *   <li>Several subclasses have been implemented, representing
+ *     various international calendar systems.</li>
+ *
+ * </ul>
+ *
+ * <p><big><b>Subclass API</b></big></p>
+ *
+ * <p>The original <code>Calendar</code> API was based on the experience
+ * of implementing a only a single subclass,
+ * <code>GregorianCalendar</code>. As a result, all of the subclassing
+ * kinks had not been worked out. The new subclassing API has been
+ * refined based on several implemented subclasses. This includes methods
+ * that must be overridden and methods for subclasses to call. Subclasses
+ * no longer have direct access to <code>fields</code> and
+ * <code>stamp</code>. Instead, they have new API to access
+ * these. Subclasses are able to allocate the <code>fields</code> array
+ * through a protected framework method; this allows subclasses to
+ * specify additional fields. </p>
+ *
+ * <p>More functionality has been moved into the base class. The base
+ * class now contains much of the computational machinery to support the
+ * Gregorian calendar. This is based on two things: (1) Many calendars
+ * are based on the Gregorian calendar (such as the Buddhist and Japanese
+ * imperial calendars). (2) <em>All</em> calendars require basic
+ * Gregorian support in order to handle timezone computations. </p>
+ *
+ * <p>Common computations have been moved into
+ * <code>Calendar</code>. Subclasses no longer compute the week related
+ * fields and the time related fields. These are commonly handled for all
+ * calendars by the base class. </p>
+ *
+ * <p><b>Subclass computation of time <tt>=&gt;</tt> fields</b>
+ *
+ * <p>The {@link #ERA}, {@link #YEAR},
+ * {@link #EXTENDED_YEAR}, {@link #MONTH},
+ * {@link #DAY_OF_MONTH}, and {@link #DAY_OF_YEAR} fields are
+ * computed by the subclass, based on the Julian day. All other fields
+ * are computed by <code>Calendar</code>.
+ *
+ * <ul>
+ *
+ *   <li>Subclasses should implement {@link #handleComputeFields}
+ *     to compute the {@link #ERA}, {@link #YEAR},
+ *     {@link #EXTENDED_YEAR}, {@link #MONTH},
+ *     {@link #DAY_OF_MONTH}, and {@link #DAY_OF_YEAR} fields,
+ *     based on the value of the {@link #JULIAN_DAY} field. If there
+ *     are calendar-specific fields not defined by <code>Calendar</code>,
+ *     they must also be computed. These are the only fields that the
+ *     subclass should compute. All other fields are computed by the base
+ *     class, so time and week fields behave in a consistent way across
+ *     all calendars. The default version of this method in
+ *     <code>Calendar</code> implements a proleptic Gregorian
+ *     calendar. Within this method, subclasses may call
+ *     <code>getGregorianXxx()</code> to obtain the Gregorian calendar
+ *     month, day of month, and extended year for the given date.</li>
+ *
+ * </ul>
+ *
+ * <p><b>Subclass computation of fields <tt>=&gt;</tt> time</b>
+ *
+ * <p>The interpretation of most field values is handled entirely by
+ * <code>Calendar</code>. <code>Calendar</code> determines which fields
+ * are set, which are not, which are set more recently, and so on. In
+ * addition, <code>Calendar</code> handles the computation of the time
+ * from the time fields and handles the week-related fields. The only
+ * thing the subclass must do is determine the extended year, based on
+ * the year fields, and then, given an extended year and a month, it must
+ * return a Julian day number.
+ *
+ * <ul>
+ *
+ *   <li>Subclasses should implement {@link #handleGetExtendedYear}
+ *     to return the extended year for this calendar system, based on the
+ *     {@link #YEAR}, {@link #EXTENDED_YEAR}, and any fields that
+ *     the calendar system uses that are larger than a year, such as
+ *     {@link #ERA}.</li>
+ *
+ *   <li>Subclasses should implement {@link #handleComputeMonthStart}
+ *     to return the Julian day number
+ *     associated with a month and extended year. This is the Julian day
+ *     number of the day before the first day of the month. The month
+ *     number is zero-based. This computation should not depend on any
+ *     field values.</li>
+ *
+ * </ul>
+ *
+ * <p><b>Other methods</b>
+ *
+ * <ul>
+ *
+ *   <li>Subclasses should implement {@link #handleGetMonthLength}
+ *     to return the number of days in a
+ *     given month of a given extended year. The month number, as always,
+ *     is zero-based.</li>
+ *
+ *   <li>Subclasses should implement {@link #handleGetYearLength}
+ *     to return the number of days in the given
+ *     extended year. This method is used by
+ *     <tt>computeWeekFields</tt> to compute the
+ *     {@link #WEEK_OF_YEAR} and {@link #YEAR_WOY} fields.</li>
+ *
+ *   <li>Subclasses should implement {@link #handleGetLimit}
+ *     to return the protected values of a field, depending on the value of
+ *     <code>limitType</code>. This method only needs to handle the
+ *     fields {@link #ERA}, {@link #YEAR}, {@link #MONTH},
+ *     {@link #WEEK_OF_YEAR}, {@link #WEEK_OF_MONTH},
+ *     {@link #DAY_OF_MONTH}, {@link #DAY_OF_YEAR},
+ *     {@link #DAY_OF_WEEK_IN_MONTH}, {@link #YEAR_WOY}, and
+ *     {@link #EXTENDED_YEAR}.  Other fields are invariant (with
+ *     respect to calendar system) and are handled by the base
+ *     class.</li>
+ *
+ *   <li>Optionally, subclasses may override {@link #validateField}
+ *     to check any subclass-specific fields. If the
+ *     field's value is out of range, the method should throw an
+ *     <code>IllegalArgumentException</code>. The method may call
+ *     <code>super.validateField(field)</code> to handle fields in a
+ *     generic way, that is, to compare them to the range
+ *     <code>getMinimum(field)</code>..<code>getMaximum(field)</code>.</li>
+ *
+ *   <li>Optionally, subclasses may override
+ *     {@link #handleCreateFields} to create an <code>int[]</code>
+ *     array large enough to hold the calendar's fields. This is only
+ *     necessary if the calendar defines additional fields beyond those
+ *     defined by <code>Calendar</code>. The length of the result must be
+ *     be between the base and maximum field counts.</li>
+ *
+ *   <li>Optionally, subclasses may override
+ *     {@link #handleGetDateFormat} to create a
+ *     <code>DateFormat</code> appropriate to this calendar. This is only
+ *     required if a calendar subclass redefines the use of a field (for
+ *     example, changes the {@link #ERA} field from a symbolic field
+ *     to a numeric one) or defines an additional field.</li>
+ *
+ *   <li>Optionally, subclasses may override {@link #roll roll} and
+ *     {@link #add add} to handle fields that are discontinuous. For
+ *     example, in the Hebrew calendar the month &quot;Adar I&quot; only
+ *     occurs in leap years; in other years the calendar jumps from
+ *     Shevat (month #4) to Adar (month #6). The {@link
+ *     HebrewCalendar#add HebrewCalendar.add} and {@link
+ *     HebrewCalendar#roll HebrewCalendar.roll} methods take this into
+ *     account, so that adding 1 month to Shevat gives the proper result
+ *     (Adar) in a non-leap year. The protected utility method {@link
+ *     #pinField pinField} is often useful when implementing these two
+ *     methods. </li>
+ *
+ * </ul>
+ *
+ * <p><big><b>Normalized behavior</b></big>
+ *
+ * <p>The behavior of certain fields has been made consistent across all
+ * calendar systems and implemented in <code>Calendar</code>.
+ *
+ * <ul>
+ *
+ *   <li>Time is normalized. Even though some calendar systems transition
+ *     between days at sunset or at other times, all ICU4J calendars
+ *     transition between days at <em>local zone midnight</em>.  This
+ *     allows ICU4J to centralize the time computations in
+ *     <code>Calendar</code> and to maintain basic correpsondences
+ *     between calendar systems. Affected fields: {@link #AM_PM},
+ *     {@link #HOUR}, {@link #HOUR_OF_DAY}, {@link #MINUTE},
+ *     {@link #SECOND}, {@link #MILLISECOND},
+ *     {@link #ZONE_OFFSET}, and {@link #DST_OFFSET}.</li>
+ *
+ *   <li>DST behavior is normalized. Daylight savings time behavior is
+ *     computed the same for all calendar systems, and depends on the
+ *     value of several <code>GregorianCalendar</code> fields: the
+ *     {@link #YEAR}, {@link #MONTH}, and
+ *     {@link #DAY_OF_MONTH}. As a result, <code>Calendar</code>
+ *     always computes these fields, even for non-Gregorian calendar
+ *     systems. These fields are available to subclasses.</li>
+ *
+ *   <li>Weeks are normalized. Although locales define the week
+ *     differently, in terms of the day on which it starts, and the
+ *     designation of week number one of a month or year, they all use a
+ *     common mechanism. Furthermore, the day of the week has a simple
+ *     and consistent definition throughout history. For example,
+ *     although the Gregorian calendar introduced a discontinuity when
+ *     first instituted, the day of week was not disrupted. For this
+ *     reason, the fields {@link #DAY_OF_WEEK}, <code>WEEK_OF_YEAR,
+ *     WEEK_OF_MONTH</code>, {@link #DAY_OF_WEEK_IN_MONTH},
+ *     {@link #DOW_LOCAL}, {@link #YEAR_WOY} are all computed in
+ *     a consistent way in the base class, based on the
+ *     {@link #EXTENDED_YEAR}, {@link #DAY_OF_YEAR},
+ *     {@link #MONTH}, and {@link #DAY_OF_MONTH}, which are
+ *     computed by the subclass.</li>
+ *
+ * </ul>
+ *
+ * <p><big><b>Supported range</b></big>
+ *
+ * <p>The allowable range of <code>Calendar</code> has been
+ * narrowed. <code>GregorianCalendar</code> used to attempt to support
+ * the range of dates with millisecond values from
+ * <code>Long.MIN_VALUE</code> to <code>Long.MAX_VALUE</code>. This
+ * introduced awkward constructions (hacks) which slowed down
+ * performance. It also introduced non-uniform behavior at the
+ * boundaries. The new <code>Calendar</code> protocol specifies the
+ * maximum range of supportable dates as those having Julian day numbers
+ * of <code>-0x7F000000</code> to <code>+0x7F000000</code>. This
+ * corresponds to years from ~5,000,000 BCE to ~5,000,000 CE. Programmers
+ * should use the protected constants in <code>Calendar</code> to
+ * specify an extremely early or extremely late date.</p>
+ *
+ * <p><big><b>General notes</b></big>
+ *
+ * <ul>
+ *
+ *   <li>Calendars implementations are <em>proleptic</em>. For example,
+ *     even though the Gregorian calendar was not instituted until the
+ *     16th century, the <code>GregorianCalendar</code> class supports
+ *     dates before the historical onset of the calendar by extending the
+ *     calendar system backward in time. Similarly, the
+ *     <code>HebrewCalendar</code> extends backward before the start of
+ *     its epoch into zero and negative years. Subclasses do not throw
+ *     exceptions because a date precedes the historical start of a
+ *     calendar system. Instead, they implement
+ *     {@link #handleGetLimit} to return appropriate limits on
+ *     {@link #YEAR}, {@link #ERA}, etc. fields. Then, if the
+ *     calendar is set to not be lenient, out-of-range field values will
+ *     trigger an exception.</li>
+ *
+ *   <li>Calendar system subclasses compute a <em>extended
+ *     year</em>. This differs from the {@link #YEAR} field in that
+ *     it ranges over all integer values, including zero and negative
+ *     values, and it encapsulates the information of the
+ *     {@link #YEAR} field and all larger fields.  Thus, for the
+ *     Gregorian calendar, the {@link #EXTENDED_YEAR} is computed as
+ *     <code>ERA==AD ? YEAR : 1-YEAR</code>. Another example is the Mayan
+ *     long count, which has years (<code>KUN</code>) and nested cycles
+ *     of years (<code>KATUN</code> and <code>BAKTUN</code>). The Mayan
+ *     {@link #EXTENDED_YEAR} is computed as <code>TUN + 20 * (KATUN
+ *     + 20 * BAKTUN)</code>. The <code>Calendar</code> base class uses
+ *     the {@link #EXTENDED_YEAR} field to compute the week-related
+ *     fields.</li>
+ *
+ * </ul>
+ *
+ * @see          Date
+ * @see          GregorianCalendar
+ * @see          TimeZone
+ * @see          DateFormat
+ * @author Mark Davis, David Goldsmith, Chen-Lieh Huang, Alan Liu, Laura Werner
+ * @stable ICU 2.0
+ */
+public class Calendar implements Serializable, Cloneable, Comparable<Calendar> {
+    private static final long serialVersionUID = 1L;
+    
+    /**
+     * @internal
+     */
+    public final java.util.Calendar calendar;
+        
+    /**
+     * @internal
+     * @param delegate the Calendar to which to delegate
+     */
+    public Calendar(java.util.Calendar delegate) {
+        this.calendar = delegate;
+    }
+
+    // Data flow in Calendar
+    // ---------------------
+
+    // The current time is represented in two ways by Calendar: as UTC
+    // milliseconds from the epoch start (1 January 1970 0:00 UTC), and as local
+    // fields such as MONTH, HOUR, AM_PM, etc.  It is possible to compute the
+    // millis from the fields, and vice versa.  The data needed to do this
+    // conversion is encapsulated by a TimeZone object owned by the Calendar.
+    // The data provided by the TimeZone object may also be overridden if the
+    // user sets the ZONE_OFFSET and/or DST_OFFSET fields directly. The class
+    // keeps track of what information was most recently set by the caller, and
+    // uses that to compute any other information as needed.
+
+    // If the user sets the fields using set(), the data flow is as follows.
+    // This is implemented by the Calendar subclass's computeTime() method.
+    // During this process, certain fields may be ignored.  The disambiguation
+    // algorithm for resolving which fields to pay attention to is described
+    // above.
+
+    //   local fields (YEAR, MONTH, DATE, HOUR, MINUTE, etc.)
+    //           |
+    //           | Using Calendar-specific algorithm
+    //           V
+    //   local standard millis
+    //           |
+    //           | Using TimeZone or user-set ZONE_OFFSET / DST_OFFSET
+    //           V
+    //   UTC millis (in time data member)
+
+    // If the user sets the UTC millis using setTime(), the data flow is as
+    // follows.  This is implemented by the Calendar subclass's computeFields()
+    // method.
+
+    //   UTC millis (in time data member)
+    //           |
+    //           | Using TimeZone getOffset()
+    //           V
+    //   local standard millis
+    //           |
+    //           | Using Calendar-specific algorithm
+    //           V
+    //   local fields (YEAR, MONTH, DATE, HOUR, MINUTE, etc.)
+
+    // In general, a round trip from fields, through local and UTC millis, and
+    // back out to fields is made when necessary.  This is implemented by the
+    // complete() method.  Resolving a partial set of fields into a UTC millis
+    // value allows all remaining fields to be generated from that value.  If
+    // the Calendar is lenient, the fields are also renormalized to standard
+    // ranges when they are regenerated.
+
+    /**
+     * Field number for <code>get</code> and <code>set</code> indicating the
+     * era, e.g., AD or BC in the Julian calendar. This is a calendar-specific
+     * value; see subclass documentation.
+     * @see GregorianCalendar#AD
+     * @see GregorianCalendar#BC
+     * @stable ICU 2.0
+     */
+    public final static int ERA = 0;
+
+    /**
+     * Field number for <code>get</code> and <code>set</code> indicating the
+     * year. This is a calendar-specific value; see subclass documentation.
+     * @stable ICU 2.0
+     */
+    public final static int YEAR = 1;
+
+    /**
+     * Field number for <code>get</code> and <code>set</code> indicating the
+     * month. This is a calendar-specific value. The first month of the year is
+     * <code>JANUARY</code>; the last depends on the number of months in a year.
+     * @see #JANUARY
+     * @see #FEBRUARY
+     * @see #MARCH
+     * @see #APRIL
+     * @see #MAY
+     * @see #JUNE
+     * @see #JULY
+     * @see #AUGUST
+     * @see #SEPTEMBER
+     * @see #OCTOBER
+     * @see #NOVEMBER
+     * @see #DECEMBER
+     * @see #UNDECIMBER
+     * @stable ICU 2.0
+     */
+    public final static int MONTH = 2;
+
+    /**
+     * Field number for <code>get</code> and <code>set</code> indicating the
+     * week number within the current year.  The first week of the year, as
+     * defined by {@link #getFirstDayOfWeek()} and
+     * {@link #getMinimalDaysInFirstWeek()}, has value 1.  Subclasses define
+     * the value of {@link #WEEK_OF_YEAR} for days before the first week of
+     * the year.
+     * @see #getFirstDayOfWeek
+     * @see #getMinimalDaysInFirstWeek
+     * @stable ICU 2.0
+     */
+    public final static int WEEK_OF_YEAR = 3;
+
+    /**
+     * Field number for <code>get</code> and <code>set</code> indicating the
+     * week number within the current month.  The first week of the month, as
+     * defined by {@link #getFirstDayOfWeek()} and
+     * {@link #getMinimalDaysInFirstWeek()}, has value 1.  Subclasses define
+     * the value of {@link #WEEK_OF_MONTH} for days before the first week of
+     * the month.
+     * @see #getFirstDayOfWeek
+     * @see #getMinimalDaysInFirstWeek
+     * @stable ICU 2.0
+     */
+    public final static int WEEK_OF_MONTH = 4;
+
+    /**
+     * Field number for <code>get</code> and <code>set</code> indicating the
+     * day of the month. This is a synonym for {@link #DAY_OF_MONTH}.
+     * The first day of the month has value 1.
+     * @see #DAY_OF_MONTH
+     * @stable ICU 2.0
+     */
+    public final static int DATE = 5;
+
+    /**
+     * Field number for <code>get</code> and <code>set</code> indicating the
+     * day of the month. This is a synonym for {@link #DATE}.
+     * The first day of the month has value 1.
+     * @see #DATE
+     * @stable ICU 2.0
+     */
+    public final static int DAY_OF_MONTH = 5;
+
+    /**
+     * Field number for <code>get</code> and <code>set</code> indicating the day
+     * number within the current year.  The first day of the year has value 1.
+     * @stable ICU 2.0
+     */
+    public final static int DAY_OF_YEAR = 6;
+
+    /**
+     * Field number for <code>get</code> and <code>set</code> indicating the day
+     * of the week.  This field takes values {@link #SUNDAY},
+     * {@link #MONDAY}, {@link #TUESDAY}, {@link #WEDNESDAY},
+     * {@link #THURSDAY}, {@link #FRIDAY}, and {@link #SATURDAY}.
+     * @see #SUNDAY
+     * @see #MONDAY
+     * @see #TUESDAY
+     * @see #WEDNESDAY
+     * @see #THURSDAY
+     * @see #FRIDAY
+     * @see #SATURDAY
+     * @stable ICU 2.0
+     */
+    public final static int DAY_OF_WEEK = 7;
+
+    /**
+     * Field number for <code>get</code> and <code>set</code> indicating the
+     * ordinal number of the day of the week within the current month. Together
+     * with the {@link #DAY_OF_WEEK} field, this uniquely specifies a day
+     * within a month.  Unlike {@link #WEEK_OF_MONTH} and
+     * {@link #WEEK_OF_YEAR}, this field's value does <em>not</em> depend on
+     * {@link #getFirstDayOfWeek()} or
+     * {@link #getMinimalDaysInFirstWeek()}.  <code>DAY_OF_MONTH 1</code>
+     * through <code>7</code> always correspond to <code>DAY_OF_WEEK_IN_MONTH
+     * 1</code>; <code>8</code> through <code>15</code> correspond to
+     * <code>DAY_OF_WEEK_IN_MONTH 2</code>, and so on.
+     * <code>DAY_OF_WEEK_IN_MONTH 0</code> indicates the week before
+     * <code>DAY_OF_WEEK_IN_MONTH 1</code>.  Negative values count back from the
+     * end of the month, so the last Sunday of a month is specified as
+     * <code>DAY_OF_WEEK = SUNDAY, DAY_OF_WEEK_IN_MONTH = -1</code>.  Because
+     * negative values count backward they will usually be aligned differently
+     * within the month than positive values.  For example, if a month has 31
+     * days, <code>DAY_OF_WEEK_IN_MONTH -1</code> will overlap
+     * <code>DAY_OF_WEEK_IN_MONTH 5</code> and the end of <code>4</code>.
+     * @see #DAY_OF_WEEK
+     * @see #WEEK_OF_MONTH
+     * @stable ICU 2.0
+     */
+    public final static int DAY_OF_WEEK_IN_MONTH = 8;
+
+    /**
+     * Field number for <code>get</code> and <code>set</code> indicating
+     * whether the <code>HOUR</code> is before or after noon.
+     * E.g., at 10:04:15.250 PM the <code>AM_PM</code> is <code>PM</code>.
+     * @see #AM
+     * @see #PM
+     * @see #HOUR
+     * @stable ICU 2.0
+     */
+    public final static int AM_PM = 9;
+
+    /**
+     * Field number for <code>get</code> and <code>set</code> indicating the
+     * hour of the morning or afternoon. <code>HOUR</code> is used for the 12-hour
+     * clock.
+     * E.g., at 10:04:15.250 PM the <code>HOUR</code> is 10.
+     * @see #AM_PM
+     * @see #HOUR_OF_DAY
+     * @stable ICU 2.0
+     */
+    public final static int HOUR = 10;
+
+    /**
+     * Field number for <code>get</code> and <code>set</code> indicating the
+     * hour of the day. <code>HOUR_OF_DAY</code> is used for the 24-hour clock.
+     * E.g., at 10:04:15.250 PM the <code>HOUR_OF_DAY</code> is 22.
+     * @see #HOUR
+     * @stable ICU 2.0
+     */
+    public final static int HOUR_OF_DAY = 11;
+
+    /**
+     * Field number for <code>get</code> and <code>set</code> indicating the
+     * minute within the hour.
+     * E.g., at 10:04:15.250 PM the <code>MINUTE</code> is 4.
+     * @stable ICU 2.0
+     */
+    public final static int MINUTE = 12;
+
+    /**
+     * Field number for <code>get</code> and <code>set</code> indicating the
+     * second within the minute.
+     * E.g., at 10:04:15.250 PM the <code>SECOND</code> is 15.
+     * @stable ICU 2.0
+     */
+    public final static int SECOND = 13;
+
+    /**
+     * Field number for <code>get</code> and <code>set</code> indicating the
+     * millisecond within the second.
+     * E.g., at 10:04:15.250 PM the <code>MILLISECOND</code> is 250.
+     * @stable ICU 2.0
+     */
+    public final static int MILLISECOND = 14;
+
+    /**
+     * Field number for <code>get</code> and <code>set</code> indicating the
+     * raw offset from GMT in milliseconds.
+     * @stable ICU 2.0
+     */
+    public final static int ZONE_OFFSET = 15;
+
+    /**
+     * Field number for <code>get</code> and <code>set</code> indicating the
+     * daylight savings offset in milliseconds.
+     * @stable ICU 2.0
+     */
+    public final static int DST_OFFSET = 16;
+
+    /**
+     * {@icu} Field number for <code>get()</code> and <code>set()</code>
+     * indicating the extended year corresponding to the
+     * {@link #WEEK_OF_YEAR} field.  This may be one greater or less
+     * than the value of {@link #EXTENDED_YEAR}.
+     * @stable ICU 2.0
+     */
+    public static final int YEAR_WOY = 17;
+
+    /**
+     * {@icu} Field number for <code>get()</code> and <code>set()</code>
+     * indicating the localized day of week.  This will be a value from 1
+     * to 7 inclusive, with 1 being the localized first day of the week.
+     * @stable ICU 2.0
+     */
+    public static final int DOW_LOCAL = 18;
+
+    /**
+     * {@icu} Field number for <code>get()</code> and <code>set()</code>
+     * indicating the extended year.  This is a single number designating
+     * the year of this calendar system, encompassing all supra-year
+     * fields.  For example, for the Julian calendar system, year numbers
+     * are positive, with an era of BCE or CE.  An extended year value for
+     * the Julian calendar system assigns positive values to CE years and
+     * negative values to BCE years, with 1 BCE being year 0.
+     * @stable ICU 2.0
+     */
+    public static final int EXTENDED_YEAR = 19;
+
+    /**
+     * {@icu} Field number for <code>get()</code> and <code>set()</code>
+     * indicating the modified Julian day number.  This is different from
+     * the conventional Julian day number in two regards.  First, it
+     * demarcates days at local zone midnight, rather than noon GMT.
+     * Second, it is a local number; that is, it depends on the local time
+     * zone.  It can be thought of as a single number that encompasses all
+     * the date-related fields.
+     * @stable ICU 2.0
+     */
+    public static final int JULIAN_DAY = 20;
+
+    /**
+     * {@icu} Field number for <code>get()</code> and <code>set()</code>
+     * indicating the milliseconds in the day.  This ranges from 0 to
+     * 23:59:59.999 (regardless of DST).  This field behaves
+     * <em>exactly</em> like a composite of all time-related fields, not
+     * including the zone fields.  As such, it also reflects
+     * discontinuities of those fields on DST transition days.  On a day of
+     * DST onset, it will jump forward.  On a day of DST cessation, it will
+     * jump backward.  This reflects the fact that is must be combined with
+     * the DST_OFFSET field to obtain a unique local time value.
+     * @stable ICU 2.0
+     */
+    public static final int MILLISECONDS_IN_DAY = 21;
+
+    /**
+     * {@icu} Field indicating whether or not the current month is a leap month.
+     * Should have a value of 0 for non-leap months, and 1 for leap months.
+     * @draft ICU 4.4
+     * @provisional This API might change or be removed in a future release.
+     */
+    public static final int IS_LEAP_MONTH = 22;
+
+    /**
+     * Value of the <code>DAY_OF_WEEK</code> field indicating
+     * Sunday.
+     * @stable ICU 2.0
+     */
+    public final static int SUNDAY = 1;
+
+    /**
+     * Value of the <code>DAY_OF_WEEK</code> field indicating
+     * Monday.
+     * @stable ICU 2.0
+     */
+    public final static int MONDAY = 2;
+
+    /**
+     * Value of the <code>DAY_OF_WEEK</code> field indicating
+     * Tuesday.
+     * @stable ICU 2.0
+     */
+    public final static int TUESDAY = 3;
+
+    /**
+     * Value of the <code>DAY_OF_WEEK</code> field indicating
+     * Wednesday.
+     * @stable ICU 2.0
+     */
+    public final static int WEDNESDAY = 4;
+
+    /**
+     * Value of the <code>DAY_OF_WEEK</code> field indicating
+     * Thursday.
+     * @stable ICU 2.0
+     */
+    public final static int THURSDAY = 5;
+
+    /**
+     * Value of the <code>DAY_OF_WEEK</code> field indicating
+     * Friday.
+     * @stable ICU 2.0
+     */
+    public final static int FRIDAY = 6;
+
+    /**
+     * Value of the <code>DAY_OF_WEEK</code> field indicating
+     * Saturday.
+     * @stable ICU 2.0
+     */
+    public final static int SATURDAY = 7;
+
+    /**
+     * Value of the <code>MONTH</code> field indicating the
+     * first month of the year.
+     * @stable ICU 2.0
+     */
+    public final static int JANUARY = 0;
+
+    /**
+     * Value of the <code>MONTH</code> field indicating the
+     * second month of the year.
+     * @stable ICU 2.0
+     */
+    public final static int FEBRUARY = 1;
+
+    /**
+     * Value of the <code>MONTH</code> field indicating the
+     * third month of the year.
+     * @stable ICU 2.0
+     */
+    public final static int MARCH = 2;
+
+    /**
+     * Value of the <code>MONTH</code> field indicating the
+     * fourth month of the year.
+     * @stable ICU 2.0
+     */
+    public final static int APRIL = 3;
+
+    /**
+     * Value of the <code>MONTH</code> field indicating the
+     * fifth month of the year.
+     * @stable ICU 2.0
+     */
+    public final static int MAY = 4;
+
+    /**
+     * Value of the <code>MONTH</code> field indicating the
+     * sixth month of the year.
+     * @stable ICU 2.0
+     */
+    public final static int JUNE = 5;
+
+    /**
+     * Value of the <code>MONTH</code> field indicating the
+     * seventh month of the year.
+     * @stable ICU 2.0
+     */
+    public final static int JULY = 6;
+
+    /**
+     * Value of the <code>MONTH</code> field indicating the
+     * eighth month of the year.
+     * @stable ICU 2.0
+     */
+    public final static int AUGUST = 7;
+
+    /**
+     * Value of the <code>MONTH</code> field indicating the
+     * ninth month of the year.
+     * @stable ICU 2.0
+     */
+    public final static int SEPTEMBER = 8;
+
+    /**
+     * Value of the <code>MONTH</code> field indicating the
+     * tenth month of the year.
+     * @stable ICU 2.0
+     */
+    public final static int OCTOBER = 9;
+
+    /**
+     * Value of the <code>MONTH</code> field indicating the
+     * eleventh month of the year.
+     * @stable ICU 2.0
+     */
+    public final static int NOVEMBER = 10;
+
+    /**
+     * Value of the <code>MONTH</code> field indicating the
+     * twelfth month of the year.
+     * @stable ICU 2.0
+     */
+    public final static int DECEMBER = 11;
+
+    /**
+     * Value of the <code>MONTH</code> field indicating the
+     * thirteenth month of the year. Although {@link GregorianCalendar}
+     * does not use this value, lunar calendars do.
+     * @stable ICU 2.0
+     */
+    public final static int UNDECIMBER = 12;
+
+    /**
+     * Value of the <code>AM_PM</code> field indicating the
+     * period of the day from midnight to just before noon.
+     * @stable ICU 2.0
+     */
+    public final static int AM = 0;
+
+    /**
+     * Value of the <code>AM_PM</code> field indicating the
+     * period of the day from noon to just before midnight.
+     * @stable ICU 2.0
+     */
+    public final static int PM = 1;
+
+    /**
+     * {@icu} Value returned by getDayOfWeekType(int dayOfWeek) to indicate a
+     * weekday.
+     * @see #WEEKEND
+     * @see #WEEKEND_ONSET
+     * @see #WEEKEND_CEASE
+     * @see #getDayOfWeekType
+     * @stable ICU 2.0
+     */
+    public static final int WEEKDAY = 0;
+
+    /**
+     * {@icu} Value returned by getDayOfWeekType(int dayOfWeek) to indicate a
+     * weekend day.
+     * @see #WEEKDAY
+     * @see #WEEKEND_ONSET
+     * @see #WEEKEND_CEASE
+     * @see #getDayOfWeekType
+     * @stable ICU 2.0
+     */
+    public static final int WEEKEND = 1;
+
+    /**
+     * {@icu} Value returned by getDayOfWeekType(int dayOfWeek) to indicate a
+     * day that starts as a weekday and transitions to the weekend.
+     * Call getWeekendTransition() to get the point of transition.
+     * @see #WEEKDAY
+     * @see #WEEKEND
+     * @see #WEEKEND_CEASE
+     * @see #getDayOfWeekType
+     * @stable ICU 2.0
+     */
+    public static final int WEEKEND_ONSET = 2;
+
+    /**
+     * {@icu} Value returned by getDayOfWeekType(int dayOfWeek) to indicate a
+     * day that starts as the weekend and transitions to a weekday.
+     * Call getWeekendTransition() to get the point of transition.
+     * @see #WEEKDAY
+     * @see #WEEKEND
+     * @see #WEEKEND_ONSET
+     * @see #getDayOfWeekType
+     * @stable ICU 2.0
+     */
+    public static final int WEEKEND_CEASE = 3;
+
+    /**
+     * Constructs a Calendar with the default time zone
+     * and locale.
+     * @see     TimeZone#getDefault
+     * @stable ICU 2.0
+     */
+    protected Calendar()
+    {
+        this(TimeZone.getDefault(), ULocale.getDefault(Category.FORMAT));
+    }
+
+    /**
+     * Constructs a calendar with the specified time zone and locale.
+     * @param zone the time zone to use
+     * @param aLocale the locale for the week data
+     * @stable ICU 2.0
+     */
+    protected Calendar(TimeZone zone, Locale aLocale)
+    {
+        this(zone, ULocale.forLocale(aLocale));
+    }
+
+    /**
+     * Constructs a calendar with the specified time zone and locale.
+     * @param zone the time zone to use
+     * @param locale the ulocale for the week data
+     * @stable ICU 3.2
+     */
+    protected Calendar(TimeZone zone, ULocale locale)
+    {
+        calendar = java.util.Calendar.getInstance(zone.timeZone, locale.toLocale());
+    }
+
+    /**
+     * Returns a calendar using the default time zone and locale.
+     * @return a Calendar.
+     * @stable ICU 2.0
+     */
+    public static synchronized Calendar getInstance()
+    {
+        return new Calendar(java.util.Calendar.getInstance());
+    }
+
+    /**
+     * Returns a calendar using the specified time zone and default locale.
+     * @param zone the time zone to use
+     * @return a Calendar.
+     * @stable ICU 2.0
+     */
+    public static synchronized Calendar getInstance(TimeZone zone)
+    {
+        return new Calendar(java.util.Calendar.getInstance(zone.timeZone));
+    }
+
+    /**
+     * Returns a calendar using the default time zone and specified locale.
+     * @param aLocale the locale for the week data
+     * @return a Calendar.
+     * @stable ICU 2.0
+     */
+    public static synchronized Calendar getInstance(Locale aLocale)
+    {
+        return new Calendar(java.util.Calendar.getInstance(aLocale));
+    }
+
+    /**
+     * Returns a calendar using the default time zone and specified locale.
+     * @param locale the ulocale for the week data
+     * @return a Calendar.
+     * @stable ICU 3.2
+     */
+    public static synchronized Calendar getInstance(ULocale locale)
+    {
+        return new Calendar(java.util.Calendar.getInstance(locale.toLocale()));
+    }
+
+    /**
+     * Returns a calendar with the specified time zone and locale.
+     * @param zone the time zone to use
+     * @param aLocale the locale for the week data
+     * @return a Calendar.
+     * @stable ICU 2.0
+     */
+    public static synchronized Calendar getInstance(TimeZone zone,
+                                                    Locale aLocale) {
+        return new Calendar(java.util.Calendar.getInstance(zone.timeZone, aLocale));
+    }
+
+    /**
+     * Returns a calendar with the specified time zone and locale.
+     * @param zone the time zone to use
+     * @param locale the ulocale for the week data
+     * @return a Calendar.
+     * @stable ICU 3.2
+     */
+    public static synchronized Calendar getInstance(TimeZone zone,
+                                                    ULocale locale) {
+        return new Calendar(java.util.Calendar.getInstance(zone.timeZone, locale.toLocale()));
+    }
+
+    /**
+     * Returns the list of locales for which Calendars are installed.
+     * @return the list of locales for which Calendars are installed.
+     * @stable ICU 2.0
+     */
+    public static Locale[] getAvailableLocales()
+    {
+        return java.util.Calendar.getAvailableLocales();
+    }
+
+    /**
+     * {@icu} Returns the list of locales for which Calendars are installed.
+     * @return the list of locales for which Calendars are installed.
+     * @draft ICU 3.2 (retain)
+     * @provisional This API might change or be removed in a future release.
+     */
+    public static ULocale[] getAvailableULocales()
+    {
+        if (availableLocales == null) {
+            synchronized (Calendar.class) {
+                if (availableLocales == null) {
+                    Locale[] locales = Locale.getAvailableLocales();
+                    availableLocales = new ULocale[locales.length];
+                    for (int i = 0; i < locales.length; i++) {
+                        availableLocales[i] = ULocale.forLocale(locales[i]);
+                    }
+                }
+            }
+        }
+        return availableLocales.clone();
+    }
+    private static volatile ULocale[] availableLocales;
+
+    /**
+     * {@icu} Given a key and a locale, returns an array of string values in a preferred
+     * order that would make a difference. These are all and only those values where
+     * the open (creation) of the service with the locale formed from the input locale
+     * plus input keyword and that value has different behavior than creation with the
+     * input locale alone.
+     * @param key           one of the keys supported by this service.  For now, only
+     *                      "calendar" is supported.
+     * @param locale        the locale
+     * @param commonlyUsed  if set to true it will return only commonly used values
+     *                      with the given locale in preferred order.  Otherwise,
+     *                      it will return all the available values for the locale.
+     * @return an array of string values for the given key and the locale.
+     * @stable ICU 4.2
+     */
+    public static final String[] getKeywordValuesForLocale(String key, ULocale locale,
+                                                           boolean commonlyUsed) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Returns this Calendar's current time.
+     * @return the current time.
+     * @stable ICU 2.0
+     */
+    public final Date getTime() {
+        return calendar.getTime();
+    }
+
+    /**
+     * Sets this Calendar's current time with the given Date.
+     * 
+     * <p>Note: Calling <code>setTime</code> with
+     * <code>Date(Long.MAX_VALUE)</code> or <code>Date(Long.MIN_VALUE)</code>
+     * may yield incorrect field values from {@link #get(int)}.
+     * @param date the given Date.
+     * @stable ICU 2.0
+     */
+    public final void setTime(Date date) {
+        calendar.setTime(date);
+    }
+
+    /**
+     * Returns this Calendar's current time as a long.
+     * @return the current time as UTC milliseconds from the epoch.
+     * @stable ICU 2.0
+     */
+    public long getTimeInMillis() {
+        return calendar.getTimeInMillis();
+    }
+
+    /**
+     * Sets this Calendar's current time from the given long value.
+     * @param millis the new time in UTC milliseconds from the epoch.
+     * @stable ICU 2.0
+     */
+    public void setTimeInMillis( long millis ) {
+        calendar.setTimeInMillis(millis);
+    }
+
+    /**
+     * Returns the value for a given time field.
+     * @param field the given time field.
+     * @return the value for the given time field.
+     * @stable ICU 2.0
+     */
+    public final int get(int field)
+    {
+        return calendar.get(getJDKField(field));
+    }
+
+    /**
+     * Sets the time field with the given value.
+     * @param field the given time field.
+     * @param value the value to be set for the given time field.
+     * @stable ICU 2.0
+     */
+    public final void set(int field, int value)
+    {
+        calendar.set(getJDKField(field), value);
+    }
+
+    /**
+     * Sets the values for the fields year, month, and date.
+     * Previous values of other fields are retained.  If this is not desired,
+     * call {@link #clear()} first.
+     * @param year the value used to set the YEAR time field.
+     * @param month the value used to set the MONTH time field.
+     * Month value is 0-based. e.g., 0 for January.
+     * @param date the value used to set the DATE time field.
+     * @stable ICU 2.0
+     */
+    public final void set(int year, int month, int date)
+    {
+        calendar.set(getJDKField(YEAR), year);
+        calendar.set(getJDKField(MONTH), month);
+        calendar.set(getJDKField(DATE), date);
+    }
+
+    /**
+     * Sets the values for the fields year, month, date, hour, and minute.
+     * Previous values of other fields are retained.  If this is not desired,
+     * call {@link #clear()} first.
+     * @param year the value used to set the YEAR time field.
+     * @param month the value used to set the MONTH time field.
+     * Month value is 0-based. e.g., 0 for January.
+     * @param date the value used to set the DATE time field.
+     * @param hour the value used to set the HOUR_OF_DAY time field.
+     * @param minute the value used to set the MINUTE time field.
+     * @stable ICU 2.0
+     */
+    public final void set(int year, int month, int date, int hour, int minute)
+    {
+        calendar.set(getJDKField(YEAR), year);
+        calendar.set(getJDKField(MONTH), month);
+        calendar.set(getJDKField(DATE), date);
+        calendar.set(getJDKField(HOUR_OF_DAY), hour);
+        calendar.set(getJDKField(MINUTE), minute);
+    }
+
+    /**
+     * Sets the values for the fields year, month, date, hour, minute, and second.
+     * Previous values of other fields are retained.  If this is not desired,
+     * call {@link #clear} first.
+     * @param year the value used to set the YEAR time field.
+     * @param month the value used to set the MONTH time field.
+     * Month value is 0-based. e.g., 0 for January.
+     * @param date the value used to set the DATE time field.
+     * @param hour the value used to set the HOUR_OF_DAY time field.
+     * @param minute the value used to set the MINUTE time field.
+     * @param second the value used to set the SECOND time field.
+     * @stable ICU 2.0
+     */
+    public final void set(int year, int month, int date, int hour, int minute,
+                          int second)
+    {
+        calendar.set(getJDKField(YEAR), year);
+        calendar.set(getJDKField(MONTH), month);
+        calendar.set(getJDKField(DATE), date);
+        calendar.set(getJDKField(HOUR_OF_DAY), hour);
+        calendar.set(getJDKField(MINUTE), minute);
+        calendar.set(getJDKField(SECOND), second);
+    }
+
+    /**
+     * Clears the values of all the time fields.
+     * @stable ICU 2.0
+     */
+    public final void clear()
+    {
+        calendar.clear();
+    }
+
+    /**
+     * Clears the value in the given time field.
+     * @param field the time field to be cleared.
+     * @stable ICU 2.0
+     */
+    public final void clear(int field)
+    {
+        calendar.clear(getJDKField(field));
+    }
+
+    /**
+     * Determines if the given time field has a value set.
+     * @return true if the given time field has a value set; false otherwise.
+     * @stable ICU 2.0
+     */
+    public final boolean isSet(int field)
+    {
+        return calendar.isSet(getJDKField(field));
+    }
+
+    /**
+     * Compares this calendar to the specified object.
+     * The result is <code>true</code> if and only if the argument is
+     * not <code>null</code> and is a <code>Calendar</code> object that
+     * represents the same calendar as this object.
+     * @param obj the object to compare with.
+     * @return <code>true</code> if the objects are the same;
+     * <code>false</code> otherwise.
+     * @stable ICU 2.0
+     */
+    public boolean equals(Object obj) {
+        try {
+            return calendar.equals(((Calendar)obj).calendar);
+        } catch (Exception e) {
+            return false;
+        }
+    }
+
+    /**
+     * {@icu} Returns true if the given Calendar object is equivalent to this
+     * one.  An equivalent Calendar will behave exactly as this one
+     * does, but it may be set to a different time.  By contrast, for
+     * the equals() method to return true, the other Calendar must
+     * be set to the same time.
+     *
+     * @param other the Calendar to be compared with this Calendar
+     * @stable ICU 2.4
+     */
+    public boolean isEquivalentTo(Calendar other) {
+        return calendar.getClass() == other.calendar.getClass() &&
+            calendar.isLenient() == other.calendar.isLenient() &&
+            calendar.getFirstDayOfWeek() == other.calendar.getFirstDayOfWeek() &&
+            calendar.getMinimalDaysInFirstWeek() == other.calendar.getMinimalDaysInFirstWeek() &&
+            calendar.getTimeZone().equals(other.calendar.getTimeZone());
+    }
+
+    /**
+     * Returns a hash code for this calendar.
+     * @return a hash code value for this object.
+     * @stable ICU 2.0
+     */
+    public int hashCode() {
+        return calendar.hashCode();
+    }
+
+    /**
+     * Returns the difference in milliseconds between the moment this
+     * calendar is set to and the moment the given calendar or Date object
+     * is set to.
+     */
+    private long compare(Object that) {
+        long thatMs;
+        if (that instanceof Calendar) {
+            thatMs = ((Calendar)that).getTimeInMillis();
+        } else if (that instanceof Date) {
+            thatMs = ((Date)that).getTime();
+        } else {
+            throw new IllegalArgumentException(that + "is not a Calendar or Date");
+        }
+        return getTimeInMillis() - thatMs;
+    }
+
+    /**
+     * Compares the time field records.
+     * Equivalent to comparing result of conversion to UTC.
+     * @param when the Calendar to be compared with this Calendar.
+     * @return true if the current time of this Calendar is before
+     * the time of Calendar when; false otherwise.
+     * @stable ICU 2.0
+     */
+    public boolean before(Object when) {
+        return compare(when) < 0;
+    }
+
+    /**
+     * Compares the time field records.
+     * Equivalent to comparing result of conversion to UTC.
+     * @param when the Calendar to be compared with this Calendar.
+     * @return true if the current time of this Calendar is after
+     * the time of Calendar when; false otherwise.
+     * @stable ICU 2.0
+     */
+    public boolean after(Object when) {
+        return compare(when) > 0;
+    }
+
+    /**
+     * Returns the maximum value that this field could have, given the
+     * current date.  For example, with the Gregorian date February 3, 1997
+     * and the {@link #DAY_OF_MONTH DAY_OF_MONTH} field, the actual maximum
+     * is 28; for February 3, 1996 it is 29.
+     *
+     * <p>The actual maximum computation ignores smaller fields and the
+     * current value of like-sized fields.  For example, the actual maximum
+     * of the DAY_OF_YEAR or MONTH depends only on the year and supra-year
+     * fields.  The actual maximum of the DAY_OF_MONTH depends, in
+     * addition, on the MONTH field and any other fields at that
+     * granularity (such as IS_LEAP_MONTH).  The
+     * DAY_OF_WEEK_IN_MONTH field does not depend on the current
+     * DAY_OF_WEEK; it returns the maximum for any day of week in the
+     * current month.  Likewise for the WEEK_OF_MONTH and WEEK_OF_YEAR
+     * fields.
+     *
+     * @param field the field whose maximum is desired
+     * @return the maximum of the given field for the current date of this calendar
+     * @see #getMaximum
+     * @see #getLeastMaximum
+     * @stable ICU 2.0
+     */
+    public int getActualMaximum(int field) {
+        return calendar.getActualMaximum(getJDKField(field));
+    }
+
+    /**
+     * Returns the minimum value that this field could have, given the current date.
+     * For most fields, this is the same as {@link #getMinimum getMinimum}
+     * and {@link #getGreatestMinimum getGreatestMinimum}.  However, some fields,
+     * especially those related to week number, are more complicated.
+     * <p>
+     * For example, assume {@link #getMinimalDaysInFirstWeek getMinimalDaysInFirstWeek}
+     * returns 4 and {@link #getFirstDayOfWeek getFirstDayOfWeek} returns SUNDAY.
+     * If the first day of the month is Sunday, Monday, Tuesday, or Wednesday
+     * there will be four or more days in the first week, so it will be week number 1,
+     * and <code>getActualMinimum(WEEK_OF_MONTH)</code> will return 1.  However,
+     * if the first of the month is a Thursday, Friday, or Saturday, there are
+     * <em>not</em> four days in that week, so it is week number 0, and
+     * <code>getActualMinimum(WEEK_OF_MONTH)</code> will return 0.
+     * <p>
+     * @param field the field whose actual minimum value is desired.
+     * @return the minimum of the given field for the current date of this calendar
+     *
+     * @see #getMinimum
+     * @see #getGreatestMinimum
+     * @stable ICU 2.0
+     */
+    public int getActualMinimum(int field) {
+        return calendar.getActualMinimum(getJDKField(field));
+    }
+
+    /**
+     * Rolls (up/down) a single unit of time on the given field.  If the
+     * field is rolled past its maximum allowable value, it will "wrap" back
+     * to its minimum and continue rolling. For
+     * example, to roll the current date up by one day, you can call:
+     * <p>
+     * <code>roll({@link #DATE}, true)</code>
+     * <p>
+     * When rolling on the {@link #YEAR} field, it will roll the year
+     * value in the range between 1 and the value returned by calling
+     * {@link #getMaximum getMaximum}({@link #YEAR}).
+     * <p>
+     * When rolling on certain fields, the values of other fields may conflict and
+     * need to be changed.  For example, when rolling the <code>MONTH</code> field
+     * for the Gregorian date 1/31/96 upward, the <code>DAY_OF_MONTH</code> field
+     * must be adjusted so that the result is 2/29/96 rather than the invalid
+     * 2/31/96.
+     * <p>
+     * <b>Note:</b> Calling <tt>roll(field, true)</tt> N times is <em>not</em>
+     * necessarily equivalent to calling <tt>roll(field, N)</tt>.  For example,
+     * imagine that you start with the date Gregorian date January 31, 1995.  If you call
+     * <tt>roll(Calendar.MONTH, 2)</tt>, the result will be March 31, 1995.
+     * But if you call <tt>roll(Calendar.MONTH, true)</tt>, the result will be
+     * February 28, 1995.  Calling it one more time will give March 28, 1995, which
+     * is usually not the desired result.
+     * <p>
+     * <b>Note:</b> You should always use <tt>roll</tt> and <tt>add</tt> rather
+     * than attempting to perform arithmetic operations directly on the fields
+     * of a <tt>Calendar</tt>.  It is quite possible for <tt>Calendar</tt> subclasses
+     * to have fields with non-linear behavior, for example missing months
+     * or days during non-leap years.  The subclasses' <tt>add</tt> and <tt>roll</tt>
+     * methods will take this into account, while simple arithmetic manipulations
+     * may give invalid results.
+     * <p>
+     * @param field the calendar field to roll.
+     *
+     * @param up    indicates if the value of the specified time field is to be
+     *              rolled up or rolled down. Use <code>true</code> if rolling up,
+     *              <code>false</code> otherwise.
+     *
+     * @exception   IllegalArgumentException if the field is invalid or refers
+     *              to a field that cannot be handled by this method.
+     * @see #roll(int, int)
+     * @see #add
+     * @stable ICU 2.0
+     */
+    public final void roll(int field, boolean up)
+    {
+        calendar.roll(getJDKField(field), up);
+    }
+
+    /**
+     * Rolls (up/down) a specified amount time on the given field.  For
+     * example, to roll the current date up by three days, you can call
+     * <code>roll(Calendar.DATE, 3)</code>.  If the
+     * field is rolled past its maximum allowable value, it will "wrap" back
+     * to its minimum and continue rolling.
+     * For example, calling <code>roll(Calendar.DATE, 10)</code>
+     * on a Gregorian calendar set to 4/25/96 will result in the date 4/5/96.
+     * <p>
+     * When rolling on certain fields, the values of other fields may conflict and
+     * need to be changed.  For example, when rolling the {@link #MONTH MONTH} field
+     * for the Gregorian date 1/31/96 by +1, the {@link #DAY_OF_MONTH DAY_OF_MONTH} field
+     * must be adjusted so that the result is 2/29/96 rather than the invalid
+     * 2/31/96.
+     * <p>
+     * {@icunote} the ICU implementation of this method is able to roll
+     * all fields except for {@link #ERA ERA}, {@link #DST_OFFSET DST_OFFSET},
+     * and {@link #ZONE_OFFSET ZONE_OFFSET}.  Subclasses may, of course, add support for
+     * additional fields in their overrides of <code>roll</code>.
+     * <p>
+     * <b>Note:</b> You should always use <tt>roll</tt> and <tt>add</tt> rather
+     * than attempting to perform arithmetic operations directly on the fields
+     * of a <tt>Calendar</tt>.  It is quite possible for <tt>Calendar</tt> subclasses
+     * to have fields with non-linear behavior, for example missing months
+     * or days during non-leap years.  The subclasses' <tt>add</tt> and <tt>roll</tt>
+     * methods will take this into account, while simple arithmetic manipulations
+     * may give invalid results.
+     * <p>
+     * <b>Subclassing:</b><br>
+     * This implementation of <code>roll</code> assumes that the behavior of the
+     * field is continuous between its minimum and maximum, which are found by
+     * calling {@link #getActualMinimum getActualMinimum} and {@link #getActualMaximum getActualMaximum}.
+     * For most such fields, simple addition, subtraction, and modulus operations
+     * are sufficient to perform the roll.  For week-related fields,
+     * the results of {@link #getFirstDayOfWeek getFirstDayOfWeek} and
+     * {@link #getMinimalDaysInFirstWeek getMinimalDaysInFirstWeek} are also necessary.
+     * Subclasses can override these two methods if their values differ from the defaults.
+     * <p>
+     * Subclasses that have fields for which the assumption of continuity breaks
+     * down must overide <code>roll</code> to handle those fields specially.
+     * For example, in the Hebrew calendar the month "Adar I"
+     * only occurs in leap years; in other years the calendar jumps from
+     * Shevat (month #4) to Adar (month #6).  The
+     * {@link HebrewCalendar#roll HebrewCalendar.roll} method takes this into account,
+     * so that rolling the month of Shevat by one gives the proper result (Adar) in a
+     * non-leap year.
+     * <p>
+     * @param field     the calendar field to roll.
+     * @param amount    the amount by which the field should be rolled.
+     *
+     * @exception   IllegalArgumentException if the field is invalid or refers
+     *              to a field that cannot be handled by this method.
+     * @see #roll(int, boolean)
+     * @see #add
+     * @stable ICU 2.0
+     */
+    public void roll(int field, int amount) {
+        calendar.roll(getJDKField(field), amount);
+    }
+
+    /**
+     * Add a signed amount to a specified field, using this calendar's rules.
+     * For example, to add three days to the current date, you can call
+     * <code>add(Calendar.DATE, 3)</code>.
+     * <p>
+     * When adding to certain fields, the values of other fields may conflict and
+     * need to be changed.  For example, when adding one to the {@link #MONTH MONTH} field
+     * for the Gregorian date 1/31/96, the {@link #DAY_OF_MONTH DAY_OF_MONTH} field
+     * must be adjusted so that the result is 2/29/96 rather than the invalid
+     * 2/31/96.
+     * <p>
+     * {@icunote} The ICU implementation of this method is able to add to
+     * all fields except for {@link #ERA ERA}, {@link #DST_OFFSET DST_OFFSET},
+     * and {@link #ZONE_OFFSET ZONE_OFFSET}.  Subclasses may, of course, add support for
+     * additional fields in their overrides of <code>add</code>.
+     * <p>
+     * <b>Note:</b> You should always use <tt>roll</tt> and <tt>add</tt> rather
+     * than attempting to perform arithmetic operations directly on the fields
+     * of a <tt>Calendar</tt>.  It is quite possible for <tt>Calendar</tt> subclasses
+     * to have fields with non-linear behavior, for example missing months
+     * or days during non-leap years.  The subclasses' <tt>add</tt> and <tt>roll</tt>
+     * methods will take this into account, while simple arithmetic manipulations
+     * may give invalid results.
+     * <p>
+     * <b>Subclassing:</b><br>
+     * This implementation of <code>add</code> assumes that the behavior of the
+     * field is continuous between its minimum and maximum, which are found by
+     * calling {@link #getActualMinimum getActualMinimum} and
+     * {@link #getActualMaximum getActualMaximum}.
+     * For such fields, simple arithmetic operations are sufficient to
+     * perform the add.
+     * <p>
+     * Subclasses that have fields for which this assumption of continuity breaks
+     * down must overide <code>add</code> to handle those fields specially.
+     * For example, in the Hebrew calendar the month "Adar I"
+     * only occurs in leap years; in other years the calendar jumps from
+     * Shevat (month #4) to Adar (month #6).  The
+     * {@link HebrewCalendar#add HebrewCalendar.add} method takes this into account,
+     * so that adding one month
+     * to a date in Shevat gives the proper result (Adar) in a non-leap year.
+     * <p>
+     * @param field     the time field.
+     * @param amount    the amount to add to the field.
+     *
+     * @exception   IllegalArgumentException if the field is invalid or refers
+     *              to a field that cannot be handled by this method.
+     * @see #roll(int, int)
+     * @stable ICU 2.0
+     */
+    public void add(int field, int amount) {
+        calendar.add(getJDKField(field), amount);
+    }
+
+    private static String _getDisplayName(Calendar cal) {
+        String type = cal.getType();
+        if (type.equals("japanese")) {
+            return "Japanese Calendar";
+        } else if (type.equals("buddhist")) {
+            return "Buddhist Calendar";
+        }
+        return "Gregorian Calendar";
+    }
+
+    /**
+     * Returns the name of this calendar in the language of the given locale.
+     * @stable ICU 2.0
+     */
+    public String getDisplayName(Locale loc) {
+        return _getDisplayName(this);
+    }
+
+    /**
+     * Returns the name of this calendar in the language of the given locale.
+     * @stable ICU 3.2
+     */
+    public String getDisplayName(ULocale loc) {
+        return _getDisplayName(this);
+    }
+
+    /**
+     * Compares the times (in millis) represented by two
+     * <code>Calendar</code> objects.
+     *
+     * @param that the <code>Calendar</code> to compare to this.
+     * @return <code>0</code> if the time represented by
+     * this <code>Calendar</code> is equal to the time represented
+     * by that <code>Calendar</code>, a value less than
+     * <code>0</code> if the time represented by this is before
+     * the time represented by that, and a value greater than
+     * <code>0</code> if the time represented by this
+     * is after the time represented by that.
+     * @throws NullPointerException if that
+     * <code>Calendar</code> is null.
+     * @throws IllegalArgumentException if the time of that
+     * <code>Calendar</code> can't be obtained because of invalid
+     * calendar values.
+     * @stable ICU 3.4
+     */
+    public int compareTo(Calendar that) {
+        return calendar.compareTo(that.calendar);
+    }
+
+    //-------------------------------------------------------------------------
+    // Interface for creating custon DateFormats for different types of Calendars
+    //-------------------------------------------------------------------------
+
+    /**
+     * {@icu} Returns a <code>DateFormat</code> appropriate to this calendar.
+     * Subclasses wishing to specialize this behavior should override
+     * {@link #handleGetDateFormat}.
+     * @stable ICU 2.0
+     */
+    public DateFormat getDateTimeFormat(int dateStyle, int timeStyle, Locale loc) {
+        if (dateStyle != DateFormat.NONE) {
+            if (timeStyle == DateFormat.NONE) {
+                return DateFormat.getDateInstance((Calendar)this.clone(), dateStyle, loc);
+            } else {
+                return DateFormat.getDateTimeInstance((Calendar)this.clone(), dateStyle, timeStyle, loc);
+            }
+        } else if (timeStyle != DateFormat.NONE) {
+            return DateFormat.getTimeInstance((Calendar)this.clone(), timeStyle, loc);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * {@icu} Returns a <code>DateFormat</code> appropriate to this calendar.
+     * Subclasses wishing to specialize this behavior should override
+     * {@link #handleGetDateFormat}.
+     * @stable ICU 3.2
+     */
+    public DateFormat getDateTimeFormat(int dateStyle, int timeStyle, ULocale loc) {
+        return getDateTimeFormat(dateStyle, timeStyle, loc.toLocale());
+    }
+
+    //-------------------------------------------------------------------------
+    // Constants
+    //-------------------------------------------------------------------------
+
+    /**
+     * {@icu} Returns the difference between the given time and the time this
+     * calendar object is set to.  If this calendar is set
+     * <em>before</em> the given time, the returned value will be
+     * positive.  If this calendar is set <em>after</em> the given
+     * time, the returned value will be negative.  The
+     * <code>field</code> parameter specifies the units of the return
+     * value.  For example, if <code>fieldDifference(when,
+     * Calendar.MONTH)</code> returns 3, then this calendar is set to
+     * 3 months before <code>when</code>, and possibly some additional
+     * time less than one month.
+     *
+     * <p>As a side effect of this call, this calendar is advanced
+     * toward <code>when</code> by the given amount.  That is, calling
+     * this method has the side effect of calling <code>add(field,
+     * n)</code>, where <code>n</code> is the return value.
+     *
+     * <p>Usage: To use this method, call it first with the largest
+     * field of interest, then with progressively smaller fields.  For
+     * example:
+     *
+     * <pre>
+     * int y = cal.fieldDifference(when, Calendar.YEAR);
+     * int m = cal.fieldDifference(when, Calendar.MONTH);
+     * int d = cal.fieldDifference(when, Calendar.DATE);</pre>
+     *
+     * computes the difference between <code>cal</code> and
+     * <code>when</code> in years, months, and days.
+     *
+     * <p>Note: <code>fieldDifference()</code> is
+     * <em>asymmetrical</em>.  That is, in the following code:
+     *
+     * <pre>
+     * cal.setTime(date1);
+     * int m1 = cal.fieldDifference(date2, Calendar.MONTH);
+     * int d1 = cal.fieldDifference(date2, Calendar.DATE);
+     * cal.setTime(date2);
+     * int m2 = cal.fieldDifference(date1, Calendar.MONTH);
+     * int d2 = cal.fieldDifference(date1, Calendar.DATE);</pre>
+     *
+     * one might expect that <code>m1 == -m2 && d1 == -d2</code>.
+     * However, this is not generally the case, because of
+     * irregularities in the underlying calendar system (e.g., the
+     * Gregorian calendar has a varying number of days per month).
+     *
+     * @param when the date to compare this calendar's time to
+     * @param field the field in which to compute the result
+     * @return the difference, either positive or negative, between
+     * this calendar's time and <code>when</code>, in terms of
+     * <code>field</code>.
+     * @stable ICU 2.0
+     */
+    public int fieldDifference(Date when, int field) {
+        int min = 0;
+        long startMs = getTimeInMillis();
+        long targetMs = when.getTime();
+        // Always add from the start millis.  This accomodates
+        // operations like adding years from February 29, 2000 up to
+        // February 29, 2004.  If 1, 1, 1, 1 is added to the year
+        // field, the DOM gets pinned to 28 and stays there, giving an
+        // incorrect DOM difference of 1.  We have to add 1, reset, 2,
+        // reset, 3, reset, 4.
+        if (startMs < targetMs) {
+            int max = 1;
+            // Find a value that is too large
+            for (;;) {
+                setTimeInMillis(startMs);
+                add(field, max);
+                long ms = getTimeInMillis();
+                if (ms == targetMs) {
+                    return max;
+                } else if (ms > targetMs) {
+                    break;
+                } else {
+                    max <<= 1;
+                    if (max < 0) {
+                        // Field difference too large to fit into int
+                        throw new RuntimeException();
+                    }
+                }
+            }
+            // Do a binary search
+            while ((max - min) > 1) {
+                int t = (min + max) / 2;
+                setTimeInMillis(startMs);
+                add(field, t);
+                long ms = getTimeInMillis();
+                if (ms == targetMs) {
+                    return t;
+                } else if (ms > targetMs) {
+                    max = t;
+                } else {
+                    min = t;
+                }
+            }
+        } else if (startMs > targetMs) {
+            //Eclipse stated the following is "dead code"
+            /*if (false) {
+                // This works, and makes the code smaller, but costs
+                // an extra object creation and an extra couple cycles
+                // of calendar computation.
+                setTimeInMillis(targetMs);
+                min = -fieldDifference(new Date(startMs), field);
+            }*/
+            int max = -1;
+            // Find a value that is too small
+            for (;;) {
+                setTimeInMillis(startMs);
+                add(field, max);
+                long ms = getTimeInMillis();
+                if (ms == targetMs) {
+                    return max;
+                } else if (ms < targetMs) {
+                    break;
+                } else {
+                    max <<= 1;
+                    if (max == 0) {
+                        // Field difference too large to fit into int
+                        throw new RuntimeException();
+                    }
+                }
+            }
+            // Do a binary search
+            while ((min - max) > 1) {
+                int t = (min + max) / 2;
+                setTimeInMillis(startMs);
+                add(field, t);
+                long ms = getTimeInMillis();
+                if (ms == targetMs) {
+                    return t;
+                } else if (ms < targetMs) {
+                    max = t;
+                } else {
+                    min = t;
+                }
+            }
+        }
+        // Set calendar to end point
+        setTimeInMillis(startMs);
+        add(field, min);
+        return min;
+    }
+
+    /**
+     * Sets the time zone with the given time zone value.
+     * @param value the given time zone.
+     * @stable ICU 2.0
+     */
+    public void setTimeZone(TimeZone value)
+    {
+        calendar.setTimeZone(value.timeZone);
+    }
+
+    /**
+     * Returns the time zone.
+     * @return the time zone object associated with this calendar.
+     * @stable ICU 2.0
+     */
+    public TimeZone getTimeZone()
+    {
+        return new TimeZone(calendar.getTimeZone());
+    }
+
+    /**
+     * Specify whether or not date/time interpretation is to be lenient.  With
+     * lenient interpretation, a date such as "February 942, 1996" will be
+     * treated as being equivalent to the 941st day after February 1, 1996.
+     * With strict interpretation, such dates will cause an exception to be
+     * thrown.
+     *
+     * @see DateFormat#setLenient
+     * @stable ICU 2.0
+     */
+    public void setLenient(boolean lenient)
+    {
+        calendar.setLenient(lenient);
+    }
+
+    /**
+     * Tell whether date/time interpretation is to be lenient.
+     * @stable ICU 2.0
+     */
+    public boolean isLenient()
+    {
+        return calendar.isLenient();
+    }
+
+    /**
+     * Sets what the first day of the week is; e.g., Sunday in US,
+     * Monday in France.
+     * @param value the given first day of the week.
+     * @stable ICU 2.0
+     */
+    public void setFirstDayOfWeek(int value)
+    {
+        calendar.setFirstDayOfWeek(value);
+    }
+
+    /**
+     * Returns what the first day of the week is; e.g., Sunday in US,
+     * Monday in France.
+     * @return the first day of the week.
+     * @stable ICU 2.0
+     */
+    public int getFirstDayOfWeek()
+    {
+        return calendar.getFirstDayOfWeek();
+    }
+
+    /**
+     * Sets what the minimal days required in the first week of the year are.
+     * For example, if the first week is defined as one that contains the first
+     * day of the first month of a year, call the method with value 1. If it
+     * must be a full week, use value 7.
+     * @param value the given minimal days required in the first week
+     * of the year.
+     * @stable ICU 2.0
+     */
+    public void setMinimalDaysInFirstWeek(int value)
+    {
+        calendar.setMinimalDaysInFirstWeek(value);
+    }
+
+    /**
+     * Returns what the minimal days required in the first week of the year are;
+     * e.g., if the first week is defined as one that contains the first day
+     * of the first month of a year, getMinimalDaysInFirstWeek returns 1. If
+     * the minimal days required must be a full week, getMinimalDaysInFirstWeek
+     * returns 7.
+     * @return the minimal days required in the first week of the year.
+     * @stable ICU 2.0
+     */
+    public int getMinimalDaysInFirstWeek()
+    {
+        return calendar.getMinimalDaysInFirstWeek();
+    }
+
+    /**
+     * Returns the minimum value for the given time field.
+     * e.g., for Gregorian DAY_OF_MONTH, 1.
+     * @param field the given time field.
+     * @return the minimum value for the given time field.
+     * @stable ICU 2.0
+     */
+    public final int getMinimum(int field) {
+        return calendar.getMinimum(getJDKField(field));
+    }
+
+    /**
+     * Returns the maximum value for the given time field.
+     * e.g. for Gregorian DAY_OF_MONTH, 31.
+     * @param field the given time field.
+     * @return the maximum value for the given time field.
+     * @stable ICU 2.0
+     */
+    public final int getMaximum(int field) {
+        return calendar.getMaximum(getJDKField(field));
+    }
+
+    /**
+     * Returns the highest minimum value for the given field if varies.
+     * Otherwise same as getMinimum(). For Gregorian, no difference.
+     * @param field the given time field.
+     * @return the highest minimum value for the given time field.
+     * @stable ICU 2.0
+     */
+    public final int getGreatestMinimum(int field) {
+        return calendar.getGreatestMinimum(getJDKField(field));
+    }
+
+    /**
+     * Returns the lowest maximum value for the given field if varies.
+     * Otherwise same as getMaximum(). e.g., for Gregorian DAY_OF_MONTH, 28.
+     * @param field the given time field.
+     * @return the lowest maximum value for the given time field.
+     * @stable ICU 2.0
+     */
+    public final int getLeastMaximum(int field) {
+        return calendar.getLeastMaximum(getJDKField(field));
+    }
+
+    //-------------------------------------------------------------------------
+    // Weekend support -- determining which days of the week are the weekend
+    // in a given locale
+    //-------------------------------------------------------------------------
+
+    /**
+     * {@icu} Returns whether the given day of the week is a weekday, a
+     * weekend day, or a day that transitions from one to the other,
+     * in this calendar system.  If a transition occurs at midnight,
+     * then the days before and after the transition will have the
+     * type WEEKDAY or WEEKEND.  If a transition occurs at a time
+     * other than midnight, then the day of the transition will have
+     * the type WEEKEND_ONSET or WEEKEND_CEASE.  In this case, the
+     * method getWeekendTransition() will return the point of
+     * transition.
+     * @param dayOfWeek either SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
+     * THURSDAY, FRIDAY, or SATURDAY
+     * @return either WEEKDAY, WEEKEND, WEEKEND_ONSET, or
+     * WEEKEND_CEASE
+     * @exception IllegalArgumentException if dayOfWeek is not
+     * between SUNDAY and SATURDAY, inclusive
+     * @see #WEEKDAY
+     * @see #WEEKEND
+     * @see #WEEKEND_ONSET
+     * @see #WEEKEND_CEASE
+     * @see #getWeekendTransition
+     * @see #isWeekend(Date)
+     * @see #isWeekend()
+     * @stable ICU 2.0
+     */
+    public int getDayOfWeekType(int dayOfWeek) {
+        // weekend always full saturday and sunday with com.ibm.icu.base
+        if (dayOfWeek < SUNDAY || dayOfWeek > 7) {
+            throw new IllegalArgumentException("illegal day of week: " + dayOfWeek);
+        } else if (dayOfWeek == SATURDAY || dayOfWeek == SUNDAY) {
+            return WEEKEND;
+        }
+        return WEEKDAY;}
+
+    /**
+     * {@icu} Returns the time during the day at which the weekend begins or end in this
+     * calendar system.  If getDayOfWeekType(dayOfWeek) == WEEKEND_ONSET return the time
+     * at which the weekend begins.  If getDayOfWeekType(dayOfWeek) == WEEKEND_CEASE
+     * return the time at which the weekend ends.  If getDayOfWeekType(dayOfWeek) has some
+     * other value, then throw an exception.
+     * @param dayOfWeek either SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
+     * THURSDAY, FRIDAY, or SATURDAY
+     * @return the milliseconds after midnight at which the
+     * weekend begins or ends
+     * @exception IllegalArgumentException if dayOfWeek is not
+     * WEEKEND_ONSET or WEEKEND_CEASE
+     * @see #getDayOfWeekType
+     * @see #isWeekend(Date)
+     * @see #isWeekend()
+     * @stable ICU 2.0
+     */
+    public int getWeekendTransition(int dayOfWeek) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Returns true if the given date and time is in the weekend in this calendar
+     * system.  Equivalent to calling setTime() followed by isWeekend().  Note: This
+     * method changes the time this calendar is set to.
+     * @param date the date and time
+     * @return true if the given date and time is part of the
+     * weekend
+     * @see #getDayOfWeekType
+     * @see #getWeekendTransition
+     * @see #isWeekend()
+     * @stable ICU 2.0
+     */
+    public boolean isWeekend(Date date) {
+        calendar.setTime(date);
+        return isWeekend();
+    }
+
+    /**
+     * {@icu} Returns true if this Calendar's current date and time is in the weekend in
+     * this calendar system.
+     * @return true if the given date and time is part of the
+     * weekend
+     * @see #getDayOfWeekType
+     * @see #getWeekendTransition
+     * @see #isWeekend(Date)
+     * @stable ICU 2.0
+     */
+    public boolean isWeekend() {
+        // weekend always full saturday and sunday with com.ibm.icu.base
+        int dow = calendar.get(Calendar.DAY_OF_WEEK);
+        if (dow == SATURDAY || dow == SUNDAY) {
+            return true;
+        }
+        return false;
+    }
+
+    //-------------------------------------------------------------------------
+    // End of weekend support
+    //-------------------------------------------------------------------------
+
+    /**
+     * Overrides Cloneable
+     * @stable ICU 2.0
+     */
+    public Object clone()
+    {
+        return new Calendar((java.util.Calendar)calendar.clone());
+    }
+
+    /**
+     * Returns a string representation of this calendar. This method
+     * is intended to be used only for debugging purposes, and the
+     * format of the returned string may vary between implementations.
+     * The returned string may be empty but may not be <code>null</code>.
+     *
+     * @return  a string representation of this calendar.
+     * @stable ICU 2.0
+     */
+    public String toString() {
+        return calendar.toString();
+    }
+
+    /**
+     * {@icu} Returns the number of fields defined by this calendar.  Valid field
+     * arguments to <code>set()</code> and <code>get()</code> are
+     * <code>0..getFieldCount()-1</code>.
+     * @stable ICU 2.0
+     */
+    public final int getFieldCount() {
+        return FIELD_COUNT;
+    }
+    private static final int FIELD_COUNT = IS_LEAP_MONTH + 1;
+
+    /**
+     * {@icu} Returns the current Calendar type.  Note, in 3.0 this function will return
+     * 'gregorian' in Calendar to emulate legacy behavior
+     * @return type of calendar (gregorian, etc)
+     * @stable ICU 3.8
+     */
+    public String getType() {
+        // JDK supports Gregorian, Japanese and Buddhist
+        String name = calendar.getClass().getSimpleName().toLowerCase(Locale.US);
+        if (name.contains("japanese")) {
+            return "japanese";
+        } else if (name.contains("buddhist")) {
+            return "buddhist";
+        }
+        return "gregorian";
+    }
+
+    // -------- BEGIN ULocale boilerplate --------
+
+    /**
+     * {@icu} Returns the locale that was used to create this object, or null.
+     * This may may differ from the locale requested at the time of
+     * this object's creation.  For example, if an object is created
+     * for locale <tt>en_US_CALIFORNIA</tt>, the actual data may be
+     * drawn from <tt>en</tt> (the <i>actual</i> locale), and
+     * <tt>en_US</tt> may be the most specific locale that exists (the
+     * <i>valid</i> locale).
+     *
+     * <p>Note: This method will be implemented in ICU 3.0; ICU 2.8
+     * contains a partial preview implementation.  The * <i>actual</i>
+     * locale is returned correctly, but the <i>valid</i> locale is
+     * not, in most cases.
+     * @param type type of information requested, either {@link
+     * com.ibm.icu.util.ULocale#VALID_LOCALE} or {@link
+     * com.ibm.icu.util.ULocale#ACTUAL_LOCALE}.
+     * @return the information specified by <i>type</i>, or null if
+     * this object was not constructed from locale data.
+     * @see com.ibm.icu.util.ULocale
+     * @see com.ibm.icu.util.ULocale#VALID_LOCALE
+     * @see com.ibm.icu.util.ULocale#ACTUAL_LOCALE
+     * @draft ICU 2.8 (retain)
+     * @provisional This API might change or be removed in a future release.
+     */
+    public final ULocale getLocale(ULocale.Type type) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    // -------- END ULocale boilerplate --------
+
+
+    private static int getJDKField(int icuField) {
+        switch (icuField) {
+        case ERA:
+            return java.util.Calendar.ERA;
+        case YEAR:
+            return java.util.Calendar.YEAR;
+        case MONTH:
+            return java.util.Calendar.MONTH;
+        case WEEK_OF_YEAR:
+            return java.util.Calendar.WEEK_OF_YEAR;
+        case WEEK_OF_MONTH:
+            return java.util.Calendar.WEEK_OF_MONTH;
+        case DATE:
+            return java.util.Calendar.DATE;
+//        case DAY_OF_MONTH:
+//            return java.util.Calendar.DAY_OF_MONTH;
+        case DAY_OF_YEAR:
+            return java.util.Calendar.DAY_OF_YEAR;
+        case DAY_OF_WEEK:
+            return java.util.Calendar.DAY_OF_WEEK;
+        case DAY_OF_WEEK_IN_MONTH:
+            return java.util.Calendar.DAY_OF_WEEK_IN_MONTH;
+        case AM_PM:
+            return java.util.Calendar.AM_PM;
+        case HOUR:
+            return java.util.Calendar.HOUR;
+        case HOUR_OF_DAY:
+            return java.util.Calendar.HOUR_OF_DAY;
+        case MINUTE:
+            return java.util.Calendar.MINUTE;
+        case SECOND:
+            return java.util.Calendar.SECOND;
+        case MILLISECOND:
+            return java.util.Calendar.MILLISECOND;
+        case ZONE_OFFSET:
+            return java.util.Calendar.ZONE_OFFSET;
+        case DST_OFFSET:
+            return java.util.Calendar.DST_OFFSET;
+
+        case YEAR_WOY:
+        case DOW_LOCAL:
+        case EXTENDED_YEAR:
+        case JULIAN_DAY:
+        case MILLISECONDS_IN_DAY:
+            // Unmappable
+            throw new UnsupportedOperationException("Calendar field type not supported by com.ibm.icu.base");
+        default:
+            // Illegal
+            throw new ArrayIndexOutOfBoundsException("Specified calendar field is out of range");
+        }
+    }
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/Currency.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/Currency.java
index bac7820..d635029 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/Currency.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/Currency.java
@@ -1,420 +1,420 @@
-/**
- *******************************************************************************
- * Copyright (C) 2001-2011, International Business Machines Corporation and    *
- * others. All Rights Reserved.                                                *
- *******************************************************************************
- */
-package com.ibm.icu.util;
-
-import java.io.Serializable;
-import java.text.ParsePosition;
-import java.util.Date;
-import java.util.Locale;
-
-/**
- * A class encapsulating a currency, as defined by ISO 4217.  A
- * <tt>Currency</tt> object can be created given a <tt>Locale</tt> or
- * given an ISO 4217 code.  Once created, the <tt>Currency</tt> object
- * can return various data necessary to its proper display:
- *
- * <ul><li>A display symbol, for a specific locale
- * <li>The number of fraction digits to display
- * <li>A rounding increment
- * </ul>
- *
- * The <tt>DecimalFormat</tt> class uses these data to display
- * currencies.
- *
- * <p>Note: This class deliberately resembles
- * <tt>java.util.Currency</tt> but it has a completely independent
- * implementation, and adds features not present in the JDK.
- * @author Alan Liu
- * @stable ICU 2.2
- */
-public class Currency implements Serializable {
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * @internal
-     */
-    public final java.util.Currency currency;
-
-    /**
-     * @internal
-     * @param delegate the NumberFormat to which to delegate
-     */
-    public Currency(java.util.Currency delegate) {
-        this.currency = delegate;
-    }
-
-    /**
-     * Selector for getName() indicating a symbolic name for a
-     * currency, such as "$" for USD.
-     * @stable ICU 2.6
-     */
-    public static final int SYMBOL_NAME = 0;
-
-    /**
-     * Selector for ucurr_getName indicating the long name for a
-     * currency, such as "US Dollar" for USD.
-     * @stable ICU 2.6
-     */
-    public static final int LONG_NAME = 1;
-   
-    /**
-     * Selector for getName() indicating the plural long name for a 
-     * currency, such as "US dollar" for USD in "1 US dollar", 
-     * and "US dollars" for USD in "2 US dollars".
-     * @stable ICU 4.2
-     */
-    public static final int PLURAL_LONG_NAME = 2;
-
-    /**
-     * Returns a currency object for the default currency in the given
-     * locale.
-     * @param locale the locale
-     * @return the currency object for this locale
-     * @stable ICU 2.2
-     */
-    public static Currency getInstance(Locale locale) {
-        return new Currency(java.util.Currency.getInstance(locale));
-    }
-
-    /**
-     * Returns a currency object for the default currency in the given
-     * locale.
-     * @stable ICU 3.2
-     */
-    public static Currency getInstance(ULocale locale) {
-        return new Currency(java.util.Currency.getInstance(locale.toLocale()));
-    }
-
-    /**
-     * Returns an array of Strings which contain the currency
-     * identifiers that are valid for the given locale on the 
-     * given date.  If there are no such identifiers, returns null.
-     * Returned identifiers are in preference order.
-     * @param loc the locale for which to retrieve currency codes.
-     * @param d the date for which to retrieve currency codes for the given locale.
-     * @return The array of ISO currency codes.
-     * @stable ICU 4.0
-     */
-    public static String[] getAvailableCurrencyCodes(ULocale loc, Date d) {
-        throw new UnsupportedOperationException("Method not supproted by com.ibm.icu.base");
-    }
-
-    /**
-     * Returns a currency object given an ISO 4217 3-letter code.
-     * @param theISOCode the iso code
-     * @return the currency for this iso code
-     * @throws NullPointerException if <code>theISOCode</code> is null.
-     * @throws IllegalArgumentException if <code>theISOCode</code> is not a
-     *         3-letter alpha code.
-     * @stable ICU 2.2
-     */
-    public static Currency getInstance(String theISOCode) {
-        return new Currency(java.util.Currency.getInstance(theISOCode));
-    }
-
-    /**
-     * Registers a new currency for the provided locale.  The returned object
-     * is a key that can be used to unregister this currency object.
-     * @param currency the currency to register
-     * @param locale the ulocale under which to register the currency
-     * @return a registry key that can be used to unregister this currency
-     * @see #unregister
-     * @stable ICU 3.2
-     */
-    public static Object registerInstance(Currency currency, ULocale locale) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Unregister the currency associated with this key (obtained from
-     * registerInstance).
-     * @param registryKey the registry key returned from registerInstance
-     * @see #registerInstance
-     * @stable ICU 2.6
-     */
-    public static boolean unregister(Object registryKey) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Return an array of the locales for which a currency
-     * is defined.
-     * @return an array of the available locales
-     * @stable ICU 2.2
-     */
-    public static Locale[] getAvailableLocales() {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Return an array of the ulocales for which a currency
-     * is defined.
-     * @return an array of the available ulocales
-     * @stable ICU 3.2
-     */
-    public static ULocale[] getAvailableULocales() {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Given a key and a locale, returns an array of values for the key for which data
-     * exists.  If commonlyUsed is true, these are the values that typically are used
-     * with this locale, otherwise these are all values for which data exists.  
-     * This is a common service API.
-     * <p>
-     * The only supported key is "currency", other values return an empty array.
-     * <p>
-     * Currency information is based on the region of the locale.  If the locale does not
-     * indicate a region, {@link ULocale#addLikelySubtags(ULocale)} is used to infer a region,
-     * except for the 'und' locale.
-     * <p>
-     * If commonlyUsed is true, only the currencies known to be in use as of the current date
-     * are returned.  When there are more than one, these are returned in preference order
-     * (typically, this occurs when a country is transitioning to a new currency, and the
-     * newer currency is preferred), see 
-     * <a href="http://unicode.org/reports/tr35/#Supplemental_Currency_Data">Unicode TR#35 Sec. C1</a>.  
-     * If commonlyUsed is false, all currencies ever used in any locale are returned, in no
-     * particular order.
-     * 
-     * @param key           key whose values to look up.  the only recognized key is "currency"
-     * @param locale        the locale
-     * @param commonlyUsed  if true, return only values that are currently used in the locale.
-     *                      Otherwise returns all values.
-     * @return an array of values for the given key and the locale.  If there is no data, the
-     *   array will be empty.
-     * @stable ICU 4.2
-     */
-    public static final String[] getKeywordValuesForLocale(String key, ULocale locale, 
-            boolean commonlyUsed) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Return a hashcode for this currency.
-     * @stable ICU 2.2
-     */
-    public int hashCode() {
-        return currency.hashCode();
-    }
-
-    /**
-     * Return true if rhs is a Currency instance,
-     * is non-null, and has the same currency code.
-     * @stable ICU 2.2
-     */
-    public boolean equals(Object rhs) {
-        try {
-            return currency.equals(((Currency)rhs).currency);
-        }
-        catch (Exception e) {
-            return false;
-        }
-    }
-
-    /**
-     * Returns the ISO 4217 3-letter code for this currency object.
-     * @stable ICU 2.2
-     */
-    public String getCurrencyCode() {
-        return currency.getCurrencyCode();
-    }
-
-    /**
-     * Convenience and compatibility override of getName that
-     * requests the symbol name.
-     * @see #getName
-     * @stable ICU 3.4
-     */
-    public String getSymbol() {
-        return currency.getSymbol();
-    }
-
-    /**
-     * Convenience and compatibility override of getName that
-     * requests the symbol name.
-     * @param loc the Locale for the symbol
-     * @see #getName
-     * @stable ICU 3.4
-     */
-    public String getSymbol(Locale loc) {
-        return currency.getSymbol(loc);
-    }
-
-    /**
-     * Convenience and compatibility override of getName that
-     * requests the symbol name.
-     * @param uloc the ULocale for the symbol
-     * @see #getName
-     * @stable ICU 3.4
-     */
-    public String getSymbol(ULocale uloc) {
-        return currency.getSymbol(uloc.toLocale());
-    }
-
-    /**
-     * Returns the display name for the given currency in the
-     * given locale.  
-     * This is a convenient method for 
-     * getName(ULocale, int, boolean[]); 
-     * @stable ICU 3.2
-     */
-    public String getName(Locale locale,
-                          int nameStyle,
-                          boolean[] isChoiceFormat) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Returns the display name for the given currency in the
-     * given locale.  For example, the display name for the USD
-     * currency object in the en_US locale is "$".
-     * @param locale locale in which to display currency
-     * @param nameStyle selector for which kind of name to return.
-     *                  The nameStyle should be either SYMBOL_NAME or 
-     *                  LONG_NAME. Otherwise, throw IllegalArgumentException.
-     * @param isChoiceFormat fill-in; isChoiceFormat[0] is set to true
-     * if the returned value is a ChoiceFormat pattern; otherwise it
-     * is set to false
-     * @return display string for this currency.  If the resource data
-     * contains no entry for this currency, then the ISO 4217 code is
-     * returned.  If isChoiceFormat[0] is true, then the result is a
-     * ChoiceFormat pattern.  Otherwise it is a static string. <b>Note:</b>
-     * as of ICU 4.4, choice formats are not used, and the value returned
-     * in isChoiceFormat is always false.
-     * <p>
-     * @throws  IllegalArgumentException  if the nameStyle is not SYMBOL_NAME
-     *                                    or LONG_NAME.
-     * @see #getName(ULocale, int, String, boolean[])
-     * @stable ICU 3.2
-     */
-    public String getName(ULocale locale, int nameStyle, boolean[] isChoiceFormat) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Returns the display name for the given currency in the given locale.  
-     * This is a convenience overload of getName(ULocale, int, String, boolean[]);
-     * @stable ICU 4.2
-     */
-    public String getName(Locale locale, int nameStyle, String pluralCount,
-            boolean[] isChoiceFormat) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Returns the display name for the given currency in the
-     * given locale.  For example, the SYMBOL_NAME for the USD
-     * currency object in the en_US locale is "$".
-     * The PLURAL_LONG_NAME for the USD currency object when the currency 
-     * amount is plural is "US dollars", such as in "3.00 US dollars";
-     * while the PLURAL_LONG_NAME for the USD currency object when the currency
-     * amount is singular is "US dollar", such as in "1.00 US dollar".
-     * @param locale locale in which to display currency
-     * @param nameStyle selector for which kind of name to return
-     * @param pluralCount plural count string for this locale
-     * @param isChoiceFormat fill-in; isChoiceFormat[0] is set to true
-     * if the returned value is a ChoiceFormat pattern; otherwise it
-     * is set to false
-     * @return display string for this currency.  If the resource data
-     * contains no entry for this currency, then the ISO 4217 code is
-     * returned.  If isChoiceFormat[0] is true, then the result is a
-     * ChoiceFormat pattern.  Otherwise it is a static string. <b>Note:</b>
-     * as of ICU 4.4, choice formats are not used, and the value returned
-     * in isChoiceFormat is always false.
-     * @throws  IllegalArgumentException  if the nameStyle is not SYMBOL_NAME,
-     *                                    LONG_NAME, or PLURAL_LONG_NAME.
-     * @stable ICU 4.2
-     */
-    public String getName(ULocale locale, int nameStyle, String pluralCount,
-            boolean[] isChoiceFormat) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Attempt to parse the given string as a currency, either as a
-     * display name in the given locale, or as a 3-letter ISO 4217
-     * code.  If multiple display names match, then the longest one is
-     * selected.  If both a display name and a 3-letter ISO code
-     * match, then the display name is preferred, unless it's length
-     * is less than 3.
-     *
-     * @param locale the locale of the display names to match
-     * @param text the text to parse
-     * @param type parse against currency type: LONG_NAME only or not
-     * @param pos input-output position; on input, the position within
-     * text to match; must have 0 <= pos.getIndex() < text.length();
-     * on output, the position after the last matched character. If
-     * the parse fails, the position in unchanged upon output.
-     * @return the ISO 4217 code, as a string, of the best match, or
-     * null if there is no match
-     *
-     * @internal
-     * @deprecated This API is ICU internal only.
-     */
-    public static String parse(ULocale locale, String text, int type, ParsePosition pos) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Returns the number of the number of fraction digits that should
-     * be displayed for this currency.
-     * @return a non-negative number of fraction digits to be
-     * displayed
-     * @stable ICU 2.2
-     */
-    public int getDefaultFractionDigits() {
-        return currency.getDefaultFractionDigits();
-    }
-
-    /**
-     * Returns the rounding increment for this currency, or 0.0 if no
-     * rounding is done by this currency.
-     * @return the non-negative rounding increment, or 0.0 if none
-     * @stable ICU 2.2
-     */
-    public double getRoundingIncrement() {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Returns the ISO 4217 code for this currency.
-     * @stable ICU 2.2
-     */
-    public String toString() {
-        return currency.toString();
-    }
-
-    /**
-     * Return the locale that was used to create this object, or null.
-     * This may may differ from the locale requested at the time of
-     * this object's creation.  For example, if an object is created
-     * for locale <tt>en_US_CALIFORNIA</tt>, the actual data may be
-     * drawn from <tt>en</tt> (the <i>actual</i> locale), and
-     * <tt>en_US</tt> may be the most specific locale that exists (the
-     * <i>valid</i> locale).
-     *
-     * <p>Note: This method will be obsoleted.  The implementation is
-     * no longer locale-specific and so there is no longer a valid or
-     * actual locale associated with the Currency object.  Until
-     * it is removed, this method will return the root locale.
-     * @param type type of information requested, either {@link
-     * com.ibm.icu.util.ULocale#VALID_LOCALE} or {@link
-     * com.ibm.icu.util.ULocale#ACTUAL_LOCALE}.
-     * @return the information specified by <i>type</i>, or null if
-     * this object was not constructed from locale data.
-     * @see com.ibm.icu.util.ULocale
-     * @see com.ibm.icu.util.ULocale#VALID_LOCALE
-     * @see com.ibm.icu.util.ULocale#ACTUAL_LOCALE
-     * @obsolete ICU 3.2 to be removed
-     * @deprecated This API is obsolete.
-     */
-    public final ULocale getLocale(ULocale.Type type) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-}
-
-//eof
+/**
+ *******************************************************************************
+ * Copyright (C) 2001-2011, International Business Machines Corporation and    *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+package com.ibm.icu.util;
+
+import java.io.Serializable;
+import java.text.ParsePosition;
+import java.util.Date;
+import java.util.Locale;
+
+/**
+ * A class encapsulating a currency, as defined by ISO 4217.  A
+ * <tt>Currency</tt> object can be created given a <tt>Locale</tt> or
+ * given an ISO 4217 code.  Once created, the <tt>Currency</tt> object
+ * can return various data necessary to its proper display:
+ *
+ * <ul><li>A display symbol, for a specific locale
+ * <li>The number of fraction digits to display
+ * <li>A rounding increment
+ * </ul>
+ *
+ * The <tt>DecimalFormat</tt> class uses these data to display
+ * currencies.
+ *
+ * <p>Note: This class deliberately resembles
+ * <tt>java.util.Currency</tt> but it has a completely independent
+ * implementation, and adds features not present in the JDK.
+ * @author Alan Liu
+ * @stable ICU 2.2
+ */
+public class Currency implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * @internal
+     */
+    public final java.util.Currency currency;
+
+    /**
+     * @internal
+     * @param delegate the NumberFormat to which to delegate
+     */
+    public Currency(java.util.Currency delegate) {
+        this.currency = delegate;
+    }
+
+    /**
+     * Selector for getName() indicating a symbolic name for a
+     * currency, such as "$" for USD.
+     * @stable ICU 2.6
+     */
+    public static final int SYMBOL_NAME = 0;
+
+    /**
+     * Selector for ucurr_getName indicating the long name for a
+     * currency, such as "US Dollar" for USD.
+     * @stable ICU 2.6
+     */
+    public static final int LONG_NAME = 1;
+   
+    /**
+     * Selector for getName() indicating the plural long name for a 
+     * currency, such as "US dollar" for USD in "1 US dollar", 
+     * and "US dollars" for USD in "2 US dollars".
+     * @stable ICU 4.2
+     */
+    public static final int PLURAL_LONG_NAME = 2;
+
+    /**
+     * Returns a currency object for the default currency in the given
+     * locale.
+     * @param locale the locale
+     * @return the currency object for this locale
+     * @stable ICU 2.2
+     */
+    public static Currency getInstance(Locale locale) {
+        return new Currency(java.util.Currency.getInstance(locale));
+    }
+
+    /**
+     * Returns a currency object for the default currency in the given
+     * locale.
+     * @stable ICU 3.2
+     */
+    public static Currency getInstance(ULocale locale) {
+        return new Currency(java.util.Currency.getInstance(locale.toLocale()));
+    }
+
+    /**
+     * Returns an array of Strings which contain the currency
+     * identifiers that are valid for the given locale on the 
+     * given date.  If there are no such identifiers, returns null.
+     * Returned identifiers are in preference order.
+     * @param loc the locale for which to retrieve currency codes.
+     * @param d the date for which to retrieve currency codes for the given locale.
+     * @return The array of ISO currency codes.
+     * @stable ICU 4.0
+     */
+    public static String[] getAvailableCurrencyCodes(ULocale loc, Date d) {
+        throw new UnsupportedOperationException("Method not supproted by com.ibm.icu.base");
+    }
+
+    /**
+     * Returns a currency object given an ISO 4217 3-letter code.
+     * @param theISOCode the iso code
+     * @return the currency for this iso code
+     * @throws NullPointerException if <code>theISOCode</code> is null.
+     * @throws IllegalArgumentException if <code>theISOCode</code> is not a
+     *         3-letter alpha code.
+     * @stable ICU 2.2
+     */
+    public static Currency getInstance(String theISOCode) {
+        return new Currency(java.util.Currency.getInstance(theISOCode));
+    }
+
+    /**
+     * Registers a new currency for the provided locale.  The returned object
+     * is a key that can be used to unregister this currency object.
+     * @param currency the currency to register
+     * @param locale the ulocale under which to register the currency
+     * @return a registry key that can be used to unregister this currency
+     * @see #unregister
+     * @stable ICU 3.2
+     */
+    public static Object registerInstance(Currency currency, ULocale locale) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Unregister the currency associated with this key (obtained from
+     * registerInstance).
+     * @param registryKey the registry key returned from registerInstance
+     * @see #registerInstance
+     * @stable ICU 2.6
+     */
+    public static boolean unregister(Object registryKey) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Return an array of the locales for which a currency
+     * is defined.
+     * @return an array of the available locales
+     * @stable ICU 2.2
+     */
+    public static Locale[] getAvailableLocales() {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Return an array of the ulocales for which a currency
+     * is defined.
+     * @return an array of the available ulocales
+     * @stable ICU 3.2
+     */
+    public static ULocale[] getAvailableULocales() {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Given a key and a locale, returns an array of values for the key for which data
+     * exists.  If commonlyUsed is true, these are the values that typically are used
+     * with this locale, otherwise these are all values for which data exists.  
+     * This is a common service API.
+     * <p>
+     * The only supported key is "currency", other values return an empty array.
+     * <p>
+     * Currency information is based on the region of the locale.  If the locale does not
+     * indicate a region, {@link ULocale#addLikelySubtags(ULocale)} is used to infer a region,
+     * except for the 'und' locale.
+     * <p>
+     * If commonlyUsed is true, only the currencies known to be in use as of the current date
+     * are returned.  When there are more than one, these are returned in preference order
+     * (typically, this occurs when a country is transitioning to a new currency, and the
+     * newer currency is preferred), see 
+     * <a href="http://unicode.org/reports/tr35/#Supplemental_Currency_Data">Unicode TR#35 Sec. C1</a>.  
+     * If commonlyUsed is false, all currencies ever used in any locale are returned, in no
+     * particular order.
+     * 
+     * @param key           key whose values to look up.  the only recognized key is "currency"
+     * @param locale        the locale
+     * @param commonlyUsed  if true, return only values that are currently used in the locale.
+     *                      Otherwise returns all values.
+     * @return an array of values for the given key and the locale.  If there is no data, the
+     *   array will be empty.
+     * @stable ICU 4.2
+     */
+    public static final String[] getKeywordValuesForLocale(String key, ULocale locale, 
+            boolean commonlyUsed) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Return a hashcode for this currency.
+     * @stable ICU 2.2
+     */
+    public int hashCode() {
+        return currency.hashCode();
+    }
+
+    /**
+     * Return true if rhs is a Currency instance,
+     * is non-null, and has the same currency code.
+     * @stable ICU 2.2
+     */
+    public boolean equals(Object rhs) {
+        try {
+            return currency.equals(((Currency)rhs).currency);
+        }
+        catch (Exception e) {
+            return false;
+        }
+    }
+
+    /**
+     * Returns the ISO 4217 3-letter code for this currency object.
+     * @stable ICU 2.2
+     */
+    public String getCurrencyCode() {
+        return currency.getCurrencyCode();
+    }
+
+    /**
+     * Convenience and compatibility override of getName that
+     * requests the symbol name.
+     * @see #getName
+     * @stable ICU 3.4
+     */
+    public String getSymbol() {
+        return currency.getSymbol();
+    }
+
+    /**
+     * Convenience and compatibility override of getName that
+     * requests the symbol name.
+     * @param loc the Locale for the symbol
+     * @see #getName
+     * @stable ICU 3.4
+     */
+    public String getSymbol(Locale loc) {
+        return currency.getSymbol(loc);
+    }
+
+    /**
+     * Convenience and compatibility override of getName that
+     * requests the symbol name.
+     * @param uloc the ULocale for the symbol
+     * @see #getName
+     * @stable ICU 3.4
+     */
+    public String getSymbol(ULocale uloc) {
+        return currency.getSymbol(uloc.toLocale());
+    }
+
+    /**
+     * Returns the display name for the given currency in the
+     * given locale.  
+     * This is a convenient method for 
+     * getName(ULocale, int, boolean[]); 
+     * @stable ICU 3.2
+     */
+    public String getName(Locale locale,
+                          int nameStyle,
+                          boolean[] isChoiceFormat) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Returns the display name for the given currency in the
+     * given locale.  For example, the display name for the USD
+     * currency object in the en_US locale is "$".
+     * @param locale locale in which to display currency
+     * @param nameStyle selector for which kind of name to return.
+     *                  The nameStyle should be either SYMBOL_NAME or 
+     *                  LONG_NAME. Otherwise, throw IllegalArgumentException.
+     * @param isChoiceFormat fill-in; isChoiceFormat[0] is set to true
+     * if the returned value is a ChoiceFormat pattern; otherwise it
+     * is set to false
+     * @return display string for this currency.  If the resource data
+     * contains no entry for this currency, then the ISO 4217 code is
+     * returned.  If isChoiceFormat[0] is true, then the result is a
+     * ChoiceFormat pattern.  Otherwise it is a static string. <b>Note:</b>
+     * as of ICU 4.4, choice formats are not used, and the value returned
+     * in isChoiceFormat is always false.
+     * <p>
+     * @throws  IllegalArgumentException  if the nameStyle is not SYMBOL_NAME
+     *                                    or LONG_NAME.
+     * @see #getName(ULocale, int, String, boolean[])
+     * @stable ICU 3.2
+     */
+    public String getName(ULocale locale, int nameStyle, boolean[] isChoiceFormat) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Returns the display name for the given currency in the given locale.  
+     * This is a convenience overload of getName(ULocale, int, String, boolean[]);
+     * @stable ICU 4.2
+     */
+    public String getName(Locale locale, int nameStyle, String pluralCount,
+            boolean[] isChoiceFormat) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Returns the display name for the given currency in the
+     * given locale.  For example, the SYMBOL_NAME for the USD
+     * currency object in the en_US locale is "$".
+     * The PLURAL_LONG_NAME for the USD currency object when the currency 
+     * amount is plural is "US dollars", such as in "3.00 US dollars";
+     * while the PLURAL_LONG_NAME for the USD currency object when the currency
+     * amount is singular is "US dollar", such as in "1.00 US dollar".
+     * @param locale locale in which to display currency
+     * @param nameStyle selector for which kind of name to return
+     * @param pluralCount plural count string for this locale
+     * @param isChoiceFormat fill-in; isChoiceFormat[0] is set to true
+     * if the returned value is a ChoiceFormat pattern; otherwise it
+     * is set to false
+     * @return display string for this currency.  If the resource data
+     * contains no entry for this currency, then the ISO 4217 code is
+     * returned.  If isChoiceFormat[0] is true, then the result is a
+     * ChoiceFormat pattern.  Otherwise it is a static string. <b>Note:</b>
+     * as of ICU 4.4, choice formats are not used, and the value returned
+     * in isChoiceFormat is always false.
+     * @throws  IllegalArgumentException  if the nameStyle is not SYMBOL_NAME,
+     *                                    LONG_NAME, or PLURAL_LONG_NAME.
+     * @stable ICU 4.2
+     */
+    public String getName(ULocale locale, int nameStyle, String pluralCount,
+            boolean[] isChoiceFormat) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Attempt to parse the given string as a currency, either as a
+     * display name in the given locale, or as a 3-letter ISO 4217
+     * code.  If multiple display names match, then the longest one is
+     * selected.  If both a display name and a 3-letter ISO code
+     * match, then the display name is preferred, unless it's length
+     * is less than 3.
+     *
+     * @param locale the locale of the display names to match
+     * @param text the text to parse
+     * @param type parse against currency type: LONG_NAME only or not
+     * @param pos input-output position; on input, the position within
+     * text to match; must have 0 <= pos.getIndex() < text.length();
+     * on output, the position after the last matched character. If
+     * the parse fails, the position in unchanged upon output.
+     * @return the ISO 4217 code, as a string, of the best match, or
+     * null if there is no match
+     *
+     * @internal
+     * @deprecated This API is ICU internal only.
+     */
+    public static String parse(ULocale locale, String text, int type, ParsePosition pos) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Returns the number of the number of fraction digits that should
+     * be displayed for this currency.
+     * @return a non-negative number of fraction digits to be
+     * displayed
+     * @stable ICU 2.2
+     */
+    public int getDefaultFractionDigits() {
+        return currency.getDefaultFractionDigits();
+    }
+
+    /**
+     * Returns the rounding increment for this currency, or 0.0 if no
+     * rounding is done by this currency.
+     * @return the non-negative rounding increment, or 0.0 if none
+     * @stable ICU 2.2
+     */
+    public double getRoundingIncrement() {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Returns the ISO 4217 code for this currency.
+     * @stable ICU 2.2
+     */
+    public String toString() {
+        return currency.toString();
+    }
+
+    /**
+     * Return the locale that was used to create this object, or null.
+     * This may may differ from the locale requested at the time of
+     * this object's creation.  For example, if an object is created
+     * for locale <tt>en_US_CALIFORNIA</tt>, the actual data may be
+     * drawn from <tt>en</tt> (the <i>actual</i> locale), and
+     * <tt>en_US</tt> may be the most specific locale that exists (the
+     * <i>valid</i> locale).
+     *
+     * <p>Note: This method will be obsoleted.  The implementation is
+     * no longer locale-specific and so there is no longer a valid or
+     * actual locale associated with the Currency object.  Until
+     * it is removed, this method will return the root locale.
+     * @param type type of information requested, either {@link
+     * com.ibm.icu.util.ULocale#VALID_LOCALE} or {@link
+     * com.ibm.icu.util.ULocale#ACTUAL_LOCALE}.
+     * @return the information specified by <i>type</i>, or null if
+     * this object was not constructed from locale data.
+     * @see com.ibm.icu.util.ULocale
+     * @see com.ibm.icu.util.ULocale#VALID_LOCALE
+     * @see com.ibm.icu.util.ULocale#ACTUAL_LOCALE
+     * @obsolete ICU 3.2 to be removed
+     * @deprecated This API is obsolete.
+     */
+    public final ULocale getLocale(ULocale.Type type) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+}
+
+//eof
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/CurrencyAmount.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/CurrencyAmount.java
index 22b3239..229a400 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/CurrencyAmount.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/CurrencyAmount.java
@@ -1,14 +1,14 @@
-/*
- *******************************************************************************
- * Copyright (C) 2011, International Business Machines Corporation and         *
- * others. All Rights Reserved.                                                *
- *******************************************************************************
- */
-package com.ibm.icu.util;
-
-/*
- * Empty stub
- */
-public class CurrencyAmount {
-    private CurrencyAmount() {}
-}
+/*
+ *******************************************************************************
+ * Copyright (C) 2011, International Business Machines Corporation and         *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+package com.ibm.icu.util;
+
+/*
+ * Empty stub
+ */
+public class CurrencyAmount {
+    private CurrencyAmount() {}
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/IllformedLocaleException.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/IllformedLocaleException.java
new file mode 100644
index 0000000..be0f48d
--- /dev/null
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/IllformedLocaleException.java
@@ -0,0 +1,73 @@
+/*
+ *******************************************************************************
+ * Copyright (C) 2009-2011, International Business Machines Corporation and    *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+package com.ibm.icu.util;
+
+/**
+ * Thrown by methods in {@link ULocale} and {@link ULocale.Builder} to
+ * indicate that an argument is not a well-formed BCP 47 tag.
+ * 
+ * @see ULocale
+ * @draft ICU 4.2
+ * @provisional This API might change or be removed in a future release.
+ */
+public class IllformedLocaleException extends RuntimeException {
+
+    private static final long serialVersionUID = 1L;
+
+    private int _errIdx = -1;
+
+    /**
+     * Constructs a new <code>IllformedLocaleException</code> with no
+     * detail message and -1 as the error index.
+     * @draft ICU 4.6
+     * @provisional This API might change or be removed in a future release.
+     */
+    public IllformedLocaleException() {
+        super();
+    }
+
+    /**
+     * Constructs a new <code>IllformedLocaleException</code> with the
+     * given message and -1 as the error index.
+     *
+     * @param message the message
+     * @draft ICU 4.2
+     * @provisional This API might change or be removed in a future release.
+     */
+    public IllformedLocaleException(String message) {
+        super(message);
+    }
+
+    /**
+     * Constructs a new <code>IllformedLocaleException</code> with the
+     * given message and the error index.  The error index is the approximate
+     * offset from the start of the ill-formed value to the point where the
+     * parse first detected an error.  A negative error index value indicates
+     * either the error index is not applicable or unknown.
+     *
+     * @param message the message
+     * @param errorIndex the index
+     * @draft ICU 4.2
+     * @provisional This API might change or be removed in a future release.
+     */
+    public IllformedLocaleException(String message, int errorIndex) {
+        super(message + ((errorIndex < 0) ? "" : " [at index " + errorIndex + "]"));
+        _errIdx = errorIndex;
+    }
+
+    /**
+     * Returns the index where the error was found. A negative value indicates
+     * either the error index is not applicable or unknown.
+     *
+     * @return the error index
+     * @draft ICU 4.2
+     * @provisional This API might change or be removed in a future release.
+     */
+    public int getErrorIndex() {
+        return _errIdx;
+    }
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/TimeZone.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/TimeZone.java
index f775d29..0e35274 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/TimeZone.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/TimeZone.java
@@ -1,710 +1,712 @@
-/*
- * @(#)TimeZone.java    1.51 00/01/19
- *
- * Copyright (C) 1996-2011, International Business Machines
- * Corporation and others.  All Rights Reserved.
- */
-
-package com.ibm.icu.util;
-
-import java.io.Serializable;
-import java.util.Date;
-import java.util.Locale;
-import java.util.MissingResourceException;
-
-/**
- * {@icuenhanced java.util.TimeZone}.{@icu _usage_}
- *
- * <p><code>TimeZone</code> represents a time zone offset, and also computes daylight
- * savings.
- *
- * <p>Typically, you get a <code>TimeZone</code> using {@link #getDefault()}
- * which creates a <code>TimeZone</code> based on the time zone where the program
- * is running. For example, for a program running in Japan, <code>getDefault</code>
- * creates a <code>TimeZone</code> object based on Japanese Standard Time.
- *
- * <p>You can also get a <code>TimeZone</code> using {@link #getTimeZone(String)}
- * along with a time zone ID. For instance, the time zone ID for the
- * U.S. Pacific Time zone is "America/Los_Angeles". So, you can get a
- * U.S. Pacific Time <code>TimeZone</code> object with:
- *
- * <blockquote>
- * <pre>
- * TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
- * </pre>
- * </blockquote>
- * You can use the {@link #getAvailableIDs()} method to iterate through
- * all the supported time zone IDs. You can then choose a
- * supported ID to get a <code>TimeZone</code>.
- * If the time zone you want is not represented by one of the
- * supported IDs, then you can create a custom time zone ID with
- * the following syntax:
- *
- * <blockquote>
- * <pre>
- * GMT[+|-]hh[[:]mm]
- * </pre>
- * </blockquote>
- *
- * For example, you might specify GMT+14:00 as a custom
- * time zone ID.  The <code>TimeZone</code> that is returned
- * when you specify a custom time zone ID does not include
- * daylight savings time.
- *
- * <p>For compatibility with JDK 1.1.x, some other three-letter time zone IDs
- * (such as "PST", "CTT", "AST") are also supported. However, <strong>their
- * use is deprecated</strong> because the same abbreviation is often used
- * for multiple time zones (for example, "CST" could be U.S. "Central Standard
- * Time" and "China Standard Time"), and the Java platform can then only
- * recognize one of them.
- *
- * <p><strong>Note:</strong> Starting from ICU4J 4.0, you can optionally choose
- * JDK <code>TimeZone</code> as the time zone implementation.  The TimeZone factory
- * method <code>getTimeZone</code> creates an instance of ICU's own <code>TimeZone</code>
- * subclass by default.  If you want to use the JDK implementation always, you can
- * set the default time zone implementation type by the new method
- * <code>setDefaultTimeZoneType</code>.  Alternatively, you can change the initial
- * default implementation type by setting a property below.
- *
- * <blockquote>
- * <pre>
- * #
- * # The default TimeZone implementation type used by the ICU TimeZone
- * # factory method. [ ICU | JDK ]
- * #
- * com.ibm.icu.util.TimeZone.DefaultTimeZoneType = ICU
- * </pre>
- * </blockquote>
- *
- * <p>This property is included in ICUConfig.properties in com.ibm.icu package.  When the
- * <code>TimeZone</code> class is loaded, the initialization code checks if the property
- * <code>com.ibm.icu.util.TimeZone.DefaultTimeZoneType=xxx</code> is defined by the system
- * properties.  If not available, then it loads ICUConfig.properties to get the default
- * time zone implementation type.  The property setting is only used for the initial
- * default value and you can change the default type by calling
- * <code>setDefaultTimeZoneType</code> at runtime.
- *
- * @see          Calendar
- * @see          GregorianCalendar
- * @see          SimpleTimeZone
- * @author       Mark Davis, David Goldsmith, Chen-Lieh Huang, Alan Liu
- * @stable ICU 2.0
- */
-public class TimeZone implements Serializable, Cloneable {
-    private static final long serialVersionUID = 1L;
-    
-    /**
-     * @internal
-     */
-    public final java.util.TimeZone timeZone;
-        
-    /**
-     * @internal
-     * @param delegate the TimeZone to which to delegate
-     */
-    public TimeZone(java.util.TimeZone delegate) {
-        this.timeZone = delegate;
-    }
-
-//    /**
-//     * {@icu} A logger for TimeZone. Will be null if logging is not on by way of system
-//     * property: "icu4j.debug.logging"
-//     * @draft ICU 4.4
-//     * @provisional This API might change or be removed in a future release.
-//     */
-//    public static ICULogger TimeZoneLogger = ICULogger.getICULogger(TimeZone.class.getName());
-
-    /**
-     * Default constructor.  (For invocation by subclass constructors,
-     * typically implicit.)
-     * @stable ICU 2.8
-     */
-    public TimeZone() {
-        this.timeZone = java.util.TimeZone.getDefault();
-    }
-
-    /**
-     * {@icu} A time zone implementation type indicating ICU's own TimeZone used by
-     * <code>getTimeZone</code>, <code>setDefaultTimeZoneType</code>
-     * and <code>getDefaultTimeZoneType</code>.
-     * @stable ICU 4.0
-     */
-    public static final int TIMEZONE_ICU = 0;
-    /**
-     * {@icu} A time zone implementation type indicating JDK TimeZone used by
-     * <code>getTimeZone</code>, <code>setDefaultTimeZoneType</code>
-     * and <code>getDefaultTimeZoneType</code>.
-     * @stable ICU 4.0
-     */
-    public static final int TIMEZONE_JDK = 1;
-
-    /**
-     * A style specifier for <code>getDisplayName()</code> indicating
-     * a short name, such as "PST."
-     * @see #LONG
-     * @stable ICU 2.0
-     */
-    public static final int SHORT = 0;
-
-    /**
-     * A style specifier for <code>getDisplayName()</code> indicating
-     * a long name, such as "Pacific Standard Time."
-     * @see #SHORT
-     * @stable ICU 2.0
-     */
-    public static final int LONG  = 1;
-
-    /**
-     * {@icu} A style specifier for <code>getDisplayName()</code> indicating
-     * a short generic name, such as "PT."
-     * @see #LONG_GENERIC
-     * @draft ICU 4.4
-     * @provisional This API might change or be removed in a future release.
-     */
-    public static final int SHORT_GENERIC = 2;
-
-    /**
-     * {@icu} A style specifier for <code>getDisplayName()</code> indicating
-     * a long generic name, such as "Pacific Time."
-     * @see #SHORT_GENERIC
-     * @draft ICU 4.4
-     * @provisional This API might change or be removed in a future release.
-     */
-    public static final int LONG_GENERIC = 3;
-
-    /**
-     * {@icu} A style specifier for <code>getDisplayName()</code> indicating
-     * a short name derived from the timezone's offset, such as "-0800."
-     * @see #LONG_GMT
-     * @draft ICU 4.4
-     * @provisional This API might change or be removed in a future release.
-     */
-    public static final int SHORT_GMT = 4;
-
-    /**
-     * {@icu} A style specifier for <code>getDisplayName()</code> indicating
-     * a long name derived from the timezone's offset, such as "GMT-08:00."
-     * @see #SHORT_GMT
-     * @draft ICU 4.4
-     * @provisional This API might change or be removed in a future release.
-     */
-    public static final int LONG_GMT = 5;
-
-    /**
-     * {@icu} A style specifier for <code>getDisplayName()</code> indicating
-     * a short name derived from the timezone's short standard or daylight
-     * timezone name ignoring commonlyUsed, such as "PDT."
-     * @draft ICU 4.4
-     * @provisional This API might change or be removed in a future release.
-     */
-
-    public static final int SHORT_COMMONLY_USED = 6;
-
-    /**
-     * {@icu} A style specifier for <code>getDisplayName()</code> indicating
-     * a long name derived from the timezone's fallback name, such as
-     * "United States (Los Angeles)."
-     * @draft ICU 4.4
-     * @provisional This API might change or be removed in a future release.
-     */
-    public static final int GENERIC_LOCATION = 7;
-
-    /**
-     * Gets the time zone offset, for current date, modified in case of
-     * daylight savings. This is the offset to add *to* UTC to get local time.
-     * @param era the era of the given date.
-     * @param year the year in the given date.
-     * @param month the month in the given date.
-     * Month is 0-based. e.g., 0 for January.
-     * @param day the day-in-month of the given date.
-     * @param dayOfWeek the day-of-week of the given date.
-     * @param milliseconds the millis in day in <em>standard</em> local time.
-     * @return the offset to add *to* GMT to get local time.
-     * @stable ICU 2.0
-     */
-    public int getOffset(int era, int year, int month, int day,
-                                  int dayOfWeek, int milliseconds) {
-        return timeZone.getOffset(era, year, month, day, dayOfWeek, milliseconds);
-    }
-
-
-    /**
-     * Returns the offset of this time zone from UTC at the specified
-     * date. If Daylight Saving Time is in effect at the specified
-     * date, the offset value is adjusted with the amount of daylight
-     * saving.
-     *
-     * @param date the date represented in milliseconds since January 1, 1970 00:00:00 GMT
-     * @return the amount of time in milliseconds to add to UTC to get local time.
-     *
-     * @see Calendar#ZONE_OFFSET
-     * @see Calendar#DST_OFFSET
-     * @see #getOffset(long, boolean, int[])
-     * @stable ICU 2.8
-     */
-    public int getOffset(long date) {
-        return timeZone.getOffset(date);
-    }
-
-    /**
-     * Returns the time zone raw and GMT offset for the given moment
-     * in time.  Upon return, local-millis = GMT-millis + rawOffset +
-     * dstOffset.  All computations are performed in the proleptic
-     * Gregorian calendar.  The default implementation in the TimeZone
-     * class delegates to the 8-argument getOffset().
-     *
-     * @param date moment in time for which to return offsets, in
-     * units of milliseconds from January 1, 1970 0:00 GMT, either GMT
-     * time or local wall time, depending on `local'.
-     * @param local if true, `date' is local wall time; otherwise it
-     * is in GMT time.
-     * @param offsets output parameter to receive the raw offset, that
-     * is, the offset not including DST adjustments, in offsets[0],
-     * and the DST offset, that is, the offset to be added to
-     * `rawOffset' to obtain the total offset between local and GMT
-     * time, in offsets[1]. If DST is not in effect, the DST offset is
-     * zero; otherwise it is a positive value, typically one hour.
-     *
-     * @stable ICU 2.8
-     */
-    public void getOffset(long date, boolean local, int[] offsets) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Sets the base time zone offset to GMT.
-     * This is the offset to add *to* UTC to get local time.
-     * @param offsetMillis the given base time zone offset to GMT.
-     * @stable ICU 2.0
-     */
-    public void setRawOffset(int offsetMillis) {
-        timeZone.setRawOffset(offsetMillis);
-    }
-
-    /**
-     * Gets unmodified offset, NOT modified in case of daylight savings.
-     * This is the offset to add *to* UTC to get local time.
-     * @return the unmodified offset to add *to* UTC to get local time.
-     * @stable ICU 2.0
-     */
-    public int getRawOffset() {
-        return timeZone.getRawOffset();
-    }
-
-    /**
-     * Gets the ID of this time zone.
-     * @return the ID of this time zone.
-     * @stable ICU 2.0
-     */
-    public String getID() {
-        return timeZone.getID();
-    }
-
-    /**
-     * Sets the time zone ID. This does not change any other data in
-     * the time zone object.
-     * @param ID the new time zone ID.
-     * @stable ICU 2.0
-     */
-    public void setID(String ID) {
-        timeZone.setID(ID);
-    }
-
-    /**
-     * Returns a name of this time zone suitable for presentation to the user
-     * in the default locale.
-     * This method returns the long generic name.
-     * If the display name is not available for the locale,
-     * a fallback based on the country, city, or time zone id will be used.
-     * @return the human-readable name of this time zone in the default locale.
-     * @stable ICU 2.0
-     */
-    public final String getDisplayName() {
-        return timeZone.getDisplayName();
-    }
-
-    /**
-     * Returns a name of this time zone suitable for presentation to the user
-     * in the specified locale.
-     * This method returns the long generic name.
-     * If the display name is not available for the locale,
-     * a fallback based on the country, city, or time zone id will be used.
-     * @param locale the locale in which to supply the display name.
-     * @return the human-readable name of this time zone in the given locale
-     * or in the default locale if the given locale is not recognized.
-     * @stable ICU 2.0
-     */
-    public final String getDisplayName(Locale locale) {
-        return timeZone.getDisplayName(locale);
-    }
-
-    /**
-     * Returns a name of this time zone suitable for presentation to the user
-     * in the specified locale.
-     * This method returns the long name, not including daylight savings.
-     * If the display name is not available for the locale,
-     * a fallback based on the country, city, or time zone id will be used.
-     * @param locale the ulocale in which to supply the display name.
-     * @return the human-readable name of this time zone in the given locale
-     * or in the default ulocale if the given ulocale is not recognized.
-     * @stable ICU 3.2
-     */
-    public final String getDisplayName(ULocale locale) {
-        return timeZone.getDisplayName(locale.toLocale());
-    }
-
-    /**
-     * Returns a name of this time zone suitable for presentation to the user
-     * in the default locale.
-     * If the display name is not available for the locale,
-     * then this method returns a string in the format
-     * <code>GMT[+-]hh:mm</code>.
-     * @param daylight if true, return the daylight savings name.
-     * @param style the output style of the display name.  Valid styles are
-     * <code>SHORT</code>, <code>LONG</code>, <code>SHORT_GENERIC</code>,
-     * <code>LONG_GENERIC</code>, <code>SHORT_GMT</code>, <code>LONG_GMT</code>,
-     * <code>SHORT_COMMONLY_USED</code> or <code>GENERIC_LOCATION</code>.
-     * @return the human-readable name of this time zone in the default locale.
-     * @stable ICU 2.0
-     */
-    public final String getDisplayName(boolean daylight, int style) {
-        return getDisplayName(daylight, style, ULocale.getDefault());
-    }
-
-    /**
-     * Returns a name of this time zone suitable for presentation to the user
-     * in the specified locale.
-     * If the display name is not available for the locale,
-     * then this method returns a string in the format
-     * <code>GMT[+-]hh:mm</code>.
-     * @param daylight if true, return the daylight savings name.
-     * @param style the output style of the display name.  Valid styles are
-     * <code>SHORT</code>, <code>LONG</code>, <code>SHORT_GENERIC</code>,
-     * <code>LONG_GENERIC</code>, <code>SHORT_GMT</code>, <code>LONG_GMT</code>,
-     * <code>SHORT_COMMONLY_USED</code> or <code>GENERIC_LOCATION</code>.
-     * @param locale the locale in which to supply the display name.
-     * @return the human-readable name of this time zone in the given locale
-     * or in the default locale if the given locale is not recognized.
-     * @exception IllegalArgumentException style is invalid.
-     * @stable ICU 2.0
-     */
-    public String getDisplayName(boolean daylight, int style, Locale locale) {
-        return getDisplayName(daylight, style, ULocale.forLocale(locale));
-    }
-
-    /**
-     * Returns a name of this time zone suitable for presentation to the user
-     * in the specified locale.
-     * If the display name is not available for the locale,
-     * then this method returns a string in the format
-     * <code>GMT[+-]hh:mm</code>.
-     * @param daylight if true, return the daylight savings name.
-     * @param style the output style of the display name.  Valid styles are
-     * <code>SHORT</code>, <code>LONG</code>, <code>SHORT_GENERIC</code>,
-     * <code>LONG_GENERIC</code>, <code>SHORT_GMT</code>, <code>LONG_GMT</code>,
-     * <code>SHORT_COMMONLY_USED</code> or <code>GENERIC_LOCATION</code>.
-     * @param locale the locale in which to supply the display name.
-     * @return the human-readable name of this time zone in the given locale
-     * or in the default locale if the given locale is not recognized.
-     * @exception IllegalArgumentException style is invalid.
-     * @stable ICU 3.2
-     */
-    public String getDisplayName(boolean daylight, int style, ULocale locale) {
-        if (style == SHORT) {
-            return timeZone.getDisplayName(daylight, java.util.TimeZone.SHORT, locale.toLocale());
-        } else if (style == LONG) {
-            return timeZone.getDisplayName(daylight, java.util.TimeZone.LONG, locale.toLocale());
-        } else {
-            throw new UnsupportedOperationException("Specified time zone format style is not supported by com.ibm.icu.base");
-        }
-    }
-
-    /**
-     * Returns the amount of time to be added to local standard time
-     * to get local wall clock time.
-     * <p>
-     * The default implementation always returns 3600000 milliseconds
-     * (i.e., one hour) if this time zone observes Daylight Saving
-     * Time. Otherwise, 0 (zero) is returned.
-     * <p>
-     * If an underlying TimeZone implementation subclass supports
-     * historical Daylight Saving Time changes, this method returns
-     * the known latest daylight saving value.
-     *
-     * @return the amount of saving time in milliseconds
-     * @stable ICU 2.8
-     */
-    public int getDSTSavings() {
-        return timeZone.getDSTSavings();
-    }
-
-    /**
-     * Queries if this time zone uses daylight savings time.
-     * @return true if this time zone uses daylight savings time,
-     * false, otherwise.
-     * @stable ICU 2.0
-     */
-    public boolean useDaylightTime() {
-        return timeZone.useDaylightTime();
-    }
-
-    /**
-     * Queries if the given date is in daylight savings time in
-     * this time zone.
-     * @param date the given Date.
-     * @return true if the given date is in daylight savings time,
-     * false, otherwise.
-     * @stable ICU 2.0
-     */
-    public boolean inDaylightTime(Date date) {
-        return timeZone.inDaylightTime(date);
-    }
-
-    /**
-     * Gets the <code>TimeZone</code> for the given ID.
-     *
-     * @param ID the ID for a <code>TimeZone</code>, such as "America/Los_Angeles",
-     * or a custom ID such as "GMT-8:00". Note that the support of abbreviations,
-     * such as "PST", is for JDK 1.1.x compatibility only and full names should be used.
-     *
-     * @return the specified <code>TimeZone</code>, or the GMT zone if the given ID
-     * cannot be understood.
-     * @stable ICU 2.0
-     */
-    public static synchronized TimeZone getTimeZone(String ID) {
-        return new TimeZone(java.util.TimeZone.getTimeZone(ID));
-    }
-
-    /**
-     * Gets the <code>TimeZone</code> for the given ID and the timezone type.
-     * @param ID the ID for a <code>TimeZone</code>, such as "America/Los_Angeles", or a
-     * custom ID such as "GMT-8:00". Note that the support of abbreviations, such as
-     * "PST", is for JDK 1.1.x compatibility only and full names should be used.
-     * @param type Time zone type, either <code>TIMEZONE_ICU</code> or
-     * <code>TIMEZONE_JDK</code>.
-     * @return the specified <code>TimeZone</code>, or the GMT zone if the given ID
-     * cannot be understood.
-     * @stable ICU 4.0
-     */
-    public static synchronized TimeZone getTimeZone(String ID, int type) {
-        if (type == TIMEZONE_JDK) {
-            return new TimeZone(java.util.TimeZone.getTimeZone(ID));
-        }
-        throw new UnsupportedOperationException("TIMEZONE_ICU not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Sets the default time zone type used by <code>getTimeZone</code>.
-     * @param type time zone type, either <code>TIMEZONE_ICU</code> or
-     * <code>TIMEZONE_JDK</code>.
-     * @stable ICU 4.0
-     */
-    public static synchronized void setDefaultTimeZoneType(int type) {
-        if (type != TIMEZONE_JDK) {
-            throw new UnsupportedOperationException("TimeZone type other than TIMEZONE_JDK is not supported by com.ibm.icu.base");
-        }
-    }
-
-    /**
-     * {@icu} Returns the default time zone type currently used.
-     * @return The default time zone type, either <code>TIMEZONE_ICU</code> or
-     * <code>TIMEZONE_JDK</code>.
-     * @stable ICU 4.0
-     */
-    public static int getDefaultTimeZoneType() {
-        return TIMEZONE_JDK;
-    }
-
-    /**
-     * Return a new String array containing all system TimeZone IDs
-     * with the given raw offset from GMT.  These IDs may be passed to
-     * <code>get()</code> to construct the corresponding TimeZone
-     * object.
-     * @param rawOffset the offset in milliseconds from GMT
-     * @return an array of IDs for system TimeZones with the given
-     * raw offset.  If there are none, return a zero-length array.
-     * @stable ICU 2.0
-     */
-    public static String[] getAvailableIDs(int rawOffset) {
-        return java.util.TimeZone.getAvailableIDs(rawOffset);
-
-    }
-
-
-    /**
-     * Return a new String array containing all system TimeZone IDs
-     * associated with the given country.  These IDs may be passed to
-     * <code>get()</code> to construct the corresponding TimeZone
-     * object.
-     * @param country a two-letter ISO 3166 country code, or <code>null</code>
-     * to return zones not associated with any country
-     * @return an array of IDs for system TimeZones in the given
-     * country.  If there are none, return a zero-length array.
-     * @stable ICU 2.0
-     */
-    public static String[] getAvailableIDs(String country) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Return a new String array containing all system TimeZone IDs.
-     * These IDs (and only these IDs) may be passed to
-     * <code>get()</code> to construct the corresponding TimeZone
-     * object.
-     * @return an array of all system TimeZone IDs
-     * @stable ICU 2.0
-     */
-    public static String[] getAvailableIDs() {
-        return java.util.TimeZone.getAvailableIDs();
-    }
-
-    /**
-     * {@icu} Returns the number of IDs in the equivalency group that
-     * includes the given ID.  An equivalency group contains zones
-     * that have the same GMT offset and rules.
-     *
-     * <p>The returned count includes the given ID; it is always >= 1
-     * for valid IDs.  The given ID must be a system time zone.  If it
-     * is not, returns zero.
-     * @param id a system time zone ID
-     * @return the number of zones in the equivalency group containing
-     * 'id', or zero if 'id' is not a valid system ID
-     * @see #getEquivalentID
-     * @stable ICU 2.0
-     */
-    public static int countEquivalentIDs(String id) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Returns an ID in the equivalency group that
-     * includes the given ID.  An equivalency group contains zones
-     * that have the same GMT offset and rules.
-     *
-     * <p>The given index must be in the range 0..n-1, where n is the
-     * value returned by <code>countEquivalentIDs(id)</code>.  For
-     * some value of 'index', the returned value will be equal to the
-     * given id.  If the given id is not a valid system time zone, or
-     * if 'index' is out of range, then returns an empty string.
-     * @param id a system time zone ID
-     * @param index a value from 0 to n-1, where n is the value
-     * returned by <code>countEquivalentIDs(id)</code>
-     * @return the ID of the index-th zone in the equivalency group
-     * containing 'id', or an empty string if 'id' is not a valid
-     * system ID or 'index' is out of range
-     * @see #countEquivalentIDs
-     * @stable ICU 2.0
-     */
-    public static String getEquivalentID(String id, int index) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * Gets the default <code>TimeZone</code> for this host.
-     * The source of the default <code>TimeZone</code>
-     * may vary with implementation.
-     * @return a default <code>TimeZone</code>.
-     * @stable ICU 2.0
-     */
-    public static TimeZone getDefault() {
-        return new TimeZone(java.util.TimeZone.getDefault());
-    }
-
-    /**
-     * Sets the <code>TimeZone</code> that is
-     * returned by the <code>getDefault</code> method.  If <code>zone</code>
-     * is null, reset the default to the value it had originally when the
-     * VM first started.
-     * @param tz the new default time zone
-     * @stable ICU 2.0
-     */
-    public static void setDefault(TimeZone tz) {
-        java.util.TimeZone.setDefault(tz.timeZone);
-    }
-
-    /**
-     * Returns true if this zone has the same rule and offset as another zone.
-     * That is, if this zone differs only in ID, if at all.  Returns false
-     * if the other zone is null.
-     * @param other the <code>TimeZone</code> object to be compared with
-     * @return true if the other zone is not null and is the same as this one,
-     * with the possible exception of the ID
-     * @stable ICU 2.0
-     */
-    public boolean hasSameRules(TimeZone other) {
-        return timeZone.hasSameRules(other.timeZone);
-    }
-
-    /**
-     * Overrides clone.
-     * @stable ICU 2.0
-     */
-    public Object clone() {
-        return new TimeZone((java.util.TimeZone)timeZone.clone());
-    }
-
-    /**
-     * Overrides equals.
-     * @stable ICU 3.6
-     */
-    public boolean equals(Object obj){
-        try {
-            return timeZone.equals(((TimeZone)obj).timeZone);
-        } catch (Exception e) {
-            return false;
-        }
-    }
-
-    /**
-     * Overrides hashCode.
-     * @stable ICU 3.6
-     */
-    public int hashCode(){
-        return timeZone.hashCode();
-    }
-
-    /**
-     * {@icu} Returns the time zone data version currently used by ICU.
-     *
-     * @return the version string, such as "2007f"
-     * @throws MissingResourceException if ICU time zone resource bundle
-     * is missing or the version information is not available.
-     *
-     * @stable ICU 3.8
-     */
-    public static synchronized String getTZDataVersion() {
-        throw new UnsupportedOperationException("Method not supproted by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Returns the canonical system time zone ID or the normalized
-     * custom time zone ID for the given time zone ID.
-     * @param id The input time zone ID to be canonicalized.
-     * @return The canonical system time zone ID or the custom time zone ID
-     * in normalized format for the given time zone ID.  When the given time zone ID
-     * is neither a known system time zone ID nor a valid custom time zone ID,
-     * null is returned.
-     * @stable ICU 4.0
-     */
-    public static String getCanonicalID(String id) {
-        throw new UnsupportedOperationException("Method not supproted by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Returns the canonical system time zone ID or the normalized
-     * custom time zone ID for the given time zone ID.
-     * @param id The input time zone ID to be canonicalized.
-     * @param isSystemID When non-null boolean array is specified and
-     * the given ID is a known system time zone ID, true is set to <code>isSystemID[0]</code>
-     * @return The canonical system time zone ID or the custom time zone ID
-     * in normalized format for the given time zone ID.  When the given time zone ID
-     * is neither a known system time zone ID nor a valid custom time zone ID,
-     * null is returned.
-     * @stable ICU 4.0
-     */
-    public static String getCanonicalID(String id, boolean[] isSystemID) {
-        throw new UnsupportedOperationException("Method not supproted by com.ibm.icu.base");
-    }
-}
-
-//eof
+/*
+ * @(#)TimeZone.java    1.51 00/01/19
+ *
+ * Copyright (C) 1996-2011, International Business Machines
+ * Corporation and others.  All Rights Reserved.
+ */
+
+package com.ibm.icu.util;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.Locale;
+import java.util.MissingResourceException;
+
+import com.ibm.icu.util.ULocale.Category;
+
+/**
+ * {@icuenhanced java.util.TimeZone}.{@icu _usage_}
+ *
+ * <p><code>TimeZone</code> represents a time zone offset, and also computes daylight
+ * savings.
+ *
+ * <p>Typically, you get a <code>TimeZone</code> using {@link #getDefault()}
+ * which creates a <code>TimeZone</code> based on the time zone where the program
+ * is running. For example, for a program running in Japan, <code>getDefault</code>
+ * creates a <code>TimeZone</code> object based on Japanese Standard Time.
+ *
+ * <p>You can also get a <code>TimeZone</code> using {@link #getTimeZone(String)}
+ * along with a time zone ID. For instance, the time zone ID for the
+ * U.S. Pacific Time zone is "America/Los_Angeles". So, you can get a
+ * U.S. Pacific Time <code>TimeZone</code> object with:
+ *
+ * <blockquote>
+ * <pre>
+ * TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
+ * </pre>
+ * </blockquote>
+ * You can use the {@link #getAvailableIDs()} method to iterate through
+ * all the supported time zone IDs. You can then choose a
+ * supported ID to get a <code>TimeZone</code>.
+ * If the time zone you want is not represented by one of the
+ * supported IDs, then you can create a custom time zone ID with
+ * the following syntax:
+ *
+ * <blockquote>
+ * <pre>
+ * GMT[+|-]hh[[:]mm]
+ * </pre>
+ * </blockquote>
+ *
+ * For example, you might specify GMT+14:00 as a custom
+ * time zone ID.  The <code>TimeZone</code> that is returned
+ * when you specify a custom time zone ID does not include
+ * daylight savings time.
+ *
+ * <p>For compatibility with JDK 1.1.x, some other three-letter time zone IDs
+ * (such as "PST", "CTT", "AST") are also supported. However, <strong>their
+ * use is deprecated</strong> because the same abbreviation is often used
+ * for multiple time zones (for example, "CST" could be U.S. "Central Standard
+ * Time" and "China Standard Time"), and the Java platform can then only
+ * recognize one of them.
+ *
+ * <p><strong>Note:</strong> Starting from ICU4J 4.0, you can optionally choose
+ * JDK <code>TimeZone</code> as the time zone implementation.  The TimeZone factory
+ * method <code>getTimeZone</code> creates an instance of ICU's own <code>TimeZone</code>
+ * subclass by default.  If you want to use the JDK implementation always, you can
+ * set the default time zone implementation type by the new method
+ * <code>setDefaultTimeZoneType</code>.  Alternatively, you can change the initial
+ * default implementation type by setting a property below.
+ *
+ * <blockquote>
+ * <pre>
+ * #
+ * # The default TimeZone implementation type used by the ICU TimeZone
+ * # factory method. [ ICU | JDK ]
+ * #
+ * com.ibm.icu.util.TimeZone.DefaultTimeZoneType = ICU
+ * </pre>
+ * </blockquote>
+ *
+ * <p>This property is included in ICUConfig.properties in com.ibm.icu package.  When the
+ * <code>TimeZone</code> class is loaded, the initialization code checks if the property
+ * <code>com.ibm.icu.util.TimeZone.DefaultTimeZoneType=xxx</code> is defined by the system
+ * properties.  If not available, then it loads ICUConfig.properties to get the default
+ * time zone implementation type.  The property setting is only used for the initial
+ * default value and you can change the default type by calling
+ * <code>setDefaultTimeZoneType</code> at runtime.
+ *
+ * @see          Calendar
+ * @see          GregorianCalendar
+ * @see          SimpleTimeZone
+ * @author       Mark Davis, David Goldsmith, Chen-Lieh Huang, Alan Liu
+ * @stable ICU 2.0
+ */
+public class TimeZone implements Serializable, Cloneable {
+    private static final long serialVersionUID = 1L;
+    
+    /**
+     * @internal
+     */
+    public final java.util.TimeZone timeZone;
+        
+    /**
+     * @internal
+     * @param delegate the TimeZone to which to delegate
+     */
+    public TimeZone(java.util.TimeZone delegate) {
+        this.timeZone = delegate;
+    }
+
+//    /**
+//     * {@icu} A logger for TimeZone. Will be null if logging is not on by way of system
+//     * property: "icu4j.debug.logging"
+//     * @draft ICU 4.4
+//     * @provisional This API might change or be removed in a future release.
+//     */
+//    public static ICULogger TimeZoneLogger = ICULogger.getICULogger(TimeZone.class.getName());
+
+    /**
+     * Default constructor.  (For invocation by subclass constructors,
+     * typically implicit.)
+     * @stable ICU 2.8
+     */
+    public TimeZone() {
+        this.timeZone = java.util.TimeZone.getDefault();
+    }
+
+    /**
+     * {@icu} A time zone implementation type indicating ICU's own TimeZone used by
+     * <code>getTimeZone</code>, <code>setDefaultTimeZoneType</code>
+     * and <code>getDefaultTimeZoneType</code>.
+     * @stable ICU 4.0
+     */
+    public static final int TIMEZONE_ICU = 0;
+    /**
+     * {@icu} A time zone implementation type indicating JDK TimeZone used by
+     * <code>getTimeZone</code>, <code>setDefaultTimeZoneType</code>
+     * and <code>getDefaultTimeZoneType</code>.
+     * @stable ICU 4.0
+     */
+    public static final int TIMEZONE_JDK = 1;
+
+    /**
+     * A style specifier for <code>getDisplayName()</code> indicating
+     * a short name, such as "PST."
+     * @see #LONG
+     * @stable ICU 2.0
+     */
+    public static final int SHORT = 0;
+
+    /**
+     * A style specifier for <code>getDisplayName()</code> indicating
+     * a long name, such as "Pacific Standard Time."
+     * @see #SHORT
+     * @stable ICU 2.0
+     */
+    public static final int LONG  = 1;
+
+    /**
+     * {@icu} A style specifier for <code>getDisplayName()</code> indicating
+     * a short generic name, such as "PT."
+     * @see #LONG_GENERIC
+     * @draft ICU 4.4
+     * @provisional This API might change or be removed in a future release.
+     */
+    public static final int SHORT_GENERIC = 2;
+
+    /**
+     * {@icu} A style specifier for <code>getDisplayName()</code> indicating
+     * a long generic name, such as "Pacific Time."
+     * @see #SHORT_GENERIC
+     * @draft ICU 4.4
+     * @provisional This API might change or be removed in a future release.
+     */
+    public static final int LONG_GENERIC = 3;
+
+    /**
+     * {@icu} A style specifier for <code>getDisplayName()</code> indicating
+     * a short name derived from the timezone's offset, such as "-0800."
+     * @see #LONG_GMT
+     * @draft ICU 4.4
+     * @provisional This API might change or be removed in a future release.
+     */
+    public static final int SHORT_GMT = 4;
+
+    /**
+     * {@icu} A style specifier for <code>getDisplayName()</code> indicating
+     * a long name derived from the timezone's offset, such as "GMT-08:00."
+     * @see #SHORT_GMT
+     * @draft ICU 4.4
+     * @provisional This API might change or be removed in a future release.
+     */
+    public static final int LONG_GMT = 5;
+
+    /**
+     * {@icu} A style specifier for <code>getDisplayName()</code> indicating
+     * a short name derived from the timezone's short standard or daylight
+     * timezone name ignoring commonlyUsed, such as "PDT."
+     * @draft ICU 4.4
+     * @provisional This API might change or be removed in a future release.
+     */
+
+    public static final int SHORT_COMMONLY_USED = 6;
+
+    /**
+     * {@icu} A style specifier for <code>getDisplayName()</code> indicating
+     * a long name derived from the timezone's fallback name, such as
+     * "United States (Los Angeles)."
+     * @draft ICU 4.4
+     * @provisional This API might change or be removed in a future release.
+     */
+    public static final int GENERIC_LOCATION = 7;
+
+    /**
+     * Gets the time zone offset, for current date, modified in case of
+     * daylight savings. This is the offset to add *to* UTC to get local time.
+     * @param era the era of the given date.
+     * @param year the year in the given date.
+     * @param month the month in the given date.
+     * Month is 0-based. e.g., 0 for January.
+     * @param day the day-in-month of the given date.
+     * @param dayOfWeek the day-of-week of the given date.
+     * @param milliseconds the millis in day in <em>standard</em> local time.
+     * @return the offset to add *to* GMT to get local time.
+     * @stable ICU 2.0
+     */
+    public int getOffset(int era, int year, int month, int day,
+                                  int dayOfWeek, int milliseconds) {
+        return timeZone.getOffset(era, year, month, day, dayOfWeek, milliseconds);
+    }
+
+
+    /**
+     * Returns the offset of this time zone from UTC at the specified
+     * date. If Daylight Saving Time is in effect at the specified
+     * date, the offset value is adjusted with the amount of daylight
+     * saving.
+     *
+     * @param date the date represented in milliseconds since January 1, 1970 00:00:00 GMT
+     * @return the amount of time in milliseconds to add to UTC to get local time.
+     *
+     * @see Calendar#ZONE_OFFSET
+     * @see Calendar#DST_OFFSET
+     * @see #getOffset(long, boolean, int[])
+     * @stable ICU 2.8
+     */
+    public int getOffset(long date) {
+        return timeZone.getOffset(date);
+    }
+
+    /**
+     * Returns the time zone raw and GMT offset for the given moment
+     * in time.  Upon return, local-millis = GMT-millis + rawOffset +
+     * dstOffset.  All computations are performed in the proleptic
+     * Gregorian calendar.  The default implementation in the TimeZone
+     * class delegates to the 8-argument getOffset().
+     *
+     * @param date moment in time for which to return offsets, in
+     * units of milliseconds from January 1, 1970 0:00 GMT, either GMT
+     * time or local wall time, depending on `local'.
+     * @param local if true, `date' is local wall time; otherwise it
+     * is in GMT time.
+     * @param offsets output parameter to receive the raw offset, that
+     * is, the offset not including DST adjustments, in offsets[0],
+     * and the DST offset, that is, the offset to be added to
+     * `rawOffset' to obtain the total offset between local and GMT
+     * time, in offsets[1]. If DST is not in effect, the DST offset is
+     * zero; otherwise it is a positive value, typically one hour.
+     *
+     * @stable ICU 2.8
+     */
+    public void getOffset(long date, boolean local, int[] offsets) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Sets the base time zone offset to GMT.
+     * This is the offset to add *to* UTC to get local time.
+     * @param offsetMillis the given base time zone offset to GMT.
+     * @stable ICU 2.0
+     */
+    public void setRawOffset(int offsetMillis) {
+        timeZone.setRawOffset(offsetMillis);
+    }
+
+    /**
+     * Gets unmodified offset, NOT modified in case of daylight savings.
+     * This is the offset to add *to* UTC to get local time.
+     * @return the unmodified offset to add *to* UTC to get local time.
+     * @stable ICU 2.0
+     */
+    public int getRawOffset() {
+        return timeZone.getRawOffset();
+    }
+
+    /**
+     * Gets the ID of this time zone.
+     * @return the ID of this time zone.
+     * @stable ICU 2.0
+     */
+    public String getID() {
+        return timeZone.getID();
+    }
+
+    /**
+     * Sets the time zone ID. This does not change any other data in
+     * the time zone object.
+     * @param ID the new time zone ID.
+     * @stable ICU 2.0
+     */
+    public void setID(String ID) {
+        timeZone.setID(ID);
+    }
+
+    /**
+     * Returns a name of this time zone suitable for presentation to the user
+     * in the default locale.
+     * This method returns the long generic name.
+     * If the display name is not available for the locale,
+     * a fallback based on the country, city, or time zone id will be used.
+     * @return the human-readable name of this time zone in the default locale.
+     * @stable ICU 2.0
+     */
+    public final String getDisplayName() {
+        return timeZone.getDisplayName();
+    }
+
+    /**
+     * Returns a name of this time zone suitable for presentation to the user
+     * in the specified locale.
+     * This method returns the long generic name.
+     * If the display name is not available for the locale,
+     * a fallback based on the country, city, or time zone id will be used.
+     * @param locale the locale in which to supply the display name.
+     * @return the human-readable name of this time zone in the given locale
+     * or in the default locale if the given locale is not recognized.
+     * @stable ICU 2.0
+     */
+    public final String getDisplayName(Locale locale) {
+        return timeZone.getDisplayName(locale);
+    }
+
+    /**
+     * Returns a name of this time zone suitable for presentation to the user
+     * in the specified locale.
+     * This method returns the long name, not including daylight savings.
+     * If the display name is not available for the locale,
+     * a fallback based on the country, city, or time zone id will be used.
+     * @param locale the ulocale in which to supply the display name.
+     * @return the human-readable name of this time zone in the given locale
+     * or in the default ulocale if the given ulocale is not recognized.
+     * @stable ICU 3.2
+     */
+    public final String getDisplayName(ULocale locale) {
+        return timeZone.getDisplayName(locale.toLocale());
+    }
+
+    /**
+     * Returns a name of this time zone suitable for presentation to the user
+     * in the default locale.
+     * If the display name is not available for the locale,
+     * then this method returns a string in the format
+     * <code>GMT[+-]hh:mm</code>.
+     * @param daylight if true, return the daylight savings name.
+     * @param style the output style of the display name.  Valid styles are
+     * <code>SHORT</code>, <code>LONG</code>, <code>SHORT_GENERIC</code>,
+     * <code>LONG_GENERIC</code>, <code>SHORT_GMT</code>, <code>LONG_GMT</code>,
+     * <code>SHORT_COMMONLY_USED</code> or <code>GENERIC_LOCATION</code>.
+     * @return the human-readable name of this time zone in the default locale.
+     * @stable ICU 2.0
+     */
+    public final String getDisplayName(boolean daylight, int style) {
+        return getDisplayName(daylight, style, ULocale.getDefault(Category.DISPLAY));
+    }
+
+    /**
+     * Returns a name of this time zone suitable for presentation to the user
+     * in the specified locale.
+     * If the display name is not available for the locale,
+     * then this method returns a string in the format
+     * <code>GMT[+-]hh:mm</code>.
+     * @param daylight if true, return the daylight savings name.
+     * @param style the output style of the display name.  Valid styles are
+     * <code>SHORT</code>, <code>LONG</code>, <code>SHORT_GENERIC</code>,
+     * <code>LONG_GENERIC</code>, <code>SHORT_GMT</code>, <code>LONG_GMT</code>,
+     * <code>SHORT_COMMONLY_USED</code> or <code>GENERIC_LOCATION</code>.
+     * @param locale the locale in which to supply the display name.
+     * @return the human-readable name of this time zone in the given locale
+     * or in the default locale if the given locale is not recognized.
+     * @exception IllegalArgumentException style is invalid.
+     * @stable ICU 2.0
+     */
+    public String getDisplayName(boolean daylight, int style, Locale locale) {
+        return getDisplayName(daylight, style, ULocale.forLocale(locale));
+    }
+
+    /**
+     * Returns a name of this time zone suitable for presentation to the user
+     * in the specified locale.
+     * If the display name is not available for the locale,
+     * then this method returns a string in the format
+     * <code>GMT[+-]hh:mm</code>.
+     * @param daylight if true, return the daylight savings name.
+     * @param style the output style of the display name.  Valid styles are
+     * <code>SHORT</code>, <code>LONG</code>, <code>SHORT_GENERIC</code>,
+     * <code>LONG_GENERIC</code>, <code>SHORT_GMT</code>, <code>LONG_GMT</code>,
+     * <code>SHORT_COMMONLY_USED</code> or <code>GENERIC_LOCATION</code>.
+     * @param locale the locale in which to supply the display name.
+     * @return the human-readable name of this time zone in the given locale
+     * or in the default locale if the given locale is not recognized.
+     * @exception IllegalArgumentException style is invalid.
+     * @stable ICU 3.2
+     */
+    public String getDisplayName(boolean daylight, int style, ULocale locale) {
+        if (style == SHORT) {
+            return timeZone.getDisplayName(daylight, java.util.TimeZone.SHORT, locale.toLocale());
+        } else if (style == LONG) {
+            return timeZone.getDisplayName(daylight, java.util.TimeZone.LONG, locale.toLocale());
+        } else {
+            throw new UnsupportedOperationException("Specified time zone format style is not supported by com.ibm.icu.base");
+        }
+    }
+
+    /**
+     * Returns the amount of time to be added to local standard time
+     * to get local wall clock time.
+     * <p>
+     * The default implementation always returns 3600000 milliseconds
+     * (i.e., one hour) if this time zone observes Daylight Saving
+     * Time. Otherwise, 0 (zero) is returned.
+     * <p>
+     * If an underlying TimeZone implementation subclass supports
+     * historical Daylight Saving Time changes, this method returns
+     * the known latest daylight saving value.
+     *
+     * @return the amount of saving time in milliseconds
+     * @stable ICU 2.8
+     */
+    public int getDSTSavings() {
+        return timeZone.getDSTSavings();
+    }
+
+    /**
+     * Queries if this time zone uses daylight savings time.
+     * @return true if this time zone uses daylight savings time,
+     * false, otherwise.
+     * @stable ICU 2.0
+     */
+    public boolean useDaylightTime() {
+        return timeZone.useDaylightTime();
+    }
+
+    /**
+     * Queries if the given date is in daylight savings time in
+     * this time zone.
+     * @param date the given Date.
+     * @return true if the given date is in daylight savings time,
+     * false, otherwise.
+     * @stable ICU 2.0
+     */
+    public boolean inDaylightTime(Date date) {
+        return timeZone.inDaylightTime(date);
+    }
+
+    /**
+     * Gets the <code>TimeZone</code> for the given ID.
+     *
+     * @param ID the ID for a <code>TimeZone</code>, such as "America/Los_Angeles",
+     * or a custom ID such as "GMT-8:00". Note that the support of abbreviations,
+     * such as "PST", is for JDK 1.1.x compatibility only and full names should be used.
+     *
+     * @return the specified <code>TimeZone</code>, or the GMT zone if the given ID
+     * cannot be understood.
+     * @stable ICU 2.0
+     */
+    public static synchronized TimeZone getTimeZone(String ID) {
+        return new TimeZone(java.util.TimeZone.getTimeZone(ID));
+    }
+
+    /**
+     * Gets the <code>TimeZone</code> for the given ID and the timezone type.
+     * @param ID the ID for a <code>TimeZone</code>, such as "America/Los_Angeles", or a
+     * custom ID such as "GMT-8:00". Note that the support of abbreviations, such as
+     * "PST", is for JDK 1.1.x compatibility only and full names should be used.
+     * @param type Time zone type, either <code>TIMEZONE_ICU</code> or
+     * <code>TIMEZONE_JDK</code>.
+     * @return the specified <code>TimeZone</code>, or the GMT zone if the given ID
+     * cannot be understood.
+     * @stable ICU 4.0
+     */
+    public static synchronized TimeZone getTimeZone(String ID, int type) {
+        if (type == TIMEZONE_JDK) {
+            return new TimeZone(java.util.TimeZone.getTimeZone(ID));
+        }
+        throw new UnsupportedOperationException("TIMEZONE_ICU not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Sets the default time zone type used by <code>getTimeZone</code>.
+     * @param type time zone type, either <code>TIMEZONE_ICU</code> or
+     * <code>TIMEZONE_JDK</code>.
+     * @stable ICU 4.0
+     */
+    public static synchronized void setDefaultTimeZoneType(int type) {
+        if (type != TIMEZONE_JDK) {
+            throw new UnsupportedOperationException("TimeZone type other than TIMEZONE_JDK is not supported by com.ibm.icu.base");
+        }
+    }
+
+    /**
+     * {@icu} Returns the default time zone type currently used.
+     * @return The default time zone type, either <code>TIMEZONE_ICU</code> or
+     * <code>TIMEZONE_JDK</code>.
+     * @stable ICU 4.0
+     */
+    public static int getDefaultTimeZoneType() {
+        return TIMEZONE_JDK;
+    }
+
+    /**
+     * Return a new String array containing all system TimeZone IDs
+     * with the given raw offset from GMT.  These IDs may be passed to
+     * <code>get()</code> to construct the corresponding TimeZone
+     * object.
+     * @param rawOffset the offset in milliseconds from GMT
+     * @return an array of IDs for system TimeZones with the given
+     * raw offset.  If there are none, return a zero-length array.
+     * @stable ICU 2.0
+     */
+    public static String[] getAvailableIDs(int rawOffset) {
+        return java.util.TimeZone.getAvailableIDs(rawOffset);
+
+    }
+
+
+    /**
+     * Return a new String array containing all system TimeZone IDs
+     * associated with the given country.  These IDs may be passed to
+     * <code>get()</code> to construct the corresponding TimeZone
+     * object.
+     * @param country a two-letter ISO 3166 country code, or <code>null</code>
+     * to return zones not associated with any country
+     * @return an array of IDs for system TimeZones in the given
+     * country.  If there are none, return a zero-length array.
+     * @stable ICU 2.0
+     */
+    public static String[] getAvailableIDs(String country) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Return a new String array containing all system TimeZone IDs.
+     * These IDs (and only these IDs) may be passed to
+     * <code>get()</code> to construct the corresponding TimeZone
+     * object.
+     * @return an array of all system TimeZone IDs
+     * @stable ICU 2.0
+     */
+    public static String[] getAvailableIDs() {
+        return java.util.TimeZone.getAvailableIDs();
+    }
+
+    /**
+     * {@icu} Returns the number of IDs in the equivalency group that
+     * includes the given ID.  An equivalency group contains zones
+     * that have the same GMT offset and rules.
+     *
+     * <p>The returned count includes the given ID; it is always >= 1
+     * for valid IDs.  The given ID must be a system time zone.  If it
+     * is not, returns zero.
+     * @param id a system time zone ID
+     * @return the number of zones in the equivalency group containing
+     * 'id', or zero if 'id' is not a valid system ID
+     * @see #getEquivalentID
+     * @stable ICU 2.0
+     */
+    public static int countEquivalentIDs(String id) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Returns an ID in the equivalency group that
+     * includes the given ID.  An equivalency group contains zones
+     * that have the same GMT offset and rules.
+     *
+     * <p>The given index must be in the range 0..n-1, where n is the
+     * value returned by <code>countEquivalentIDs(id)</code>.  For
+     * some value of 'index', the returned value will be equal to the
+     * given id.  If the given id is not a valid system time zone, or
+     * if 'index' is out of range, then returns an empty string.
+     * @param id a system time zone ID
+     * @param index a value from 0 to n-1, where n is the value
+     * returned by <code>countEquivalentIDs(id)</code>
+     * @return the ID of the index-th zone in the equivalency group
+     * containing 'id', or an empty string if 'id' is not a valid
+     * system ID or 'index' is out of range
+     * @see #countEquivalentIDs
+     * @stable ICU 2.0
+     */
+    public static String getEquivalentID(String id, int index) {
+        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
+    }
+
+    /**
+     * Gets the default <code>TimeZone</code> for this host.
+     * The source of the default <code>TimeZone</code>
+     * may vary with implementation.
+     * @return a default <code>TimeZone</code>.
+     * @stable ICU 2.0
+     */
+    public static TimeZone getDefault() {
+        return new TimeZone(java.util.TimeZone.getDefault());
+    }
+
+    /**
+     * Sets the <code>TimeZone</code> that is
+     * returned by the <code>getDefault</code> method.  If <code>zone</code>
+     * is null, reset the default to the value it had originally when the
+     * VM first started.
+     * @param tz the new default time zone
+     * @stable ICU 2.0
+     */
+    public static void setDefault(TimeZone tz) {
+        java.util.TimeZone.setDefault(tz.timeZone);
+    }
+
+    /**
+     * Returns true if this zone has the same rule and offset as another zone.
+     * That is, if this zone differs only in ID, if at all.  Returns false
+     * if the other zone is null.
+     * @param other the <code>TimeZone</code> object to be compared with
+     * @return true if the other zone is not null and is the same as this one,
+     * with the possible exception of the ID
+     * @stable ICU 2.0
+     */
+    public boolean hasSameRules(TimeZone other) {
+        return timeZone.hasSameRules(other.timeZone);
+    }
+
+    /**
+     * Overrides clone.
+     * @stable ICU 2.0
+     */
+    public Object clone() {
+        return new TimeZone((java.util.TimeZone)timeZone.clone());
+    }
+
+    /**
+     * Overrides equals.
+     * @stable ICU 3.6
+     */
+    public boolean equals(Object obj){
+        try {
+            return timeZone.equals(((TimeZone)obj).timeZone);
+        } catch (Exception e) {
+            return false;
+        }
+    }
+
+    /**
+     * Overrides hashCode.
+     * @stable ICU 3.6
+     */
+    public int hashCode(){
+        return timeZone.hashCode();
+    }
+
+    /**
+     * {@icu} Returns the time zone data version currently used by ICU.
+     *
+     * @return the version string, such as "2007f"
+     * @throws MissingResourceException if ICU time zone resource bundle
+     * is missing or the version information is not available.
+     *
+     * @stable ICU 3.8
+     */
+    public static synchronized String getTZDataVersion() {
+        throw new UnsupportedOperationException("Method not supproted by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Returns the canonical system time zone ID or the normalized
+     * custom time zone ID for the given time zone ID.
+     * @param id The input time zone ID to be canonicalized.
+     * @return The canonical system time zone ID or the custom time zone ID
+     * in normalized format for the given time zone ID.  When the given time zone ID
+     * is neither a known system time zone ID nor a valid custom time zone ID,
+     * null is returned.
+     * @stable ICU 4.0
+     */
+    public static String getCanonicalID(String id) {
+        throw new UnsupportedOperationException("Method not supproted by com.ibm.icu.base");
+    }
+
+    /**
+     * {@icu} Returns the canonical system time zone ID or the normalized
+     * custom time zone ID for the given time zone ID.
+     * @param id The input time zone ID to be canonicalized.
+     * @param isSystemID When non-null boolean array is specified and
+     * the given ID is a known system time zone ID, true is set to <code>isSystemID[0]</code>
+     * @return The canonical system time zone ID or the custom time zone ID
+     * in normalized format for the given time zone ID.  When the given time zone ID
+     * is neither a known system time zone ID nor a valid custom time zone ID,
+     * null is returned.
+     * @stable ICU 4.0
+     */
+    public static String getCanonicalID(String id, boolean[] isSystemID) {
+        throw new UnsupportedOperationException("Method not supproted by com.ibm.icu.base");
+    }
+}
+
+//eof
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/ULocale.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/ULocale.java
index 7ffd322..c98b655 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/ULocale.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/ULocale.java
@@ -1,2493 +1,4405 @@
-/*
-******************************************************************************
-* Copyright (C) 2003-2011, International Business Machines Corporation and   *
-* others. All Rights Reserved.                                               *
-******************************************************************************
-*/
-
-package com.ibm.icu.util;
-
-import java.io.Serializable;
-import java.text.ParseException;
-import java.util.Iterator;
-import java.util.Locale;
-import java.util.MissingResourceException;
-import java.util.Set;
-import java.util.TreeMap;
-
-import com.ibm.icu.impl.ICUCache;
-import com.ibm.icu.impl.LocaleIDParser;
-import com.ibm.icu.impl.LocaleIDs;
-import com.ibm.icu.impl.LocaleUtility;
-import com.ibm.icu.impl.SimpleCache;
-import com.ibm.icu.impl.locale.AsciiUtil;
-
-/**
- * {@icuenhanced java.util.Locale}.{@icu _usage_}
- *
- * A class analogous to {@link java.util.Locale} that provides additional
- * support for ICU protocol.  In ICU 3.0 this class is enhanced to support
- * RFC 3066 language identifiers.
- *
- * <p>Many classes and services in ICU follow a factory idiom, in
- * which a factory method or object responds to a client request with
- * an object.  The request includes a locale (the <i>requested</i>
- * locale), and the returned object is constructed using data for that
- * locale.  The system may lack data for the requested locale, in
- * which case the locale fallback mechanism will be invoked until a
- * populated locale is found (the <i>valid</i> locale).  Furthermore,
- * even when a populated locale is found (the <i>valid</i> locale),
- * further fallback may be required to reach a locale containing the
- * specific data required by the service (the <i>actual</i> locale).
- *
- * <p>ULocale performs <b>'normalization'</b> and <b>'canonicalization'</b> of locale ids.
- * Normalization 'cleans up' ICU locale ids as follows:
- * <ul>
- * <li>language, script, country, variant, and keywords are properly cased<br>
- * (lower, title, upper, upper, and lower case respectively)</li>
- * <li>hyphens used as separators are converted to underscores</li>
- * <li>three-letter language and country ids are converted to two-letter
- * equivalents where available</li>
- * <li>surrounding spaces are removed from keywords and values</li>
- * <li>if there are multiple keywords, they are put in sorted order</li>
- * </ul>
- * Canonicalization additionally performs the following:
- * <ul>
- * <li>POSIX ids are converted to ICU format IDs</li>
- * <li>'grandfathered' 3066 ids are converted to ICU standard form</li>
- * <li>'PREEURO' and 'EURO' variants are converted to currency keyword form,
- * with the currency
- * id appropriate to the country of the locale (for PREEURO) or EUR (for EURO).
- * </ul>
- * All ULocale constructors automatically normalize the locale id.  To handle
- * POSIX ids, <code>canonicalize</code> can be called to convert the id
- * to canonical form, or the <code>canonicalInstance</code> factory method
- * can be called.</p>
- *
- * <p>This class provides selectors {@link #VALID_LOCALE} and {@link
- * #ACTUAL_LOCALE} intended for use in methods named
- * <tt>getLocale()</tt>.  These methods exist in several ICU classes,
- * including {@link com.ibm.icu.util.Calendar}, {@link
- * com.ibm.icu.util.Currency}, {@link com.ibm.icu.text.UFormat},
- * {@link com.ibm.icu.text.BreakIterator},
- * <a href="../text/Collator.html" title="class in com.ibm.icu.text"><code>Collator</code></a>,
- * {@link com.ibm.icu.text.DateFormatSymbols}, and {@link
- * com.ibm.icu.text.DecimalFormatSymbols} and their subclasses, if
- * any.  Once an object of one of these classes has been created,
- * <tt>getLocale()</tt> may be called on it to determine the valid and
- * actual locale arrived at during the object's construction.
- *
- * <p>Note: The <i>actual</i> locale is returned correctly, but the <i>valid</i>
- * locale is not, in most cases.
- *
- * @see java.util.Locale
- * @author weiv
- * @author Alan Liu
- * @author Ram Viswanadha
- * @stable ICU 2.8
- */
-public final class ULocale implements Serializable {
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * Useful constant for language.
-     * @stable ICU 3.0
-     */
-    public static final ULocale ENGLISH = new ULocale("en", Locale.ENGLISH);
-
-    /**
-     * Useful constant for language.
-     * @stable ICU 3.0
-     */
-    public static final ULocale FRENCH = new ULocale("fr", Locale.FRENCH);
-
-    /**
-     * Useful constant for language.
-     * @stable ICU 3.0
-     */
-    public static final ULocale GERMAN = new ULocale("de", Locale.GERMAN);
-
-    /**
-     * Useful constant for language.
-     * @stable ICU 3.0
-     */
-    public static final ULocale ITALIAN = new ULocale("it", Locale.ITALIAN);
-
-    /**
-     * Useful constant for language.
-     * @stable ICU 3.0
-     */
-    public static final ULocale JAPANESE = new ULocale("ja", Locale.JAPANESE);
-
-    /**
-     * Useful constant for language.
-     * @stable ICU 3.0
-     */
-    public static final ULocale KOREAN = new ULocale("ko", Locale.KOREAN);
-
-    /**
-     * Useful constant for language.
-     * @stable ICU 3.0
-     */
-    public static final ULocale CHINESE = new ULocale("zh", Locale.CHINESE);
-
-    /**
-     * Useful constant for language.
-     * @stable ICU 3.0
-     */
-    public static final ULocale SIMPLIFIED_CHINESE = new ULocale("zh_Hans", Locale.CHINESE);
-
-    /**
-     * Useful constant for language.
-     * @stable ICU 3.0
-     */
-    public static final ULocale TRADITIONAL_CHINESE = new ULocale("zh_Hant", Locale.CHINESE);
-
-    /**
-     * Useful constant for country/region.
-     * @stable ICU 3.0
-     */
-    public static final ULocale FRANCE = new ULocale("fr_FR", Locale.FRANCE);
-
-    /**
-     * Useful constant for country/region.
-     * @stable ICU 3.0
-     */
-    public static final ULocale GERMANY = new ULocale("de_DE", Locale.GERMANY);
-
-    /**
-     * Useful constant for country/region.
-     * @stable ICU 3.0
-     */
-    public static final ULocale ITALY = new ULocale("it_IT", Locale.ITALY);
-
-    /**
-     * Useful constant for country/region.
-     * @stable ICU 3.0
-     */
-    public static final ULocale JAPAN = new ULocale("ja_JP", Locale.JAPAN);
-
-    /**
-     * Useful constant for country/region.
-     * @stable ICU 3.0
-     */
-    public static final ULocale KOREA = new ULocale("ko_KR", Locale.KOREA);
-
-    /**
-     * Useful constant for country/region.
-     * @stable ICU 3.0
-     */
-    public static final ULocale CHINA = new ULocale("zh_Hans_CN", Locale.CHINA);
-
-    /**
-     * Useful constant for country/region.
-     * @stable ICU 3.0
-     */
-    public static final ULocale PRC = CHINA;
-
-    /**
-     * Useful constant for country/region.
-     * @stable ICU 3.0
-     */
-    public static final ULocale TAIWAN = new ULocale("zh_Hant_TW", Locale.TAIWAN);
-
-    /**
-     * Useful constant for country/region.
-     * @stable ICU 3.0
-     */
-    public static final ULocale UK = new ULocale("en_GB", Locale.UK);
-
-    /**
-     * Useful constant for country/region.
-     * @stable ICU 3.0
-     */
-    public static final ULocale US = new ULocale("en_US", Locale.US);
-
-    /**
-     * Useful constant for country/region.
-     * @stable ICU 3.0
-     */
-    public static final ULocale CANADA = new ULocale("en_CA", Locale.CANADA);
-
-    /**
-     * Useful constant for country/region.
-     * @stable ICU 3.0
-     */
-    public static final ULocale CANADA_FRENCH = new ULocale("fr_CA", Locale.CANADA_FRENCH);
-
-    /**
-     * Handy constant.
-     */
-    private static final String EMPTY_STRING = "";
-
-    // Used in both ULocale and LocaleIDParser, so moved up here.
-    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_LOCALE);
-
-    private static final SimpleCache<Locale, ULocale> CACHE = new SimpleCache<Locale, ULocale>();
-
-    /**
-     * Cache the locale.
-     */
-    private transient volatile Locale locale;
-
-    /**
-     * The raw localeID that we were passed in.
-     */
-    private String localeID;
-
-    private static String[][] CANONICALIZE_MAP;
-    private static String[][] variantsToKeywords;
-
-    private static void initCANONICALIZE_MAP() {
-        if (CANONICALIZE_MAP == null) {
-            /**
-             * This table lists pairs of locale ids for canonicalization.  The
-             * 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[][] 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 */
-                { "az_AZ_CYRL",     "az_Cyrl_AZ", null, null }, /* .NET name */
-                { "az_AZ_LATN",     "az_Latn_AZ", null, null }, /* .NET name */
-                { "ca_ES_PREEURO",  "ca_ES", "currency", "ESP" },
-                { "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" }, /* Old ICU name */
-                { "de_AT_PREEURO",  "de_AT", "currency", "ATS" },
-                { "de_DE_PREEURO",  "de_DE", "currency", "DEM" },
-                { "de_LU_PREEURO",  "de_LU", "currency", "EUR" },
-                { "el_GR_PREEURO",  "el_GR", "currency", "GRD" },
-                { "en_BOONT",       "en__BOONT", null, null }, /* registered name */
-                { "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" }, /* Old ICU name */
-                { "es_ES_PREEURO",  "es_ES", "currency", "ESP" },
-                { "eu_ES_PREEURO",  "eu_ES", "currency", "ESP" },
-                { "fi_FI_PREEURO",  "fi_FI", "currency", "FIM" },
-                { "fr_BE_PREEURO",  "fr_BE", "currency", "BEF" },
-                { "fr_FR_PREEURO",  "fr_FR", "currency", "FRF" },
-                { "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" }, /* Old ICU name */
-                { "it_IT_PREEURO",  "it_IT", "currency", "ITL" },
-                { "ja_JP_TRADITIONAL", "ja_JP", "calendar", "japanese" },
-//              { "nb_NO_NY",       "nn_NO", null, null },
-                { "nl_BE_PREEURO",  "nl_BE", "currency", "BEF" },
-                { "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_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 */
-                { "zh_CHT",         "zh_Hant", null, null }, /* .NET name */
-                { "zh_GAN",         "zh__GAN", null, null }, /* registered name */
-                { "zh_GUOYU",       "zh", null, null }, /* registered name */
-                { "zh_HAKKA",       "zh__HAKKA", null, null }, /* registered name */
-                { "zh_MIN",         "zh__MIN", null, null }, /* registered name */
-                { "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 */
-            };
-
-            synchronized (ULocale.class) {
-                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",    "numbers",  "thai",     "th"},
-    };
-
-    /**
-     * Private constructor used by static initializers.
-     */
-    private ULocale(String localeID, Locale locale) {
-        this.localeID = localeID;
-        this.locale = locale;
-    }
-
-    /**
-     * Construct a ULocale object from a {@link java.util.Locale}.
-     * @param loc a JDK locale
-     */
-    private ULocale(Locale loc) {
-        this.localeID = getName(forLocale(loc).toString());
-        this.locale = loc;
-    }
-
-    /**
-     * {@icu} Returns a ULocale object for a {@link java.util.Locale}.
-     * The ULocale is canonicalized.
-     * @param loc a JDK locale
-     * @stable ICU 3.2
-     */
-    public static ULocale forLocale(Locale loc) {
-        if (loc == null) {
-            return null;
-        }
-        ULocale result = CACHE.get(loc);
-        if (result == null) {
-            if (defaultULocale != null && loc == defaultULocale.locale) {
-            result = defaultULocale;
-        } else {
-                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)) {
-                            LocaleIDParser p = new LocaleIDParser(_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;
-    }
-
-    /**
-     * {@icu} Constructs a ULocale from a RFC 3066 locale ID. The locale ID consists
-     * of optional language, script, country, and variant fields in that order,
-     * separated by underscores, followed by an optional keyword list.  The
-     * 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 two
-     * or more keyword/value pairs separated by semicolons(';').
-     * 
-     * <p>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"
-     * @stable ICU 2.8
-     */
-    public ULocale(String localeID) {
-        this.localeID = getName(localeID);
-    }
-
-    /**
-     * Convenience overload of ULocale(String, String, String) for
-     * compatibility with java.util.Locale.
-     * @see #ULocale(String, String, String)
-     * @stable ICU 3.4
-     */
-    public ULocale(String a, String b) {
-        this(a, b, null);
-    }
-
-    /**
-     * Constructs a ULocale from a localeID constructed from the three 'fields' a, b, and
-     * c.  These fields are concatenated using underscores to form a localeID of the form
-     * a_b_c, which is then handled like the localeID passed to <code>ULocale(String
-     * localeID)</code>.
-     *
-     * <p>Java locale strings consisting of language, country, and
-     * variant will be handled by this form, since the country code
-     * (being shorter than four letters long) will not be interpreted
-     * as a script code.  If a script code is present, the final
-     * argument ('c') will be interpreted as the country code.  It is
-     * recommended that this constructor only be used to ease porting,
-     * and that clients instead use the single-argument constructor
-     * when constructing a ULocale from a localeID.
-     * @param a first component of the locale id
-     * @param b second component of the locale id
-     * @param c third component of the locale id
-     * @see #ULocale(String)
-     * @stable ICU 3.0
-     */
-    public ULocale(String a, String b, String c) {
-        localeID = getName(lscvToID(a, b, c, EMPTY_STRING));
-    }
-
-    /**
-     * {@icu} Creates a ULocale from the id by first canonicalizing the id.
-     * @param nonCanonicalID the locale id to canonicalize
-     * @return the locale created from the canonical version of the ID.
-     * @stable ICU 3.0
-     */
-    public static ULocale createCanonical(String nonCanonicalID) {
-        return new ULocale(canonicalize(nonCanonicalID), (Locale)null);
-    }
-
-    private static String lscvToID(String lang, String script, String country, String variant) {
-        StringBuilder buf = new StringBuilder();
-
-        if (lang != null && lang.length() > 0) {
-            buf.append(lang);
-        }
-        if (script != null && script.length() > 0) {
-            buf.append(UNDERSCORE);
-            buf.append(script);
-        }
-        if (country != null && country.length() > 0) {
-            buf.append(UNDERSCORE);
-            buf.append(country);
-        }
-        if (variant != null && variant.length() > 0) {
-            if (country == null || country.length() == 0) {
-                buf.append(UNDERSCORE);
-            }
-            buf.append(UNDERSCORE);
-            buf.append(variant);
-        }
-        return buf.toString();
-    }
-
-    /**
-     * {@icu} Converts this ULocale object to a {@link java.util.Locale}.
-     * @return a JDK locale that either exactly represents this object
-     * or is the closest approximation.
-     * @stable ICU 2.8
-     */
-    public Locale toLocale() {
-        if (locale == null) {
-            LocaleIDParser p = new LocaleIDParser(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 LocaleIDParser(_javaLocaleMap[i][0]);
-                            break;
-                        }
-                    } else {
-                        p = new LocaleIDParser(_javaLocaleMap[i][0]);
-                        break;
-                    }
-                }
-            }
-            String[] names = p.getLanguageScriptCountryVariant();
-            locale = new Locale(names[0], names[2], names[3]);
-        }
-        return locale;
-    }
-
-    private static ICUCache<String, String> nameCache = new SimpleCache<String, String>();
-    /**
-     * Keep our own default ULocale.
-     */
-    private static Locale defaultLocale = Locale.getDefault();
-    private static ULocale defaultULocale = new ULocale(defaultLocale);
-
-    /**
-     * Returns the current default ULocale.
-     * @stable ICU 2.8
-     */
-    public static ULocale getDefault() {
-        synchronized (ULocale.class) {
-            Locale currentDefault = Locale.getDefault();
-            if (!defaultLocale.equals(currentDefault)) {
-                defaultLocale = currentDefault;
-                defaultULocale = new ULocale(defaultLocale);
-            }
-            return defaultULocale;
-        }
-    }
-
-    /**
-     * {@icu} Sets the default ULocale.  This also sets the default Locale.
-     * If the caller does not have write permission to the
-     * user.language property, a security exception will be thrown,
-     * and the default ULocale will remain unchanged.
-     * @param newLocale the new default locale
-     * @throws SecurityException 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(java.security.Permission)
-     * @see java.util.PropertyPermission
-     * @stable ICU 3.0
-     */
-    public static synchronized void setDefault(ULocale newLocale){
-        Locale.setDefault(newLocale.toLocale());
-        defaultULocale = newLocale;
-    }
-
-    /**
-     * This is for compatibility with Locale-- in actuality, since ULocale is
-     * immutable, there is no reason to clone it, so this API returns 'this'.
-     * @stable ICU 3.0
-     */
-    public Object clone() {
-        return this;
-    }
-
-    /**
-     * Returns the hashCode.
-     * @stable ICU 3.0
-     */
-    public int hashCode() {
-        return localeID.hashCode();
-    }
-
-    /**
-     * Returns true if the other object is another ULocale with the
-     * same full name, or is a String localeID that matches the full name.
-     * Note that since names are not canonicalized, two ULocales that
-     * function identically might not compare equal.
-     *
-     * @return true if this Locale is equal to the specified object.
-     * @stable ICU 3.0
-     */
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj instanceof String) {
-            return localeID.equals((String)obj);
-        }
-        if (obj instanceof ULocale) {
-            return localeID.equals(((ULocale)obj).localeID);
-        }
-        return false;
-    }
-
-    /**
-     * {@icunote} Unlike the Locale API, this returns an array of <code>ULocale</code>,
-     * not <code>Locale</code>.  Returns a list of all installed locales.
-     * @stable ICU 3.0
-     */
-    public static ULocale[] getAvailableLocales() {
-        if (availableLocales == null) {
-            synchronized (ULocale.class) {
-                if (availableLocales == null) {
-                    Locale[] locales = Locale.getAvailableLocales();
-                    availableLocales = new ULocale[locales.length];
-                    for (int i = 0; i < locales.length; i++) {
-                        availableLocales[i] = ULocale.forLocale(locales[i]);
-                    }
-                }
-            }
-        }
-        return availableLocales.clone();
-    }
-    private static volatile ULocale[] availableLocales = null;
-
-    /**
-     * Returns a list of all 2-letter country codes defined in ISO 3166.
-     * Can be used to create Locales.
-     * @stable ICU 3.0
-     */
-    public static String[] getISOCountries() {
-        return LocaleIDs.getISOCountries();
-    }
-
-    /**
-     * Returns a list of all 2-letter language codes defined in ISO 639.
-     * Can be used to create Locales.
-     * [NOTE:  ISO 639 is not a stable standard-- some languages' codes have changed.
-     * The list this function returns includes both the new and the old codes for the
-     * languages whose codes have changed.]
-     * @stable ICU 3.0
-     */
-    public static String[] getISOLanguages() {
-        return LocaleIDs.getISOLanguages();
-    }
-
-    /**
-     * Returns the language code for this locale, which will either be the empty string
-     * or a lowercase ISO 639 code.
-     * @see #getDisplayLanguage()
-     * @see #getDisplayLanguage(ULocale)
-     * @stable ICU 3.0
-     */
-    public String getLanguage() {
-        return getLanguage(localeID);
-    }
-
-    /**
-     * 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(ULocale)
-     * @stable ICU 3.0
-     */
-    public static String getLanguage(String localeID) {
-        return new LocaleIDParser(localeID).getLanguage();
-    }
-
-    /**
-     * {@icu} Returns the script code for this locale, which might be the empty string.
-     * @see #getDisplayScript()
-     * @see #getDisplayScript(ULocale)
-     * @stable ICU 3.0
-     */
-    public String getScript() {
-        return getScript(localeID);
-    }
-
-    /**
-     * {@icu} Returns the script code for the specified locale, which might be the empty
-     * string.
-     * @see #getDisplayScript()
-     * @see #getDisplayScript(ULocale)
-     * @stable ICU 3.0
-     */
-    public static String getScript(String localeID) {
-        return new LocaleIDParser(localeID).getScript();
-    }
-
-    /**
-     * 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(ULocale)
-     * @stable ICU 3.0
-     */
-    public String getCountry() {
-        return getCountry(localeID);
-    }
-
-    /**
-     * 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 The locale identification string.
-     * @see #getDisplayCountry()
-     * @see #getDisplayCountry(ULocale)
-     * @stable ICU 3.0
-     */
-    public static String getCountry(String localeID) {
-        return new LocaleIDParser(localeID).getCountry();
-    }
-
-    /**
-     * Returns the variant code for this locale, which might be the empty string.
-     * @see #getDisplayVariant()
-     * @see #getDisplayVariant(ULocale)
-     * @stable ICU 3.0
-     */
-    public String getVariant() {
-        return getVariant(localeID);
-    }
-
-    /**
-     * Returns the variant code for the specified locale, which might be the empty string.
-     * @see #getDisplayVariant()
-     * @see #getDisplayVariant(ULocale)
-     * @stable ICU 3.0
-     */
-    public static String getVariant(String localeID) {
-        return new LocaleIDParser(localeID).getVariant();
-    }
-
-    /**
-     * {@icu} Returns the fallback locale for the specified locale, which might be the
-     * empty string.
-     * @stable ICU 3.2
-     */
-    public static String getFallback(String localeID) {
-        return getFallbackString(getName(localeID));
-    }
-
-    /**
-     * {@icu} Returns the fallback locale for this locale.  If this locale is root,
-     * returns null.
-     * @stable ICU 3.2
-     */
-    public ULocale getFallback() {
-        if (localeID.length() == 0 || localeID.charAt(0) == '@') {
-            return null;
-        }
-        return new ULocale(getFallbackString(localeID), (Locale)null);
-    }
-
-    /**
-     * Returns the given (canonical) locale id minus the last part before the tags.
-     */
-    private static String getFallbackString(String fallback) {
-        int extStart = fallback.indexOf('@');
-        if (extStart == -1) {
-            extStart = fallback.length();
-        }
-        int last = fallback.lastIndexOf('_', extStart);
-        if (last == -1) {
-            last = 0;
-        } else {
-            // truncate empty segment
-            while (last > 0) {
-                if (fallback.charAt(last - 1) != '_') {
-                    break;
-                }
-                last--;
-            }
-        }
-        return fallback.substring(0, last) + fallback.substring(extStart);
-    }
-
-    /**
-     * {@icu} Returns the (normalized) base name for this locale.
-     * @return the base name as a String.
-     * @stable ICU 3.0
-     */
-    public String getBaseName() {
-        return getBaseName(localeID);
-    }
-
-    /**
-     * {@icu} Returns the (normalized) base name for the specified locale.
-     * @param localeID the locale ID as a string
-     * @return the base name as a String.
-     * @stable ICU 3.0
-     */
-    public static String getBaseName(String localeID){
-        if (localeID.indexOf('@') == -1) {
-            return localeID;
-        }
-        return new LocaleIDParser(localeID).getBaseName();
-    }
-
-    /**
-     * {@icu} Returns the (normalized) full name for this locale.
-     *
-     * @return String the full name of the localeID
-     * @stable ICU 3.0
-     */
-    public String getName() {
-        return localeID; // always normalized
-    }
-
-    /**
-     * {@icu} Returns the (normalized) full name for the specified locale.
-     *
-     * @param localeID the localeID as a string
-     * @return String the full name of the localeID
-     * @stable ICU 3.0
-     */
-    public static String getName(String localeID){
-        String name = nameCache.get(localeID);
-        if (name == null) {
-            name = new LocaleIDParser(localeID).getName();
-            nameCache.put(localeID, name);
-        }
-        return name;
-    }
-
-    /**
-     * Returns a string representation of this object.
-     * @stable ICU 3.0
-     */
-    public String toString() {
-        return localeID;
-    }
-
-    /**
-     * {@icu} Returns an iterator over keywords for this locale.  If there
-     * are no keywords, returns null.
-     * @return iterator over keywords, or null if there are no keywords.
-     * @stable ICU 3.0
-     */
-    public Iterator<String> getKeywords() {
-        return getKeywords(localeID);
-    }
-
-    /**
-     * {@icu} Returns an iterator over keywords for the specified locale.  If there
-     * are no keywords, returns null.
-     * @return an iterator over the keywords in the specified locale, or null
-     * if there are no keywords.
-     * @stable ICU 3.0
-     */
-    public static Iterator<String> getKeywords(String localeID){
-        return new LocaleIDParser(localeID).getKeywords();
-    }
-
-    /**
-     * {@icu} Returns the value for a keyword in this locale. If the keyword is not
-     * defined, returns null.
-     * @param keywordName name of the keyword whose value is desired. Case insensitive.
-     * @return the value of the keyword, or null.
-     * @stable ICU 3.0
-     */
-    public String getKeywordValue(String keywordName){
-        return getKeywordValue(localeID, keywordName);
-    }
-
-    /**
-     * {@icu} Returns the value for a keyword in the specified locale. If the keyword is
-     * not defined, returns null.  The locale name does not need to be normalized.
-     * @param keywordName name of the keyword whose value is desired. Case insensitive.
-     * @return String the value of the keyword as a string
-     * @stable ICU 3.0
-     */
-    public static String getKeywordValue(String localeID, String keywordName) {
-        return new LocaleIDParser(localeID).getKeywordValue(keywordName);
-    }
-
-    /**
-     * {@icu} Returns the canonical name for the specified locale ID.  This is used to
-     * convert POSIX and other grandfathered IDs to standard ICU form.
-     * @param localeID the locale id
-     * @return the canonicalized id
-     * @stable ICU 3.0
-     */
-    public static String canonicalize(String localeID){
-        LocaleIDParser parser = new LocaleIDParser(localeID, true);
-        String baseName = parser.getBaseName();
-        boolean foundVariant = false;
-
-        // formerly, we always set to en_US_POSIX if the basename was empty, but
-        // now we require that the entire id be empty, so that "@foo=bar"
-        // will pass through unchanged.
-        // {dlf} I'd rather keep "" unchanged.
-        if (localeID.equals("")) {
-            return "";
-//              return "en_US_POSIX";
-        }
-
-        // we have an ID in the form xx_Yyyy_ZZ_KKKKK
-
-        initCANONICALIZE_MAP();
-
-        /* 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;
-
-                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]);
-                }
-                break;
-            }
-        }
-
-        /* total mondo hack for Norwegian, fortunately the main NY case is handled earlier */
-        if (!foundVariant) {
-            if (parser.getLanguage().equals("nb") && parser.getVariant().equals("NY")) {
-                parser.setBaseName(lscvToID("nn", parser.getScript(), parser.getCountry(), null));
-            }
-        }
-
-        return parser.getName();
-    }
-
-    /**
-     * Given a keyword and a value, return a new locale with an updated
-     * keyword and value.  If keyword is null, this removes all keywords from the locale id.
-     * Otherwise, if the value is null, this removes the value for this keyword from the
-     * locale id.  Otherwise, this adds/replaces the value for this keyword in the locale id.
-     * The keyword and value must not be empty.
-     * @param keyword the keyword to add/remove, or null to remove all keywords.
-     * @param value the value to add/set, or null to remove this particular keyword.
-     * @return the updated locale
-     * @stable ICU 3.2
-     */
-    public ULocale setKeywordValue(String keyword, String value) {
-        return new ULocale(setKeywordValue(localeID, keyword, value), (Locale)null);
-    }
-
-    /**
-     * Given a locale id, a keyword, and a value, return a new locale id with an updated
-     * keyword and value.  If keyword is null, this removes all keywords from the locale id.
-     * Otherwise, if the value is null, this removes the value for this keyword from the
-     * locale id.  Otherwise, this adds/replaces the value for this keyword in the locale id.
-     * The keyword and value must not be empty.
-     * @param localeID the locale id to modify
-     * @param keyword the keyword to add/remove, or null to remove all keywords.
-     * @param value the value to add/set, or null to remove this particular keyword.
-     * @return the updated locale id
-     * @stable ICU 3.2
-     */
-    public static String setKeywordValue(String localeID, String keyword, String value) {
-        LocaleIDParser parser = new LocaleIDParser(localeID);
-        parser.setKeywordValue(keyword, value);
-        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
-     */
-/*    private static String defaultKeywordValue(String localeID, String keyword, String value) {
-        LocaleIDParser parser = new LocaleIDParser(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
-     * a lowercase ISO 639-2/T language code.
-     * The ISO 639-2 language codes can be found on-line at
-     *   <a href="ftp://dkuug.dk/i18n/iso-639-2.txt"><code>ftp://dkuug.dk/i18n/iso-639-2.txt</code></a>
-     * @exception MissingResourceException Throws MissingResourceException if the
-     * three-letter language abbreviation is not available for this locale.
-     * @stable ICU 3.0
-     */
-    public String getISO3Language(){
-        return getISO3Language(localeID);
-    }
-
-    /**
-     * Returns a three-letter abbreviation for this locale's language.  If the locale
-     * doesn't specify a language, returns the empty string.  Otherwise, returns
-     * a lowercase ISO 639-2/T language code.
-     * The ISO 639-2 language codes can be found on-line at
-     *   <a href="ftp://dkuug.dk/i18n/iso-639-2.txt"><code>ftp://dkuug.dk/i18n/iso-639-2.txt</code></a>
-     * @exception MissingResourceException Throws MissingResourceException if the
-     * three-letter language abbreviation is not available for this locale.
-     * @stable ICU 3.0
-     */
-    public static String getISO3Language(String localeID) {
-        return LocaleIDs.getISO3Language(getLanguage(localeID));
-    }
-
-    /**
-     * Returns a three-letter abbreviation for this locale's country/region.  If the locale
-     * doesn't specify a country, returns the empty string.  Otherwise, returns
-     * an uppercase ISO 3166 3-letter country code.
-     * @exception MissingResourceException Throws MissingResourceException if the
-     * three-letter country abbreviation is not available for this locale.
-     * @stable ICU 3.0
-     */
-    public String getISO3Country() {
-        return getISO3Country(localeID);
-    }
-
-    /**
-     * Returns a three-letter abbreviation for this locale's country/region.  If the locale
-     * doesn't specify a country, returns the empty string.  Otherwise, returns
-     * an uppercase ISO 3166 3-letter country code.
-     * @exception MissingResourceException Throws MissingResourceException if the
-     * three-letter country abbreviation is not available for this locale.
-     * @stable ICU 3.0
-     */
-    public static String getISO3Country(String localeID) {
-        return LocaleIDs.getISO3Country(getCountry(localeID));
-    }
-
-    // display names
-
-    /**
-     * 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 getDisplayLanguageInternal(this, getDefault(), false);
-    }
-
-    /**
-     * {@icu} Returns this locale's language localized for display in the provided locale.
-     * @param displayLocale the locale in which to display the name.
-     * @return the localized language name.
-     * @stable ICU 3.0
-     */
-    public String getDisplayLanguage(ULocale displayLocale) {
-        return getDisplayLanguageInternal(this, displayLocale, false);
-    }
-
-    /**
-     * Returns a locale's language localized for display in the provided locale.
-     * This is a cover for the ICU4C API.
-     * @param localeID the id of the locale whose language will be displayed
-     * @param displayLocaleID the id of the locale in which to display the name.
-     * @return the localized language name.
-     * @stable ICU 3.0
-     */
-    public static String getDisplayLanguage(String localeID, String displayLocaleID) {
-        return getDisplayLanguageInternal(new ULocale(localeID), new ULocale(displayLocaleID),
-                false);
-    }
-
-    /**
-     * Returns a locale's language localized for display in the provided locale.
-     * This is a cover for the ICU4C API.
-     * @param localeID the id of the locale whose language will be displayed.
-     * @param displayLocale the locale in which to display the name.
-     * @return the localized language name.
-     * @stable ICU 3.0
-     */
-    public static String getDisplayLanguage(String localeID, ULocale displayLocale) {
-        return getDisplayLanguageInternal(new ULocale(localeID), displayLocale, false);
-    }
-    /**
-     * {@icu} Returns this locale's language localized for display in the default locale.
-     * If a dialect name is present in the data, then it is returned.
-     * @return the localized language name.
-     * @draft ICU 4.4
-     * @provisional This API might change or be removed in a future release.
-     */
-    public String getDisplayLanguageWithDialect() {
-        return getDisplayLanguageInternal(this, getDefault(), true);
-    }
-
-    /**
-     * {@icu} Returns this locale's language localized for display in the provided locale.
-     * If a dialect name is present in the data, then it is returned.
-     * @param displayLocale the locale in which to display the name.
-     * @return the localized language name.
-     * @draft ICU 4.4
-     * @provisional This API might change or be removed in a future release.
-     */
-    public String getDisplayLanguageWithDialect(ULocale displayLocale) {
-        return getDisplayLanguageInternal(this, displayLocale, true);
-    }
-
-    /**
-     * {@icu} Returns a locale's language localized for display in the provided locale.
-     * If a dialect name is present in the data, then it is returned.
-     * This is a cover for the ICU4C API.
-     * @param localeID the id of the locale whose language will be displayed
-     * @param displayLocaleID the id of the locale in which to display the name.
-     * @return the localized language name.
-     * @draft ICU 4.4
-     * @provisional This API might change or be removed in a future release.
-     */
-    public static String getDisplayLanguageWithDialect(String localeID, String displayLocaleID) {
-        return getDisplayLanguageInternal(new ULocale(localeID), new ULocale(displayLocaleID),
-                true);
-    }
-
-    /**
-     * {@icu} Returns a locale's language localized for display in the provided locale.
-     * If a dialect name is present in the data, then it is returned.
-     * This is a cover for the ICU4C API.
-     * @param localeID the id of the locale whose language will be displayed.
-     * @param displayLocale the locale in which to display the name.
-     * @return the localized language name.
-     * @draft ICU 4.4
-     * @provisional This API might change or be removed in a future release.
-     */
-    public static String getDisplayLanguageWithDialect(String localeID, ULocale displayLocale) {
-        return getDisplayLanguageInternal(new ULocale(localeID), displayLocale, true);
-    }
-
-    private static String getDisplayLanguageInternal(ULocale locale, ULocale displayLocale,
-            boolean useDialect) {
-        // No dialect support
-        return locale.toLocale().getDisplayLanguage(displayLocale.toLocale());
-    }
-
-    /**
-     * {@icu} 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 getDisplayScriptInternal(this, getDefault());
-    }
-
-    /**
-     * {@icu} Returns this locale's script localized for display in the provided locale.
-     * @param displayLocale the locale in which to display the name.
-     * @return the localized script name.
-     * @stable ICU 3.0
-     */
-    public String getDisplayScript(ULocale displayLocale) {
-        return getDisplayScriptInternal(this, displayLocale);
-    }
-
-    /**
-     * {@icu} Returns a locale's script localized for display in the provided locale.
-     * This is a cover for the ICU4C API.
-     * @param localeID the id of the locale whose script will be displayed
-     * @param displayLocaleID the id of the locale in which to display the name.
-     * @return the localized script name.
-     * @stable ICU 3.0
-     */
-    public static String getDisplayScript(String localeID, String displayLocaleID) {
-        return getDisplayScriptInternal(new ULocale(localeID), new ULocale(displayLocaleID));
-    }
-
-    /**
-     * {@icu} Returns a locale's script localized for display in the provided locale.
-     * @param localeID the id of the locale whose script will be displayed.
-     * @param displayLocale the locale in which to display the name.
-     * @return the localized script name.
-     * @stable ICU 3.0
-     */
-    public static String getDisplayScript(String localeID, ULocale displayLocale) {
-        return getDisplayScriptInternal(new ULocale(localeID), displayLocale);
-    }
-
-    // displayLocaleID is canonical, localeID need not be since parsing will fix this.
-    private static String getDisplayScriptInternal(ULocale locale, ULocale displayLocale) {
-        // No localization, just return the script code
-        return locale.getScript();
-    }
-
-    /**
-     * Returns this locale's country localized for display in the default locale.
-     * @return the localized country name.
-     * @stable ICU 3.0
-     */
-    public String getDisplayCountry() {
-        return getDisplayCountryInternal(this, getDefault());
-    }
-
-    /**
-     * Returns this locale's country localized for display in the provided locale.
-     * @param displayLocale the locale in which to display the name.
-     * @return the localized country name.
-     * @stable ICU 3.0
-     */
-    public String getDisplayCountry(ULocale displayLocale){
-        return getDisplayCountryInternal(this, displayLocale);
-    }
-
-    /**
-     * Returns a locale's country localized for display in the provided locale.
-     * This is a cover for the ICU4C API.
-     * @param localeID the id of the locale whose country will be displayed
-     * @param displayLocaleID the id of the locale in which to display the name.
-     * @return the localized country name.
-     * @stable ICU 3.0
-     */
-    public static String getDisplayCountry(String localeID, String displayLocaleID) {
-        return getDisplayCountryInternal(new ULocale(localeID), new ULocale(displayLocaleID));
-    }
-
-    /**
-     * Returns a locale's country localized for display in the provided locale.
-     * This is a cover for the ICU4C API.
-     * @param localeID the id of the locale whose country will be displayed.
-     * @param displayLocale the locale in which to display the name.
-     * @return the localized country name.
-     * @stable ICU 3.0
-     */
-    public static String getDisplayCountry(String localeID, ULocale displayLocale) {
-        return getDisplayCountryInternal(new ULocale(localeID), displayLocale);
-    }
-
-    // displayLocaleID is canonical, localeID need not be since parsing will fix this.
-    private static String getDisplayCountryInternal(ULocale locale, ULocale displayLocale) {
-        return locale.toLocale().getDisplayCountry(displayLocale.toLocale());
-    }
-
-    /**
-     * 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 getDisplayVariantInternal(this, getDefault());
-    }
-
-    /**
-     * Returns this locale's variant localized for display in the provided locale.
-     * @param displayLocale the locale in which to display the name.
-     * @return the localized variant name.
-     * @stable ICU 3.0
-     */
-    public String getDisplayVariant(ULocale displayLocale) {
-        return getDisplayVariantInternal(this, displayLocale);
-    }
-
-    /**
-     * Returns a locale's variant localized for display in the provided locale.
-     * This is a cover for the ICU4C API.
-     * @param localeID the id of the locale whose variant will be displayed
-     * @param displayLocaleID the id of the locale in which to display the name.
-     * @return the localized variant name.
-     * @stable ICU 3.0
-     */
-    public static String getDisplayVariant(String localeID, String displayLocaleID){
-        return getDisplayVariantInternal(new ULocale(localeID), new ULocale(displayLocaleID));
-    }
-
-    /**
-     * Returns a locale's variant localized for display in the provided locale.
-     * This is a cover for the ICU4C API.
-     * @param localeID the id of the locale whose variant will be displayed.
-     * @param displayLocale the locale in which to display the name.
-     * @return the localized variant name.
-     * @stable ICU 3.0
-     */
-    public static String getDisplayVariant(String localeID, ULocale displayLocale) {
-        return getDisplayVariantInternal(new ULocale(localeID), displayLocale);
-    }
-
-    private static String getDisplayVariantInternal(ULocale locale, ULocale displayLocale) {
-        return locale.toLocale().getDisplayVariant(displayLocale.toLocale());
-    }
-
-    /**
-     * {@icu} Returns a keyword localized for display in the default locale.
-     * @param keyword the keyword to be displayed.
-     * @return the localized keyword name.
-     * @see #getKeywords()
-     * @stable ICU 3.0
-     */
-    public static String getDisplayKeyword(String keyword) {
-        return getDisplayKeywordInternal(keyword, getDefault());
-    }
-
-    /**
-     * {@icu} Returns a keyword localized for display in the specified locale.
-     * @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(String)
-     * @stable ICU 3.0
-     */
-    public static String getDisplayKeyword(String keyword, String displayLocaleID) {
-        return getDisplayKeywordInternal(keyword, new ULocale(displayLocaleID));
-    }
-
-    /**
-     * {@icu} Returns a keyword localized for display in the specified locale.
-     * @param keyword the keyword to be displayed.
-     * @param displayLocale the locale in which to display the keyword.
-     * @return the localized keyword name.
-     * @see #getKeywords(String)
-     * @stable ICU 3.0
-     */
-    public static String getDisplayKeyword(String keyword, ULocale displayLocale) {
-        return getDisplayKeywordInternal(keyword, displayLocale);
-    }
-
-    private static String getDisplayKeywordInternal(String keyword, ULocale displayLocale) {
-        // No localization
-        return keyword;
-    }
-
-    /**
-     * {@icu} Returns a keyword value localized for display in the default locale.
-     * @param keyword the keyword whose value is to be displayed.
-     * @return the localized value name.
-     * @stable ICU 3.0
-     */
-    public String getDisplayKeywordValue(String keyword) {
-        return getDisplayKeywordValueInternal(this, keyword, getDefault());
-    }
-
-    /**
-     * {@icu} Returns a keyword value localized for display in the specified locale.
-     * @param keyword the keyword whose value is to be displayed.
-     * @param displayLocale the locale in which to display the value.
-     * @return the localized value name.
-     * @stable ICU 3.0
-     */
-    public String getDisplayKeywordValue(String keyword, ULocale displayLocale) {
-        return getDisplayKeywordValueInternal(this, keyword, displayLocale);
-    }
-
-    /**
-     * {@icu} Returns a keyword value localized for display in the specified locale.
-     * This is a cover for the ICU4C API.
-     * @param localeID the id of the locale whose keyword value is to be displayed.
-     * @param keyword the keyword whose value is to be displayed.
-     * @param displayLocaleID the id of the locale in which to display the value.
-     * @return the localized value name.
-     * @stable ICU 3.0
-     */
-    public static String getDisplayKeywordValue(String localeID, String keyword,
-            String displayLocaleID) {
-        return getDisplayKeywordValueInternal(new ULocale(localeID), keyword,
-                new ULocale(displayLocaleID));
-    }
-
-    /**
-     * {@icu} Returns a keyword value localized for display in the specified locale.
-     * This is a cover for the ICU4C API.
-     * @param localeID the id of the locale whose keyword value is to be displayed.
-     * @param keyword the keyword whose value is to be displayed.
-     * @param displayLocale the id of the locale in which to display the value.
-     * @return the localized value name.
-     * @stable ICU 3.0
-     */
-    public static String getDisplayKeywordValue(String localeID, String keyword,
-            ULocale displayLocale) {
-        return getDisplayKeywordValueInternal(new ULocale(localeID), keyword, displayLocale);
-    }
-
-    // displayLocaleID is canonical, localeID need not be since parsing will fix this.
-    private static String getDisplayKeywordValueInternal(ULocale locale, String keyword,
-            ULocale displayLocale) {
-        keyword = AsciiUtil.toLowerString(keyword.trim());
-        String value = locale.getKeywordValue(keyword);
-        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(this, getDefault());
-    }
-
-    /**
-     * Returns this locale name localized for display in the provided locale.
-     * @param displayLocale the locale in which to display the locale name.
-     * @return the localized locale name.
-     * @stable ICU 3.0
-     */
-    public String getDisplayName(ULocale displayLocale) {
-        return getDisplayNameInternal(this, displayLocale);
-    }
-
-    /**
-     * Returns the locale ID localized for display in the provided locale.
-     * This is a cover for the ICU4C API.
-     * @param localeID the locale whose name is to be displayed.
-     * @param displayLocaleID the id of the locale in which to display the locale name.
-     * @return the localized locale name.
-     * @stable ICU 3.0
-     */
-    public static String getDisplayName(String localeID, String displayLocaleID) {
-        return getDisplayNameInternal(new ULocale(localeID), new ULocale(displayLocaleID));
-    }
-
-    /**
-     * Returns the locale ID localized for display in the provided locale.
-     * This is a cover for the ICU4C API.
-     * @param localeID the locale whose name is to be displayed.
-     * @param displayLocale the locale in which to display the locale name.
-     * @return the localized locale name.
-     * @stable ICU 3.0
-     */
-    public static String getDisplayName(String localeID, ULocale displayLocale) {
-        return getDisplayNameInternal(new ULocale(localeID), displayLocale);
-    }
-
-    private static String getDisplayNameInternal(ULocale locale, ULocale displayLocale) {
-        // No localization, no script and keywords
-        return locale.toLocale().getDisplayName(displayLocale.toLocale());
-    }
-
-    /**
-     * {@icu} Returns this locale name localized for display in the default locale.
-     * If a dialect name is present in the locale data, then it is returned.
-     * @return the localized locale name.
-     * @draft ICU 4.4
-     * @provisional This API might change or be removed in a future release.
-     */
-    public String getDisplayNameWithDialect() {
-        return getDisplayNameWithDialectInternal(this, getDefault());
-    }
-
-    /**
-     * {@icu} Returns this locale name localized for display in the provided locale.
-     * If a dialect name is present in the locale data, then it is returned.
-     * @param displayLocale the locale in which to display the locale name.
-     * @return the localized locale name.
-     * @draft ICU 4.4
-     * @provisional This API might change or be removed in a future release.
-     */
-    public String getDisplayNameWithDialect(ULocale displayLocale) {
-        return getDisplayNameWithDialectInternal(this, displayLocale);
-    }
-
-    /**
-     * {@icu} Returns the locale ID localized for display in the provided locale.
-     * If a dialect name is present in the locale data, then it is returned.
-     * This is a cover for the ICU4C API.
-     * @param localeID the locale whose name is to be displayed.
-     * @param displayLocaleID the id of the locale in which to display the locale name.
-     * @return the localized locale name.
-     * @draft ICU 4.4
-     * @provisional This API might change or be removed in a future release.
-     */
-    public static String getDisplayNameWithDialect(String localeID, String displayLocaleID) {
-        return getDisplayNameWithDialectInternal(new ULocale(localeID),
-                new ULocale(displayLocaleID));
-    }
-
-    /**
-     * {@icu} Returns the locale ID localized for display in the provided locale.
-     * If a dialect name is present in the locale data, then it is returned.
-     * This is a cover for the ICU4C API.
-     * @param localeID the locale whose name is to be displayed.
-     * @param displayLocale the locale in which to display the locale name.
-     * @return the localized locale name.
-     * @draft ICU 4.4
-     * @provisional This API might change or be removed in a future release.
-     */
-    public static String getDisplayNameWithDialect(String localeID, ULocale displayLocale) {
-        return getDisplayNameWithDialectInternal(new ULocale(localeID), displayLocale);
-    }
-
-    private static String getDisplayNameWithDialectInternal(ULocale locale, ULocale displayLocale) {
-        // No dialect support, no script and keyword support
-        return locale.toLocale().getDisplayName(displayLocale.toLocale());
-    }
-
-    /**
-     * {@icu} 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.
-     * @stable ICU 4.0
-     */
-    public String getCharacterOrientation() {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} 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.
-     * @stable ICU 4.0
-     */
-    public String getLineOrientation() {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} 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();
-
-    /**
-     * {@icu} 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() {}
-    }
-
-  /**
-    * {@icu} 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 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.
-    * @param acceptLanguageList list in HTTP "Accept-Language:" format of acceptable locales
-    * @param availableLocales list of available locales. One of these will be returned.
-    * @param fallback if non-null, a 1-element array containing a boolean to be set with
-    * the fallback status
-    * @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) {
-        if (acceptLanguageList == null) {
-            throw new NullPointerException();
-        }
-        ULocale acceptList[] = null;
-        try {
-            acceptList = parseAcceptLanguage(acceptLanguageList, true);
-        } catch (ParseException pe) {
-            acceptList = null;
-        }
-        if (acceptList == null) {
-            return null;
-        }
-        return acceptLanguage(acceptList, availableLocales, fallback);
-    }
-
-    /**
-    * {@icu} 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 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 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.
-    * @param acceptLanguageList list of acceptable locales
-    * @param availableLocales list of available locales. One of these will be returned.
-    * @param fallback if non-null, a 1-element array containing a boolean to be set with
-    * the fallback status
-    * @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) {
-        // fallbacklist
-        int i,j;
-        if(fallback != null) {
-            fallback[0]=true;
-        }
-        for(i=0;i<acceptLanguageList.length;i++) {
-            ULocale aLocale = acceptLanguageList[i];
-            boolean[] setFallback = fallback;
-            do {
-                for(j=0;j<availableLocales.length;j++) {
-                    if(availableLocales[j].equals(aLocale)) {
-                        if(setFallback != null) {
-                            setFallback[0]=false; // first time with this locale - not a fallback.
-                        }
-                        return availableLocales[j];
-                    }
-                }
-                Locale loc = aLocale.toLocale();
-                Locale parent = LocaleUtility.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;
-    }
-
-   /**
-    * {@icu} 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 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.
-    * @param acceptLanguageList list in HTTP "Accept-Language:" format of acceptable locales
-    * @param fallback if non-null, a 1-element array containing a boolean to be set with
-    * the fallback status
-    * @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);
-    }
-
-   /**
-    * {@icu} Based on an ordered array 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 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.
-    * @param acceptLanguageList ordered array of acceptable locales (preferred are listed first)
-    * @param fallback if non-null, a 1-element array containing a boolean to be set with
-    * the fallback status
-    * @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);
-    }
-
-    /**
-     * Package local method used for parsing Accept-Language string
-     */
-    static ULocale[] parseAcceptLanguage(String acceptLanguage, boolean isLenient) 
-        throws ParseException {
-        class ULocaleAcceptLanguageQ implements Comparable<ULocaleAcceptLanguageQ> {
-            private double q;
-            private double serial;
-            public ULocaleAcceptLanguageQ(double theq, int theserial) {
-                q = theq;
-                serial = theserial;
-            }
-            public int compareTo(ULocaleAcceptLanguageQ other) {
-                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<ULocaleAcceptLanguageQ, ULocale> map = 
-            new TreeMap<ULocaleAcceptLanguageQ, ULocale>();
-        StringBuilder languageRangeBuf = new StringBuilder();
-        StringBuilder qvalBuf = new StringBuilder();
-        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);
-                    // sort in reverse order..   1.0, 0.9, 0.8 .. etc
-                    map.put(entry, new ULocale(canonicalize(languageRangeBuf.toString())));
-                }
-
-                // 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[] = map.values().toArray(new ULocale[map.size()]);
-        return acceptList;
-    }
-
-    /**
-     * {@icu} Adds 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.
-     * @stable ICU 4.0
-     */
-    public static ULocale addLikelySubtags(ULocale loc) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Minimizes the subtags for a provided locale ID, per the algorithm described
-     * in the following CLDR technical report:<blockquote>
-     *
-     *   <a href="http://www.unicode.org/reports/tr35/#Likely_Subtags"
-     *>http://www.unicode.org/reports/tr35/#Likely_Subtags</a></blockquote>
-     *
-     * 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:<pre>
-     *
-     * "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".) </pre>
-     *
-     * @param loc The ULocale to minimize
-     * @return The minimized ULocale instance.
-     * @stable ICU 4.0
-     */
-    public static ULocale minimizeSubtags(ULocale loc) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    // --------------------------------
-    //      BCP47/OpenJDK APIs
-    // --------------------------------
-
-    /**
-     * {@icu} The key for the private use locale extension ('x').
-     *
-     * @see #getExtension(char)
-     * @see Builder#setExtension(char, String)
-     *
-     * @draft ICU 4.2
-     * @provisional This API might change or be removed in a future release.
-     */
-    public static final char PRIVATE_USE_EXTENSION = 'x';
-
-    /**
-     * {@icu} The key for Unicode locale extension ('u').
-     *
-     * @see #getExtension(char)
-     * @see Builder#setExtension(char, String)
-     *
-     * @draft ICU 4.2
-     * @provisional This API might change or be removed in a future release.
-     */
-    public static final char UNICODE_LOCALE_EXTENSION = 'u';
-
-    /**
-     * {@icu} Returns the extension (or private use) value associated with
-     * the specified singleton key, or null if there is no extension
-     * associated with the key.  To be valid, the key must be one
-     * of <code>[0-9A-Za-z]</code>.  Keys are case-insensitive, so
-     * for example 'z' and 'Z' represent the same extension.
-     *
-     * @param key the extension key
-     * @return the extension, or null if this locale defines no
-     * extension for the specified key
-     * @throws IllegalArgumentException if the key is not valid
-     * @see #PRIVATE_USE_EXTENSION
-     * @see #UNICODE_LOCALE_EXTENSION
-     *
-     * @draft ICU 4.2
-     * @provisional This API might change or be removed in a future release.
-     */
-    public String getExtension(char key) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Returns the set of extension keys associated with this locale, or the
-     * empty set if it has no extensions.  The returned set is unmodifiable.
-     *
-     * @return the set of extension keys, or the empty set if this locale has
-     * no extensions
-     *
-     * @draft ICU 4.2
-     * @provisional This API might change or be removed in a future release.
-     */
-    public Set<Character> getExtensionKeys() {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Returns the Unicode locale type associated with the specified Unicode
-     * locale key for this locale.  Unicode locale keywrods are specified
-     * by the 'u' extension and consist of key/type pairs.  The key must be
-     * two alphanumeric characters in length, or an IllegalArgumentException
-     * is thrown.
-     * @param key the Unicode locale key
-     * @return the Unicode locale type associated with the key, or null if the
-     * locale does not define a value for the key.
-     * @throws IllegalArgumentException if the key is not valid.
-     *
-     * @draft ICU 4.4
-     * @provisional This API might change or be removed in a future release.
-     */
-    public String getUnicodeLocaleType(String key) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Returns the set of keys for Unicode locale keywords defined by this locale,
-     * or null if this locale has no locale extension.  The returned set is
-     * immutable.
-     *
-     * @return the set of the Unicode locale keys, or null
-     *
-     * @draft ICU 4.4
-     * @provisional This API might change or be removed in a future release.
-     */
-    public Set<String> getUnicodeLocaleKeys() {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Returns a well-formed IETF BCP 47 language tag representing
-     * this locale.
-     *
-     * <p>
-     * If this <code>ULocale</code> object has language, country, or variant
-     * that does not satisfy the IETF BCP 47 language tag syntax requirements,
-     * this method handles these fields as described below:
-     * <p>
-     * <b>Language:</b> If language is empty or ill-formed (for example "a" or "e2"),
-     * it will be emitted as "und" (Undetermined).
-     * <p>
-     * <b>Country:</b> If country is ill-formed (for example "12" or "USA"), it
-     * will be omitted.
-     * <p>
-     * <b>Variant:</b> Variant is treated as consisting of subtags separated by
-     * underscore and converted to lower case letters.  'Well-formed' subtags
-     * consist of either an ASCII letter followed by 4-7 ASCII characters, or an
-     * ASCII digit followed by 3-7 ASCII characters.  If well-formed, the variant
-     * is emitted as each subtag in order (separated by hyphen).  Otherwise:
-     * <ul>
-     * <li>if all sub-segments consist of 1 to 8 ASCII alphanumerics (for example
-     * "WIN", "WINDOWS_XP", "SOLARIS_10"), the first ill-formed variant subtag
-     * and all following sub-segments will be emitted as private use subtags prefixed
-     * by the special private use subtag "variant" followed by each subtag in order
-     * (separated by hyphen).  For example, locale "en_US_WIN" is converted to language
-     * tag "en-US-x-variant-win", locale "de_WINDOWS_XP" is converted to language tag
-     * "de-windows-x-variant-xp".  If this locale has a private use extension value,
-     * the special private use subtags prefixed by "variant" are appended after the
-     * locale's private use value.
-     * <li>if any subtag does not consist of 1 to 8 ASCII alphanumerics, the
-     * variant will be truncated and the problematic subtag and all following
-     * sub-segments will be omitted.  If the remainder is non-empty, it will be
-     * emitted as a private use subtag as above (even if the remainder turns out
-     * to be well-formed).  For example, "Solaris_isjustthecoolestthing" is emitted
-     * as "x-jvariant-Solaris", not as "solaris".</li>
-     * </ul>
-     *
-     * <p><b>Note:</b> Although the language tag created by this method
-     * satisfies the syntax requirements defined by the IETF BCP 47
-     * specification, it is not always a valid BCP 47 language tag.
-     * For example,
-     * <pre>
-     *   new ULocale("xx_YY").toLanguageTag();
-     * </pre>
-     * will return "xx-YY", but the language subtag "xx" and the region subtag "YY"
-     * are invalid because they are not registered in the
-     * <a href="http://www.iana.org/assignments/language-subtag-registry">
-     * IANA Language Subtag Registry</a>.
-     *
-     * @return a BCP47 language tag representing the locale
-     * @see #forLanguageTag(String)
-     *
-     * @draft ICU 4.2
-     * @provisional This API might change or be removed in a future release.
-     */
-    public String toLanguageTag() {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-    /**
-     * {@icu} Returns a locale for the specified IETF BCP 47 language tag string.
-     * If the specified language tag contains any ill-formed subtags,
-     * the first such subtag and all following subtags are ignored.
-     *
-     * <p>This implements the 'Language-Tag' production of BCP47, and
-     * so supports grandfathered (regular and irregular) as well as
-     * private use language tags.  Stand alone private use tags are
-     * represented as empty language and extension 'x-whatever',
-     * and grandfathered tags are converted to their canonical replacements
-     * where they exist.  Note that a few grandfathered tags have no
-     * modern replacement; these will be converted using the fallback
-     * described above so some information might be lost.
-     *
-     * <p>For a list of grandfathered tags, see the
-     * <a href="http://www.iana.org/assignments/language-subtag-registry">
-     * IANA Language Subtag Registry</a>.
-     *
-     * <p><b>Notes:</b> This method converts private use subtags prefixed
-     * by "variant" to variant field in the result locale.  For example,
-     * the code below will return "POSIX".
-     * <pre>
-     *   ULocale.forLanguageTag("en-US-x-variant-posix).getVariant();
-     * </pre>
-     *
-     * @param languageTag the language tag
-     * @return the locale that best represents the language tag
-     * @exception NullPointerException if <code>languageTag</code> is <code>null</code>
-     * @see #toLanguageTag()
-     *
-     * @draft ICU 4.2
-     * @provisional This API might change or be removed in a future release.
-     */
-    public static ULocale forLanguageTag(String languageTag) {
-        throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-    }
-
-
-    /**
-     * <code>Builder</code> is used to build instances of <code>ULocale</code>
-     * from values configured by the setter.  Unlike the <code>ULocale</code>
-     * constructors, the <code>Builder</code> checks if a value configured by a
-     * setter satisfies the syntactical requirements defined by the <code>ULocale</code>
-     * class.  A <code>ULocale</code> object created by a <code>Builder</code> is
-     * well-formed and can be transformed to a well-formed IETF BCP 47 language tag
-     * without losing information.
-     *
-     * <p>
-     * <b>Note:</b> The <code>ULocale</code> class does not provide
-     * any syntactical restrictions on variant, while BCP 47
-     * requires each variant subtag to be 5 to 8 alphanumeric letters or a single
-     * numeric letter followed by 3 alphanumeric letters.  By default,
-     * the <code>setVariant</code> method throws <code>IllformedLocaleException</code>
-     * for a variant that does not satisfy the syntax above.  If it is
-     * necessary to support such a variant, you could use the constructor <code>
-     * Builder(boolean isLenientVariant)</code> passing <code>true</code> to
-     * skip the syntax validation for variant.  However, you should keep in
-     * mind that a <code>Locale</code> object created this way might lose
-     * the variant information when transformed to a BCP 47 language tag.
-     *
-     * <p>
-     * The following example shows how to create a <code>ULocale</code> object
-     * with the <code>Builder</code>.
-     * <blockquote>
-     * <pre>
-     *     ULocale aLocale = new Builder().setLanguage("sr").setScript("Latn").setRegion("RS").build();
-     * </pre>
-     * </blockquote>
-     *
-     * <p>Builders can be reused; <code>clear()</code> resets all
-     * fields to their default values.
-     *
-     * @see ULocale#toLanguageTag()
-     *
-     * @draft ICU 4.2
-     * @provisional This API might change or be removed in a future release.
-     */
-    public static final class Builder {
-
-        /**
-         * Constructs an empty Builder. The default value of all
-         * fields, extensions, and private use information is the
-         * empty string.
-         *
-         * @draft ICU 4.2
-         * @provisional This API might change or be removed in a future release.
-         */
-        public Builder() {
-            throw new UnsupportedOperationException("Constructor not supported by com.ibm.icu.base");
-        }
-
-        /**
-         * Constructs an empty Builder with an option whether to allow
-         * <code>setVariant</code> to accept a value that does not
-         * conform to the IETF BCP 47 variant subtag's syntax requirements.
-         *
-         * @param isLenientVariant When true, this <code>Builder</code>
-         * will accept an ill-formed variant.
-         * @see #setVariant(String)
-         *
-         * @draft ICU 4.4
-         * @provisional This API might change or be removed in a future release.
-         */
-        public Builder(boolean isLenientVariant) {
-            throw new UnsupportedOperationException("Constructor not supported by com.ibm.icu.base");
-        }
-
-        /**
-         * Returns true if this <code>Builder</code> accepts a value that does
-         * not conform to the IETF BCP 47 variant subtag's syntax requirements
-         * in <code>setVariant</code>
-         *
-         * @return true if this <code>Build</code> accepts an ill-formed variant.
-         *
-         * @draft ICU 4.4
-         * @provisional This API might change or be removed in a future release.
-         */
-        public boolean isLenientVariant() {
-            throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-        }
-
-
-        /**
-         * Resets the <code>Builder</code> to match the provided <code>locale</code>.
-         * The previous state of the builder is discarded.  Fields that do
-         * not conform to the <code>ULocale</code> class specification, for example,
-         * a single letter language, are ill-formed.
-         *
-         * @param locale the locale
-         * @return this builder
-         * @throws IllformedLocaleException if <code>locale</code> has
-         * any ill-formed fields.
-         *
-         * @draft ICU 4.2
-         * @provisional This API might change or be removed in a future release.
-         */
-        public Builder setLocale(ULocale locale) {
-            throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-        }
-
-        /**
-         * Resets the builder to match the provided IETF BCP 47 language tag.
-         * The previous state of the builder is discarded.
-         *
-         * @param languageTag the language tag
-         * @return this builder
-         * @throws IllformedLocaleException if <code>languageTag</code> is ill-formed.
-         * @throws NullPointerException if <code>languageTag</code> is null.
-         * @see ULocale#forLanguageTag(String)
-         *
-         * @draft ICU 4.2
-         * @provisional This API might change or be removed in a future release.
-         */
-        public Builder setLanguageTag(String languageTag) {
-            throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-        }
-
-        /**
-         * Sets the language.  If <code>language</code> is the empty string,
-         * the language in this <code>Builder</code> will be removed.
-         * Typical language value is a two or three-letter language
-         * code as defined in ISO639.
-         * Well-formed values are any string of two to eight alpha
-         * letters.  This method accepts upper case alpha letters
-         * [A-Z], but the language value in the <code>ULocale</code>
-         * created by the <code>Builder</code> is always normalized
-         * to lower case letters.
-         *
-         * @param language the language
-         * @return this builder
-         * @throws IllformedLocaleException if <code>language</code> is ill-formed
-         *
-         * @draft ICU 4.2
-         * @provisional This API might change or be removed in a future release.
-         */
-        public Builder setLanguage(String language) {
-            throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-        }
-
-        /**
-         * Sets the script.  If <code>script</code> is the empty string,
-         * the script in this <code>Builder</code> is removed.
-         * Typical script value is a four-letter script code as defined by ISO 15924.
-         * Well-formed values are any string of four alpha letters.
-         * This method accepts both upper and lower case alpha letters [a-zA-Z],
-         * but the script value in the <code>ULocale</code> created by the
-         * <code>Builder</code> is always normalized to title case
-         * (the first letter is upper case and the rest of letters are lower case).
-         *
-         * @param script the script
-         * @return this builder
-         * @throws IllformedLocaleException if <code>script</code> is ill-formed
-         *
-         * @draft ICU 4.2
-         * @provisional This API might change or be removed in a future release.
-         */
-        public Builder setScript(String script) {
-            throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-        }
-
-        /**
-         * Sets the region.  If region is the empty string, the region
-         * in this <code>Builder</code> is removed.
-         * Typical region value is a two-letter ISO 3166 code or a three-digit UN M.49
-         * area code.  Well-formed values are any two-letter or three-digit string.
-         * This method accepts lower case letters [a-z], but the country value in
-         * the <code>ULocale</code> created by the <code>Builder</code> is always
-         * normalized to upper case.
-         *
-         * @param region the region
-         * @return this builder
-         * @throws IllformedLocaleException if <code>region</code> is ill-formed
-         *
-         * @draft ICU 4.2
-         * @provisional This API might change or be removed in a future release.
-         */
-        public Builder setRegion(String region) {
-            throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-        }
-
-        /**
-         * Sets the variant.  If variant is the empty string, the
-         * variant in this <code>Builder</code> is removed.
-         * <p>
-         * <b>Note:</b> By default, this method checks if <code>variant</code>
-         * satisfies the IETF BCP 47 variant subtag's syntax requirements.
-         * However, the <code>ULocale</code> class itself does not impose any syntactical
-         * restriction on variant.  When a <code>Builder</code> is created by the
-         * constructor <code>Builder(boolean isLenientVariant)</code>
-         * with <code>true</code>, this method skips the syntax check.
-         *
-         * @param variant the variant
-         * @return this builder
-         * @throws IllformedLocaleException if <code>variant</code> is ill-formed
-         *
-         * @draft ICU 4.2
-         * @provisional This API might change or be removed in a future release.
-         */
-        public Builder setVariant(String variant) {
-            throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-        }
-
-        /**
-         * Sets the extension for the given key. If the value is the
-         * empty string, the extension is removed. Legal keys are
-         * characters in the ranges <code>[0-9A-Za-z]</code>.  Keys
-         * are case-insensitive, so for example 'z' and 'Z' represent
-         * the same extension. In general, well-formed values are any
-         * series of fields of two to eight alphanumeric characters,
-         * separated by hyphen or underscore.
-         *
-         * <p><b>Note:</b> The key {@link ULocale#UNICODE_LOCALE_EXTENSION
-         * UNICODE_LOCALE_EXTENSION} ('u') is used for the Unicode locale extension.
-         * Setting a value for this key replaces any existing Unicode locale key/type
-         * pairs with those defined in the extension.
-         * To be well-formed, a value for this extension must meet the additional
-         * constraints that each locale key is two alphanumeric characters,
-         * followed by at least one locale type subtag represented by
-         * three to eight alphanumeric characters, and that the keys and types
-         * be legal Unicode locale keys and values.
-         *
-         * <p><b>Note:</b> The key {@link ULocale#PRIVATE_USE_EXTENSION
-         * PRIVATE_USE_EXTENSION} ('x') is used for the private use code. To be
-         * well-formed, the value for this key needs only to have fields of one to
-         * eight alphanumeric characters, not two to eight as in the general case.
-         *
-         * @param key the extension key
-         * @param value the extension value
-         * @return this builder
-         * @throws IllformedLocaleException if <code>key</code> is illegal
-         * or <code>value</code> is ill-formed
-         * @see #setUnicodeLocaleKeyword(String, String)
-         *
-         * @draft ICU 4.2
-         * @provisional This API might change or be removed in a future release.
-         */
-        public Builder setExtension(char key, String value) {
-            throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-        }
-
-        /**
-         * Sets the Unicode locale keyword type for the given key.  If the
-         * value is the empty string, the Unicode keyword is removed.
-         * Well-formed keys are strings of two alphanumeric characters.
-         * Well-formed types are one or more subtags where each of them is
-         * three to eight alphanumeric characters.
-         * <p>
-         * <b>Note</b>:Setting the 'u' extension replaces all Unicode locale
-         * keywords with those defined in the extension.
-         * @param key the Unicode locale key
-         * @param type the Unicode locale type
-         * @return this builder
-         * @throws IllformedLocaleException if <code>key</code> or <code>type</code>
-         * is ill-formed
-         * @see #setExtension(char, String)
-         *
-         * @draft ICU 4.4
-         * @provisional This API might change or be removed in a future release.
-         */
-        public Builder setUnicodeLocaleKeyword(String key, String type) {
-            throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-        }
-
-        /**
-         * Resets the builder to its initial, empty state.
-         *
-         * @return this builder
-         *
-         * @draft ICU 4.2
-         * @provisional This API might change or be removed in a future release.
-         */
-        public Builder clear() {
-            throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-        }
-
-        /**
-         * Resets the extensions to their initial, empty state.
-         * Language, script, region and variant are unchanged.
-         *
-         * @return this builder
-         * @see #setExtension(char, String)
-         *
-         * @draft ICU 4.2
-         * @provisional This API might change or be removed in a future release.
-         */
-        public Builder clearExtensions() {
-            throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-        }
-
-        /**
-         * Returns an instance of Locale created from the fields set
-         * on this builder.
-         *
-         * @return a new Locale
-         *
-         * @draft ICU 4.4
-         * @provisional This API might change or be removed in a future release.
-         */
-        public ULocale build() {
-            throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base");
-        }
-    }
-}
+/*
+******************************************************************************
+* Copyright (C) 2003-2011, International Business Machines Corporation and   *
+* others. All Rights Reserved.                                               *
+******************************************************************************
+*/
+
+package com.ibm.icu.util;
+
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.text.ParseException;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.MissingResourceException;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import com.ibm.icu.impl.ICUCache;
+import com.ibm.icu.impl.LocaleIDParser;
+import com.ibm.icu.impl.LocaleIDs;
+import com.ibm.icu.impl.LocaleUtility;
+import com.ibm.icu.impl.SimpleCache;
+import com.ibm.icu.impl.locale.AsciiUtil;
+import com.ibm.icu.impl.locale.BaseLocale;
+import com.ibm.icu.impl.locale.Extension;
+import com.ibm.icu.impl.locale.InternalLocaleBuilder;
+import com.ibm.icu.impl.locale.LanguageTag;
+import com.ibm.icu.impl.locale.LocaleExtensions;
+import com.ibm.icu.impl.locale.LocaleSyntaxException;
+import com.ibm.icu.impl.locale.ParseStatus;
+import com.ibm.icu.impl.locale.UnicodeLocaleExtension;
+
+/**
+ * {@icuenhanced java.util.Locale}.{@icu _usage_}
+ *
+ * A class analogous to {@link java.util.Locale} that provides additional
+ * support for ICU protocol.  In ICU 3.0 this class is enhanced to support
+ * RFC 3066 language identifiers.
+ *
+ * <p>Many classes and services in ICU follow a factory idiom, in
+ * which a factory method or object responds to a client request with
+ * an object.  The request includes a locale (the <i>requested</i>
+ * locale), and the returned object is constructed using data for that
+ * locale.  The system may lack data for the requested locale, in
+ * which case the locale fallback mechanism will be invoked until a
+ * populated locale is found (the <i>valid</i> locale).  Furthermore,
+ * even when a populated locale is found (the <i>valid</i> locale),
+ * further fallback may be required to reach a locale containing the
+ * specific data required by the service (the <i>actual</i> locale).
+ *
+ * <p>ULocale performs <b>'normalization'</b> and <b>'canonicalization'</b> of locale ids.
+ * Normalization 'cleans up' ICU locale ids as follows:
+ * <ul>
+ * <li>language, script, country, variant, and keywords are properly cased<br>
+ * (lower, title, upper, upper, and lower case respectively)</li>
+ * <li>hyphens used as separators are converted to underscores</li>
+ * <li>three-letter language and country ids are converted to two-letter
+ * equivalents where available</li>
+ * <li>surrounding spaces are removed from keywords and values</li>
+ * <li>if there are multiple keywords, they are put in sorted order</li>
+ * </ul>
+ * Canonicalization additionally performs the following:
+ * <ul>
+ * <li>POSIX ids are converted to ICU format IDs</li>
+ * <li>'grandfathered' 3066 ids are converted to ICU standard form</li>
+ * <li>'PREEURO' and 'EURO' variants are converted to currency keyword form,
+ * with the currency
+ * id appropriate to the country of the locale (for PREEURO) or EUR (for EURO).
+ * </ul>
+ * All ULocale constructors automatically normalize the locale id.  To handle
+ * POSIX ids, <code>canonicalize</code> can be called to convert the id
+ * to canonical form, or the <code>canonicalInstance</code> factory method
+ * can be called.</p>
+ *
+ * <p>This class provides selectors {@link #VALID_LOCALE} and {@link
+ * #ACTUAL_LOCALE} intended for use in methods named
+ * <tt>getLocale()</tt>.  These methods exist in several ICU classes,
+ * including {@link com.ibm.icu.util.Calendar}, {@link
+ * com.ibm.icu.util.Currency}, {@link com.ibm.icu.text.UFormat},
+ * {@link com.ibm.icu.text.BreakIterator},
+ * <a href="../text/Collator.html" title="class in com.ibm.icu.text"><code>Collator</code></a>,
+ * {@link com.ibm.icu.text.DateFormatSymbols}, and {@link
+ * com.ibm.icu.text.DecimalFormatSymbols} and their subclasses, if
+ * any.  Once an object of one of these classes has been created,
+ * <tt>getLocale()</tt> may be called on it to determine the valid and
+ * actual locale arrived at during the object's construction.
+ *
+ * <p>Note: The <i>actual</i> locale is returned correctly, but the <i>valid</i>
+ * locale is not, in most cases.
+ *
+ * @see java.util.Locale
+ * @author weiv
+ * @author Alan Liu
+ * @author Ram Viswanadha
+ * @stable ICU 2.8
+ */
+public final class ULocale implements Serializable {
+    // using serialver from jdk1.4.2_05
+    private static final long serialVersionUID = 3715177670352309217L;
+
+    /**
+     * Useful constant for language.
+     * @stable ICU 3.0
+     */
+    public static final ULocale ENGLISH = new ULocale("en", Locale.ENGLISH);
+
+    /**
+     * Useful constant for language.
+     * @stable ICU 3.0
+     */
+    public static final ULocale FRENCH = new ULocale("fr", Locale.FRENCH);
+
+    /**
+     * Useful constant for language.
+     * @stable ICU 3.0
+     */
+    public static final ULocale GERMAN = new ULocale("de", Locale.GERMAN);
+
+    /**
+     * Useful constant for language.
+     * @stable ICU 3.0
+     */
+    public static final ULocale ITALIAN = new ULocale("it", Locale.ITALIAN);
+
+    /**
+     * Useful constant for language.
+     * @stable ICU 3.0
+     */
+    public static final ULocale JAPANESE = new ULocale("ja", Locale.JAPANESE);
+
+    /**
+     * Useful constant for language.
+     * @stable ICU 3.0
+     */
+    public static final ULocale KOREAN = new ULocale("ko", Locale.KOREAN);
+
+    /**
+     * Useful constant for language.
+     * @stable ICU 3.0
+     */
+    public static final ULocale CHINESE = new ULocale("zh", Locale.CHINESE);
+
+    /**
+     * Useful constant for language.
+     * @stable ICU 3.0
+     */
+    public static final ULocale SIMPLIFIED_CHINESE = new ULocale("zh_Hans", Locale.CHINESE);
+
+    /**
+     * Useful constant for language.
+     * @stable ICU 3.0
+     */
+    public static final ULocale TRADITIONAL_CHINESE = new ULocale("zh_Hant", Locale.CHINESE);
+
+    /**
+     * Useful constant for country/region.
+     * @stable ICU 3.0
+     */
+    public static final ULocale FRANCE = new ULocale("fr_FR", Locale.FRANCE);
+
+    /**
+     * Useful constant for country/region.
+     * @stable ICU 3.0
+     */
+    public static final ULocale GERMANY = new ULocale("de_DE", Locale.GERMANY);
+
+    /**
+     * Useful constant for country/region.
+     * @stable ICU 3.0
+     */
+    public static final ULocale ITALY = new ULocale("it_IT", Locale.ITALY);
+
+    /**
+     * Useful constant for country/region.
+     * @stable ICU 3.0
+     */
+    public static final ULocale JAPAN = new ULocale("ja_JP", Locale.JAPAN);
+
+    /**
+     * Useful constant for country/region.
+     * @stable ICU 3.0
+     */
+    public static final ULocale KOREA = new ULocale("ko_KR", Locale.KOREA);
+
+    /**
+     * Useful constant for country/region.
+     * @stable ICU 3.0
+     */
+    public static final ULocale CHINA = new ULocale("zh_Hans_CN", Locale.CHINA);
+
+    /**
+     * Useful constant for country/region.
+     * @stable ICU 3.0
+     */
+    public static final ULocale PRC = CHINA;
+
+    /**
+     * Useful constant for country/region.
+     * @stable ICU 3.0
+     */
+    public static final ULocale TAIWAN = new ULocale("zh_Hant_TW", Locale.TAIWAN);
+
+    /**
+     * Useful constant for country/region.
+     * @stable ICU 3.0
+     */
+    public static final ULocale UK = new ULocale("en_GB", Locale.UK);
+
+    /**
+     * Useful constant for country/region.
+     * @stable ICU 3.0
+     */
+    public static final ULocale US = new ULocale("en_US", Locale.US);
+
+    /**
+     * Useful constant for country/region.
+     * @stable ICU 3.0
+     */
+    public static final ULocale CANADA = new ULocale("en_CA", Locale.CANADA);
+
+    /**
+     * Useful constant for country/region.
+     * @stable ICU 3.0
+     */
+    public static final ULocale CANADA_FRENCH = new ULocale("fr_CA", Locale.CANADA_FRENCH);
+
+    /**
+     * Handy constant.
+     */
+    private static final String EMPTY_STRING = "";
+
+    // Used in both ULocale and LocaleIDParser, so moved up here.
+    private static final char UNDERSCORE            = '_';
+
+    // default empty locale
+    private static final Locale EMPTY_LOCALE = new Locale("", "");
+
+    // special keyword key for Unicode locale attributes
+    private static final String LOCALE_ATTRIBUTE_KEY = "attribute";
+
+    /**
+     * The root ULocale.
+     * @stable ICU 2.8
+     */
+    public static final ULocale ROOT = new ULocale("", EMPTY_LOCALE);
+
+    /**
+     * Enum for locale categories. These locale categories are used to get/set the default locale for
+     * the specific functionality represented by the category.
+     * @stable ICU 49
+     */
+    public enum Category {
+        /**
+         * Category used to represent the default locale for displaying user interfaces.
+         * @stable ICU 49
+         */
+        DISPLAY,
+        /**
+         * Category used to represent the default locale for formatting date, number and/or currency.
+         * @stable ICU 49
+         */
+        FORMAT
+    }
+
+    private static final SimpleCache<Locale, ULocale> CACHE = new SimpleCache<Locale, ULocale>();
+
+    /**
+     * Cache the locale.
+     */
+    private transient volatile Locale locale;
+
+    /**
+     * The raw localeID that we were passed in.
+     */
+    private String localeID;
+
+    /**
+     * Cache the locale data container fields.
+     * In future, we want to use them as the primary locale identifier storage.
+     */
+    private transient volatile BaseLocale baseLocale;
+    private transient volatile LocaleExtensions extensions;
+
+
+    private static String[][] CANONICALIZE_MAP;
+    private static String[][] variantsToKeywords;
+
+    private static void initCANONICALIZE_MAP() {
+        if (CANONICALIZE_MAP == null) {
+            /**
+             * This table lists pairs of locale ids for canonicalization.  The
+             * 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[][] 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 */
+                { "az_AZ_CYRL",     "az_Cyrl_AZ", null, null }, /* .NET name */
+                { "az_AZ_LATN",     "az_Latn_AZ", null, null }, /* .NET name */
+                { "ca_ES_PREEURO",  "ca_ES", "currency", "ESP" },
+                { "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" }, /* Old ICU name */
+                { "de_AT_PREEURO",  "de_AT", "currency", "ATS" },
+                { "de_DE_PREEURO",  "de_DE", "currency", "DEM" },
+                { "de_LU_PREEURO",  "de_LU", "currency", "EUR" },
+                { "el_GR_PREEURO",  "el_GR", "currency", "GRD" },
+                { "en_BOONT",       "en__BOONT", null, null }, /* registered name */
+                { "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" }, /* Old ICU name */
+                { "es_ES_PREEURO",  "es_ES", "currency", "ESP" },
+                { "eu_ES_PREEURO",  "eu_ES", "currency", "ESP" },
+                { "fi_FI_PREEURO",  "fi_FI", "currency", "FIM" },
+                { "fr_BE_PREEURO",  "fr_BE", "currency", "BEF" },
+                { "fr_FR_PREEURO",  "fr_FR", "currency", "FRF" },
+                { "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" }, /* Old ICU name */
+                { "it_IT_PREEURO",  "it_IT", "currency", "ITL" },
+                { "ja_JP_TRADITIONAL", "ja_JP", "calendar", "japanese" },
+//              { "nb_NO_NY",       "nn_NO", null, null },
+                { "nl_BE_PREEURO",  "nl_BE", "currency", "BEF" },
+                { "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_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 */
+                { "zh_CHT",         "zh_Hant", null, null }, /* .NET name */
+                { "zh_GAN",         "zh__GAN", null, null }, /* registered name */
+                { "zh_GUOYU",       "zh", null, null }, /* registered name */
+                { "zh_HAKKA",       "zh__HAKKA", null, null }, /* registered name */
+                { "zh_MIN",         "zh__MIN", null, null }, /* registered name */
+                { "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 */
+            };
+
+            synchronized (ULocale.class) {
+                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;
+                }
+            }
+        }
+    }
+
+    /**
+     * Private constructor used by static initializers.
+     */
+    private ULocale(String localeID, Locale locale) {
+        this.localeID = localeID;
+        this.locale = locale;
+    }
+
+    /**
+     * Construct a ULocale object from a {@link java.util.Locale}.
+     * @param loc a JDK locale
+     */
+    private ULocale(Locale loc) {
+        this.localeID = getName(forLocale(loc).toString());
+        this.locale = loc;
+    }
+
+    /**
+     * {@icu} Returns a ULocale object for a {@link java.util.Locale}.
+     * The ULocale is canonicalized.
+     * @param loc a JDK locale
+     * @stable ICU 3.2
+     */
+    public static ULocale forLocale(Locale loc) {
+        if (loc == null) {
+            return null;
+        }
+        ULocale result = CACHE.get(loc);
+        if (result == null) {
+            result = JDKLocaleHelper.toULocale(loc);
+            CACHE.put(loc, result);
+        }
+        return result;
+    }
+
+    /**
+     * {@icu} Constructs a ULocale from a RFC 3066 locale ID. The locale ID consists
+     * of optional language, script, country, and variant fields in that order,
+     * separated by underscores, followed by an optional keyword list.  The
+     * 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 two
+     * or more keyword/value pairs separated by semicolons(';').
+     * 
+     * <p>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"
+     * @stable ICU 2.8
+     */
+    public ULocale(String localeID) {
+        this.localeID = getName(localeID);
+    }
+
+    /**
+     * Convenience overload of ULocale(String, String, String) for
+     * compatibility with java.util.Locale.
+     * @see #ULocale(String, String, String)
+     * @stable ICU 3.4
+     */
+    public ULocale(String a, String b) {
+        this(a, b, null);
+    }
+
+    /**
+     * Constructs a ULocale from a localeID constructed from the three 'fields' a, b, and
+     * c.  These fields are concatenated using underscores to form a localeID of the form
+     * a_b_c, which is then handled like the localeID passed to <code>ULocale(String
+     * localeID)</code>.
+     *
+     * <p>Java locale strings consisting of language, country, and
+     * variant will be handled by this form, since the country code
+     * (being shorter than four letters long) will not be interpreted
+     * as a script code.  If a script code is present, the final
+     * argument ('c') will be interpreted as the country code.  It is
+     * recommended that this constructor only be used to ease porting,
+     * and that clients instead use the single-argument constructor
+     * when constructing a ULocale from a localeID.
+     * @param a first component of the locale id
+     * @param b second component of the locale id
+     * @param c third component of the locale id
+     * @see #ULocale(String)
+     * @stable ICU 3.0
+     */
+    public ULocale(String a, String b, String c) {
+        localeID = getName(lscvToID(a, b, c, EMPTY_STRING));
+    }
+
+    /**
+     * {@icu} Creates a ULocale from the id by first canonicalizing the id.
+     * @param nonCanonicalID the locale id to canonicalize
+     * @return the locale created from the canonical version of the ID.
+     * @stable ICU 3.0
+     */
+    public static ULocale createCanonical(String nonCanonicalID) {
+        return new ULocale(canonicalize(nonCanonicalID), (Locale)null);
+    }
+
+    private static String lscvToID(String lang, String script, String country, String variant) {
+        StringBuilder buf = new StringBuilder();
+
+        if (lang != null && lang.length() > 0) {
+            buf.append(lang);
+        }
+        if (script != null && script.length() > 0) {
+            buf.append(UNDERSCORE);
+            buf.append(script);
+        }
+        if (country != null && country.length() > 0) {
+            buf.append(UNDERSCORE);
+            buf.append(country);
+        }
+        if (variant != null && variant.length() > 0) {
+            if (country == null || country.length() == 0) {
+                buf.append(UNDERSCORE);
+            }
+            buf.append(UNDERSCORE);
+            buf.append(variant);
+        }
+        return buf.toString();
+    }
+
+    /**
+     * {@icu} Converts this ULocale object to a {@link java.util.Locale}.
+     * @return a JDK locale that either exactly represents this object
+     * or is the closest approximation.
+     * @stable ICU 2.8
+     */
+    public Locale toLocale() {
+        if (locale == null) {
+            locale = JDKLocaleHelper.toLocale(this);
+        }
+        return locale;
+    }
+
+    private static ICUCache<String, String> nameCache = new SimpleCache<String, String>();
+
+    /**
+     * Keep our own default ULocale.
+     */
+    private static Locale defaultLocale = Locale.getDefault();
+    private static ULocale defaultULocale = forLocale(defaultLocale);
+
+    private static Locale[] defaultCategoryLocales = new Locale[Category.values().length];
+    private static ULocale[] defaultCategoryULocales = new ULocale[Category.values().length];
+
+    static {
+        for (Category cat: Category.values()) {
+            int idx = cat.ordinal();
+            defaultCategoryLocales[idx] = JDKLocaleHelper.getDefault(cat);
+            defaultCategoryULocales[idx] = forLocale(defaultCategoryLocales[idx]);
+        }
+    }
+
+    /**
+     * Returns the current default ULocale.
+     * @return the default ULocale.
+     * @stable ICU 2.8
+     */
+    public static ULocale getDefault() {
+        synchronized (ULocale.class) {
+            if (defaultULocale == null) {
+                // When Java's default locale has extensions (such as ja-JP-u-ca-japanese),
+                // Locale -> ULocale mapping requires BCP47 keyword mapping data that is currently
+                // stored in a resource bundle. However, UResourceBundle currently requires
+                // non-null default ULocale. For now, this implementation returns ULocale.ROOT
+                // to avoid the problem.
+
+                // TODO: Consider moving BCP47 mapping data out of resource bundle later.
+
+                return ULocale.ROOT;
+            }
+            Locale currentDefault = Locale.getDefault();
+            if (!defaultLocale.equals(currentDefault)) {
+                defaultLocale = currentDefault;
+                defaultULocale = forLocale(currentDefault);
+
+                if (!JDKLocaleHelper.isJava7orNewer()) {
+                    // Detected Java default Locale change.
+                    // We need to update category defaults to match the
+                    // Java 7's behavior on Java 6 or older environment.
+                    for (Category cat : Category.values()) {
+                        int idx = cat.ordinal();
+                        defaultCategoryLocales[idx] = currentDefault;
+                        defaultCategoryULocales[idx] = forLocale(currentDefault);
+                    }
+                }
+            }
+            return defaultULocale;
+        }
+    }
+
+    /**
+     * {@icu} Sets the default ULocale.  This also sets the default Locale.
+     * If the caller does not have write permission to the
+     * user.language property, a security exception will be thrown,
+     * and the default ULocale will remain unchanged.
+     * <p>
+     * By setting the default ULocale with this method, all of the default categoy locales
+     * are also set to the specified default ULocale.
+     * @param newLocale the new default locale
+     * @throws SecurityException 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(java.security.Permission)
+     * @see java.util.PropertyPermission
+     * @see ULocale#setDefault(Category, ULocale)
+     * @stable ICU 3.0
+     */
+    public static synchronized void setDefault(ULocale newLocale){
+        defaultLocale = newLocale.toLocale();
+        Locale.setDefault(defaultLocale);
+        defaultULocale = newLocale;
+        // This method also updates all category default locales
+        for (Category cat : Category.values()) {
+            setDefault(cat, newLocale);
+        }
+    }
+
+    /**
+     * Returns the current default ULocale for the specified category.
+     * 
+     * @param category the category
+     * @return the default ULocale for the specified category.
+     * @stable ICU 49
+     */
+    public static ULocale getDefault(Category category) {
+        synchronized (ULocale.class) {
+            int idx = category.ordinal();
+            if (defaultCategoryULocales[idx] == null) {
+                // Just in case this method is called during ULocale class
+                // initialization. Unlike getDefault(), we do not have
+                // cyclic dependency for category default.
+                return ULocale.ROOT;
+            }
+            if (JDKLocaleHelper.isJava7orNewer()) {
+                Locale currentCategoryDefault = JDKLocaleHelper.getDefault(category);
+                if (!defaultCategoryLocales[idx].equals(currentCategoryDefault)) {
+                    defaultCategoryLocales[idx] = currentCategoryDefault;
+                    defaultCategoryULocales[idx] = forLocale(currentCategoryDefault);
+                }
+            } else {
+                // java.util.Locale.setDefault(Locale) in Java 7 updates
+                // category locale defaults. On Java 6 or older environment,
+                // ICU4J checks if the default locale has changed and update
+                // category ULocales here if necessary.
+                
+                // Note: When java.util.Locale.setDefault(Locale) is called
+                // with a Locale same with the previous one, Java 7 still
+                // updates category locale defaults. On Java 6 or older env,
+                // there is no good way to detect the event, ICU4J simply
+                // check if the default Java Locale has changed since last
+                // time.
+
+                Locale currentDefault = Locale.getDefault();
+                if (!defaultLocale.equals(currentDefault)) {
+                    defaultLocale = currentDefault;
+                    defaultULocale = forLocale(currentDefault);
+
+                    for (Category cat : Category.values()) {
+                        int tmpIdx = cat.ordinal();
+                        defaultCategoryLocales[tmpIdx] = currentDefault;
+                        defaultCategoryULocales[tmpIdx] = forLocale(currentDefault);
+                    }
+                }
+                
+                // No synchronization with JDK Locale, because category default
+                // is not supported in Java 6 or older versions
+            }
+            return defaultCategoryULocales[idx];
+        }
+    }
+
+    /**
+     * Sets the default <code>ULocale</code> for the specified <code>Category</code>.
+     * This also sets the default <code>Locale</code> for the specified <code>Category</code>
+     * of the JVM. If the caller does not have write permission to the
+     * user.language property, a security exception will be thrown,
+     * and the default ULocale for the specified Category will remain unchanged.
+     * 
+     * @param category the specified category to set the default locale
+     * @param newLocale the new default locale
+     * @see SecurityManager#checkPermission(java.security.Permission)
+     * @see java.util.PropertyPermission
+     * @stable ICU 49
+     */
+    public static synchronized void setDefault(Category category, ULocale newLocale) {
+        Locale newJavaDefault = newLocale.toLocale();
+        int idx = category.ordinal();
+        defaultCategoryULocales[idx] = newLocale;
+        defaultCategoryLocales[idx] = newJavaDefault;
+        JDKLocaleHelper.setDefault(category, newJavaDefault);
+    }
+
+    /**
+     * This is for compatibility with Locale-- in actuality, since ULocale is
+     * immutable, there is no reason to clone it, so this API returns 'this'.
+     * @stable ICU 3.0
+     */
+    public Object clone() {
+        return this;
+    }
+
+    /**
+     * Returns the hashCode.
+     * @stable ICU 3.0
+     */
+    public int hashCode() {
+        return localeID.hashCode();
+    }
+
+    /**
+     * Returns true if the other object is another ULocale with the
+     * same full name, or is a String localeID that matches the full name.
+     * Note that since names are not canonicalized, two ULocales that
+     * function identically might not compare equal.
+     *
+     * @return true if this Locale is equal to the specified object.
+     * @stable ICU 3.0
+     */
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof String) {
+            return localeID.equals((String)obj);
+        }
+        if (obj instanceof ULocale) {
+            return localeID.equals(((ULocale)obj).localeID);
+        }
+        return false;
+    }
+
+    /**
+     * {@icunote} Unlike the Locale API, this returns an array of <code>ULocale</code>,
+     * not <code>Locale</code>.  Returns a list of all installed locales.
+     * @stable ICU 3.0
+     */
+    public static ULocale[] getAvailableLocales() {
+        //#com.ibm.icu.base
+        if (availableLocales == null) {
+            synchronized (ULocale.class) {
+                if (availableLocales == null) {
+                    Locale[] locales = Locale.getAvailableLocales();
+                    availableLocales = new ULocale[locales.length];
+                    for (int i = 0; i < locales.length; i++) {
+                        availableLocales[i] = ULocale.forLocale(locales[i]);
+                    }
+                }
+            }
+        }
+        return availableLocales.clone();
+    }
+    private static volatile ULocale[] availableLocales = null;
+
+    /**
+     * Returns a list of all 2-letter country codes defined in ISO 3166.
+     * Can be used to create Locales.
+     * @stable ICU 3.0
+     */
+    public static String[] getISOCountries() {
+        return LocaleIDs.getISOCountries();
+    }
+
+    /**
+     * Returns a list of all 2-letter language codes defined in ISO 639.
+     * Can be used to create Locales.
+     * [NOTE:  ISO 639 is not a stable standard-- some languages' codes have changed.
+     * The list this function returns includes both the new and the old codes for the
+     * languages whose codes have changed.]
+     * @stable ICU 3.0
+     */
+    public static String[] getISOLanguages() {
+        return LocaleIDs.getISOLanguages();
+    }
+
+    /**
+     * Returns the language code for this locale, which will either be the empty string
+     * or a lowercase ISO 639 code.
+     * @see #getDisplayLanguage()
+     * @see #getDisplayLanguage(ULocale)
+     * @stable ICU 3.0
+     */
+    public String getLanguage() {
+        return getLanguage(localeID);
+    }
+
+    /**
+     * 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(ULocale)
+     * @stable ICU 3.0
+     */
+    public static String getLanguage(String localeID) {
+        return new LocaleIDParser(localeID).getLanguage();
+    }
+
+    /**
+     * {@icu} Returns the script code for this locale, which might be the empty string.
+     * @see #getDisplayScript()
+     * @see #getDisplayScript(ULocale)
+     * @stable ICU 3.0
+     */
+    public String getScript() {
+        return getScript(localeID);
+    }
+
+    /**
+     * {@icu} Returns the script code for the specified locale, which might be the empty
+     * string.
+     * @see #getDisplayScript()
+     * @see #getDisplayScript(ULocale)
+     * @stable ICU 3.0
+     */
+    public static String getScript(String localeID) {
+        return new LocaleIDParser(localeID).getScript();
+    }
+
+    /**
+     * 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(ULocale)
+     * @stable ICU 3.0
+     */
+    public String getCountry() {
+        return getCountry(localeID);
+    }
+
+    /**
+     * 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 The locale identification string.
+     * @see #getDisplayCountry()
+     * @see #getDisplayCountry(ULocale)
+     * @stable ICU 3.0
+     */
+    public static String getCountry(String localeID) {
+        return new LocaleIDParser(localeID).getCountry();
+    }
+
+    /**
+     * Returns the variant code for this locale, which might be the empty string.
+     * @see #getDisplayVariant()
+     * @see #getDisplayVariant(ULocale)
+     * @stable ICU 3.0
+     */
+    public String getVariant() {
+        return getVariant(localeID);
+    }
+
+    /**
+     * Returns the variant code for the specified locale, which might be the empty string.
+     * @see #getDisplayVariant()
+     * @see #getDisplayVariant(ULocale)
+     * @stable ICU 3.0
+     */
+    public static String getVariant(String localeID) {
+        return new LocaleIDParser(localeID).getVariant();
+    }
+
+    /**
+     * {@icu} Returns the fallback locale for the specified locale, which might be the
+     * empty string.
+     * @stable ICU 3.2
+     */
+    public static String getFallback(String localeID) {
+        return getFallbackString(getName(localeID));
+    }
+
+    /**
+     * {@icu} Returns the fallback locale for this locale.  If this locale is root,
+     * returns null.
+     * @stable ICU 3.2
+     */
+    public ULocale getFallback() {
+        if (localeID.length() == 0 || localeID.charAt(0) == '@') {
+            return null;
+        }
+        return new ULocale(getFallbackString(localeID), (Locale)null);
+    }
+
+    /**
+     * Returns the given (canonical) locale id minus the last part before the tags.
+     */
+    private static String getFallbackString(String fallback) {
+        int extStart = fallback.indexOf('@');
+        if (extStart == -1) {
+            extStart = fallback.length();
+        }
+        int last = fallback.lastIndexOf('_', extStart);
+        if (last == -1) {
+            last = 0;
+        } else {
+            // truncate empty segment
+            while (last > 0) {
+                if (fallback.charAt(last - 1) != '_') {
+                    break;
+                }
+                last--;
+            }
+        }
+        return fallback.substring(0, last) + fallback.substring(extStart);
+    }
+
+    /**
+     * {@icu} Returns the (normalized) base name for this locale.
+     * @return the base name as a String.
+     * @stable ICU 3.0
+     */
+    public String getBaseName() {
+        return getBaseName(localeID);
+    }
+
+    /**
+     * {@icu} Returns the (normalized) base name for the specified locale.
+     * @param localeID the locale ID as a string
+     * @return the base name as a String.
+     * @stable ICU 3.0
+     */
+    public static String getBaseName(String localeID){
+        if (localeID.indexOf('@') == -1) {
+            return localeID;
+        }
+        return new LocaleIDParser(localeID).getBaseName();
+    }
+
+    /**
+     * {@icu} Returns the (normalized) full name for this locale.
+     *
+     * @return String the full name of the localeID
+     * @stable ICU 3.0
+     */
+    public String getName() {
+        return localeID; // always normalized
+    }
+    
+    /**
+     * Gets the shortest length subtag's size.
+     *
+     * @param localeID
+     * @return The size of the shortest length subtag
+     **/
+    private static int getShortestSubtagLength(String localeID) {
+        int localeIDLength = localeID.length();
+        int length = localeIDLength;
+        boolean reset = true;
+        int tmpLength = 0;
+        
+        for (int i = 0; i < localeIDLength; i++) {
+            if (localeID.charAt(i) != '_' && localeID.charAt(i) != '-') {
+                if (reset) {
+                    reset = false;
+                    tmpLength = 0;
+                }
+                tmpLength++;
+            } else {
+                if (tmpLength != 0 && tmpLength < length) {
+                    length = tmpLength;
+                }
+                reset = true;
+            }
+        }
+        
+        return length;
+    }
+
+    /**
+     * {@icu} Returns the (normalized) full name for the specified locale.
+     *
+     * @param localeID the localeID as a string
+     * @return String the full name of the localeID
+     * @stable ICU 3.0
+     */
+    public static String getName(String localeID){
+        String tmpLocaleID;
+        // Convert BCP47 id if necessary
+        if (localeID != null && !localeID.contains("@") && getShortestSubtagLength(localeID) == 1) {
+            tmpLocaleID = forLanguageTag(localeID).getName();
+            if (tmpLocaleID.length() == 0) {
+                tmpLocaleID = localeID;
+            }
+        } else {
+            tmpLocaleID = localeID;
+        }
+        String name = nameCache.get(tmpLocaleID);
+        if (name == null) {
+            name = new LocaleIDParser(tmpLocaleID).getName();
+            nameCache.put(tmpLocaleID, name);
+        }
+        return name;
+    }
+
+    /**
+     * Returns a string representation of this object.
+     * @stable ICU 3.0
+     */
+    public String toString() {
+        return localeID;
+    }
+
+    /**
+     * {@icu} Returns an iterator over keywords for this locale.  If there
+     * are no keywords, returns null.
+     * @return iterator over keywords, or null if there are no keywords.
+     * @stable ICU 3.0
+     */
+    public Iterator<String> getKeywords() {
+        return getKeywords(localeID);
+    }
+
+    /**
+     * {@icu} Returns an iterator over keywords for the specified locale.  If there
+     * are no keywords, returns null.
+     * @return an iterator over the keywords in the specified locale, or null
+     * if there are no keywords.
+     * @stable ICU 3.0
+     */
+    public static Iterator<String> getKeywords(String localeID){
+        return new LocaleIDParser(localeID).getKeywords();
+    }
+
+    /**
+     * {@icu} Returns the value for a keyword in this locale. If the keyword is not
+     * defined, returns null.
+     * @param keywordName name of the keyword whose value is desired. Case insensitive.
+     * @return the value of the keyword, or null.
+     * @stable ICU 3.0
+     */
+    public String getKeywordValue(String keywordName){
+        return getKeywordValue(localeID, keywordName);
+    }
+
+    /**
+     * {@icu} Returns the value for a keyword in the specified locale. If the keyword is
+     * not defined, returns null.  The locale name does not need to be normalized.
+     * @param keywordName name of the keyword whose value is desired. Case insensitive.
+     * @return String the value of the keyword as a string
+     * @stable ICU 3.0
+     */
+    public static String getKeywordValue(String localeID, String keywordName) {
+        return new LocaleIDParser(localeID).getKeywordValue(keywordName);
+    }
+
+    /**
+     * {@icu} Returns the canonical name for the specified locale ID.  This is used to
+     * convert POSIX and other grandfathered IDs to standard ICU form.
+     * @param localeID the locale id
+     * @return the canonicalized id
+     * @stable ICU 3.0
+     */
+    public static String canonicalize(String localeID){
+        LocaleIDParser parser = new LocaleIDParser(localeID, true);
+        String baseName = parser.getBaseName();
+        boolean foundVariant = false;
+
+        // formerly, we always set to en_US_POSIX if the basename was empty, but
+        // now we require that the entire id be empty, so that "@foo=bar"
+        // will pass through unchanged.
+        // {dlf} I'd rather keep "" unchanged.
+        if (localeID.equals("")) {
+            return "";
+//              return "en_US_POSIX";
+        }
+
+        // we have an ID in the form xx_Yyyy_ZZ_KKKKK
+
+        initCANONICALIZE_MAP();
+
+        /* 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;
+
+                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]);
+                }
+                break;
+            }
+        }
+
+        /* total mondo hack for Norwegian, fortunately the main NY case is handled earlier */
+        if (!foundVariant) {
+            if (parser.getLanguage().equals("nb") && parser.getVariant().equals("NY")) {
+                parser.setBaseName(lscvToID("nn", parser.getScript(), parser.getCountry(), null));
+            }
+        }
+
+        return parser.getName();
+    }
+
+    /**
+     * Given a keyword and a value, return a new locale with an updated
+     * keyword and value.  If keyword is null, this removes all keywords from the locale id.
+     * Otherwise, if the value is null, this removes the value for this keyword from the
+     * locale id.  Otherwise, this adds/replaces the value for this keyword in the locale id.
+     * The keyword and value must not be empty.
+     * @param keyword the keyword to add/remove, or null to remove all keywords.
+     * @param value the value to add/set, or null to remove this particular keyword.
+     * @return the updated locale
+     * @stable ICU 3.2
+     */
+    public ULocale setKeywordValue(String keyword, String value) {
+        return new ULocale(setKeywordValue(localeID, keyword, value), (Locale)null);
+    }
+
+    /**
+     * Given a locale id, a keyword, and a value, return a new locale id with an updated
+     * keyword and value.  If keyword is null, this removes all keywords from the locale id.
+     * Otherwise, if the value is null, this removes the value for this keyword from the
+     * locale id.  Otherwise, this adds/replaces the value for this keyword in the locale id.
+     * The keyword and value must not be empty.
+     * @param localeID the locale id to modify
+     * @param keyword the keyword to add/remove, or null to remove all keywords.
+     * @param value the value to add/set, or null to remove this particular keyword.
+     * @return the updated locale id
+     * @stable ICU 3.2
+     */
+    public static String setKeywordValue(String localeID, String keyword, String value) {
+        LocaleIDParser parser = new LocaleIDParser(localeID);
+        parser.setKeywordValue(keyword, value);
+        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
+     */
+/*    private static String defaultKeywordValue(String localeID, String keyword, String value) {
+        LocaleIDParser parser = new LocaleIDParser(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
+     * a lowercase ISO 639-2/T language code.
+     * The ISO 639-2 language codes can be found on-line at
+     *   <a href="ftp://dkuug.dk/i18n/iso-639-2.txt"><code>ftp://dkuug.dk/i18n/iso-639-2.txt</code></a>
+     * @exception MissingResourceException Throws MissingResourceException if the
+     * three-letter language abbreviation is not available for this locale.
+     * @stable ICU 3.0
+     */
+    public String getISO3Language(){
+        return getISO3Language(localeID);
+    }
+
+    /**
+     * Returns a three-letter abbreviation for this locale's language.  If the locale
+     * doesn't specify a language, returns the empty string.  Otherwise, returns
+     * a lowercase ISO 639-2/T language code.
+     * The ISO 639-2 language codes can be found on-line at
+     *   <a href="ftp://dkuug.dk/i18n/iso-639-2.txt"><code>ftp://dkuug.dk/i18n/iso-639-2.txt</code></a>
+     * @exception MissingResourceException Throws MissingResourceException if the
+     * three-letter language abbreviation is not available for this locale.
+     * @stable ICU 3.0
+     */
+    public static String getISO3Language(String localeID) {
+        return LocaleIDs.getISO3Language(getLanguage(localeID));
+    }
+
+    /**
+     * Returns a three-letter abbreviation for this locale's country/region.  If the locale
+     * doesn't specify a country, returns the empty string.  Otherwise, returns
+     * an uppercase ISO 3166 3-letter country code.
+     * @exception MissingResourceException Throws MissingResourceException if the
+     * three-letter country abbreviation is not available for this locale.
+     * @stable ICU 3.0
+     */
+    public String getISO3Country() {
+        return getISO3Country(localeID);
+    }
+
+    /**
+     * Returns a three-letter abbreviation for this locale's country/region.  If the locale
+     * doesn't specify a country, returns the empty string.  Otherwise, returns
+     * an uppercase ISO 3166 3-letter country code.
+     * @exception MissingResourceException Throws MissingResourceException if the
+     * three-letter country abbreviation is not available for this locale.
+     * @stable ICU 3.0
+     */
+    public static String getISO3Country(String localeID) {
+        return LocaleIDs.getISO3Country(getCountry(localeID));
+    }
+
+    // display names
+
+    /**
+     * Returns this locale's language localized for display in the default <code>DISPLAY</code> locale.
+     * @return the localized language name.
+     * @see Category#DISPLAY
+     * @stable ICU 3.0
+     */
+    public String getDisplayLanguage() {
+        return getDisplayLanguageInternal(this, getDefault(Category.DISPLAY), false);
+    }
+
+    /**
+     * {@icu} Returns this locale's language localized for display in the provided locale.
+     * @param displayLocale the locale in which to display the name.
+     * @return the localized language name.
+     * @stable ICU 3.0
+     */
+    public String getDisplayLanguage(ULocale displayLocale) {
+        return getDisplayLanguageInternal(this, displayLocale, false);
+    }
+
+    /**
+     * Returns a locale's language localized for display in the provided locale.
+     * This is a cover for the ICU4C API.
+     * @param localeID the id of the locale whose language will be displayed
+     * @param displayLocaleID the id of the locale in which to display the name.
+     * @return the localized language name.
+     * @stable ICU 3.0
+     */
+    public static String getDisplayLanguage(String localeID, String displayLocaleID) {
+        return getDisplayLanguageInternal(new ULocale(localeID), new ULocale(displayLocaleID),
+                false);
+    }
+
+    /**
+     * Returns a locale's language localized for display in the provided locale.
+     * This is a cover for the ICU4C API.
+     * @param localeID the id of the locale whose language will be displayed.
+     * @param displayLocale the locale in which to display the name.
+     * @return the localized language name.
+     * @stable ICU 3.0
+     */
+    public static String getDisplayLanguage(String localeID, ULocale displayLocale) {
+        return getDisplayLanguageInternal(new ULocale(localeID), displayLocale, false);
+    }
+    /**
+     * {@icu} Returns this locale's language localized for display in the default <code>DISPLAY</code> locale.
+     * If a dialect name is present in the data, then it is returned.
+     * @return the localized language name.
+     * @see Category#DISPLAY
+     * @stable ICU 4.4
+     */
+    public String getDisplayLanguageWithDialect() {
+        return getDisplayLanguageInternal(this, getDefault(Category.DISPLAY), true);
+    }
+
+    /**
+     * {@icu} Returns this locale's language localized for display in the provided locale.
+     * If a dialect name is present in the data, then it is returned.
+     * @param displayLocale the locale in which to display the name.
+     * @return the localized language name.
+     * @stable ICU 4.4
+     */
+    public String getDisplayLanguageWithDialect(ULocale displayLocale) {
+        return getDisplayLanguageInternal(this, displayLocale, true);
+    }
+
+    /**
+     * {@icu} Returns a locale's language localized for display in the provided locale.
+     * If a dialect name is present in the data, then it is returned.
+     * This is a cover for the ICU4C API.
+     * @param localeID the id of the locale whose language will be displayed
+     * @param displayLocaleID the id of the locale in which to display the name.
+     * @return the localized language name.
+     * @stable ICU 4.4
+     */
+    public static String getDisplayLanguageWithDialect(String localeID, String displayLocaleID) {
+        return getDisplayLanguageInternal(new ULocale(localeID), new ULocale(displayLocaleID),
+                true);
+    }
+
+    /**
+     * {@icu} Returns a locale's language localized for display in the provided locale.
+     * If a dialect name is present in the data, then it is returned.
+     * This is a cover for the ICU4C API.
+     * @param localeID the id of the locale whose language will be displayed.
+     * @param displayLocale the locale in which to display the name.
+     * @return the localized language name.
+     * @stable ICU 4.4
+     */
+    public static String getDisplayLanguageWithDialect(String localeID, ULocale displayLocale) {
+        return getDisplayLanguageInternal(new ULocale(localeID), displayLocale, true);
+    }
+
+    private static String getDisplayLanguageInternal(ULocale locale, ULocale displayLocale,
+            boolean useDialect) {
+        //#com.ibm.icu.base
+        // No dialect support
+        return locale.toLocale().getDisplayLanguage(displayLocale.toLocale());
+    }
+
+    /**
+     * {@icu} Returns this locale's script localized for display in the default <code>DISPLAY</code> locale.
+     * @return the localized script name.
+     * @see Category#DISPLAY
+     * @stable ICU 3.0
+     */
+    public String getDisplayScript() {
+        return getDisplayScriptInternal(this, getDefault(Category.DISPLAY));
+    }
+
+    /**
+     * {@icu} Returns this locale's script localized for display in the provided locale.
+     * @param displayLocale the locale in which to display the name.
+     * @return the localized script name.
+     * @stable ICU 3.0
+     */
+    public String getDisplayScript(ULocale displayLocale) {
+        return getDisplayScriptInternal(this, displayLocale);
+    }
+
+    /**
+     * {@icu} Returns a locale's script localized for display in the provided locale.
+     * This is a cover for the ICU4C API.
+     * @param localeID the id of the locale whose script will be displayed
+     * @param displayLocaleID the id of the locale in which to display the name.
+     * @return the localized script name.
+     * @stable ICU 3.0
+     */
+    public static String getDisplayScript(String localeID, String displayLocaleID) {
+        return getDisplayScriptInternal(new ULocale(localeID), new ULocale(displayLocaleID));
+    }
+
+    /**
+     * {@icu} Returns a locale's script localized for display in the provided locale.
+     * @param localeID the id of the locale whose script will be displayed.
+     * @param displayLocale the locale in which to display the name.
+     * @return the localized script name.
+     * @stable ICU 3.0
+     */
+    public static String getDisplayScript(String localeID, ULocale displayLocale) {
+        return getDisplayScriptInternal(new ULocale(localeID), displayLocale);
+    }
+
+    // displayLocaleID is canonical, localeID need not be since parsing will fix this.
+    private static String getDisplayScriptInternal(ULocale locale, ULocale displayLocale) {
+        //#com.ibm.icu.base
+        String dispScript = null;
+        try {
+            // Calling Locale#getDisplayScript on Java 7 or later
+            Method mGetDisplayScript = Locale.class.getMethod("getDisplayScript", Locale.class);
+            dispScript = (String) mGetDisplayScript.invoke(locale.toLocale(), displayLocale.toLocale());
+            
+        } catch (NoSuchMethodException e) {
+        } catch (InvocationTargetException e) {
+        } catch (IllegalAccessException e) {
+        }
+
+        if (dispScript == null) {
+            dispScript = locale.getScript();
+        }
+        return dispScript;
+    }
+
+    /**
+     * Returns this locale's country localized for display in the default <code>DISPLAY</code> locale.
+     * @return the localized country name.
+     * @see Category#DISPLAY
+     * @stable ICU 3.0
+     */
+    public String getDisplayCountry() {
+        return getDisplayCountryInternal(this, getDefault(Category.DISPLAY));
+    }
+
+    /**
+     * Returns this locale's country localized for display in the provided locale.
+     * @param displayLocale the locale in which to display the name.
+     * @return the localized country name.
+     * @stable ICU 3.0
+     */
+    public String getDisplayCountry(ULocale displayLocale){
+        return getDisplayCountryInternal(this, displayLocale);
+    }
+
+    /**
+     * Returns a locale's country localized for display in the provided locale.
+     * This is a cover for the ICU4C API.
+     * @param localeID the id of the locale whose country will be displayed
+     * @param displayLocaleID the id of the locale in which to display the name.
+     * @return the localized country name.
+     * @stable ICU 3.0
+     */
+    public static String getDisplayCountry(String localeID, String displayLocaleID) {
+        return getDisplayCountryInternal(new ULocale(localeID), new ULocale(displayLocaleID));
+    }
+
+    /**
+     * Returns a locale's country localized for display in the provided locale.
+     * This is a cover for the ICU4C API.
+     * @param localeID the id of the locale whose country will be displayed.
+     * @param displayLocale the locale in which to display the name.
+     * @return the localized country name.
+     * @stable ICU 3.0
+     */
+    public static String getDisplayCountry(String localeID, ULocale displayLocale) {
+        return getDisplayCountryInternal(new ULocale(localeID), displayLocale);
+    }
+
+    // displayLocaleID is canonical, localeID need not be since parsing will fix this.
+    private static String getDisplayCountryInternal(ULocale locale, ULocale displayLocale) {
+        //#com.ibm.icu.base
+        return locale.toLocale().getDisplayCountry(displayLocale.toLocale());
+    }
+
+    /**
+     * Returns this locale's variant localized for display in the default <code>DISPLAY</code> locale.
+     * @return the localized variant name.
+     * @see Category#DISPLAY
+     * @stable ICU 3.0
+     */
+    public String getDisplayVariant() {
+        return getDisplayVariantInternal(this, getDefault(Category.DISPLAY));
+    }
+
+    /**
+     * Returns this locale's variant localized for display in the provided locale.
+     * @param displayLocale the locale in which to display the name.
+     * @return the localized variant name.
+     * @stable ICU 3.0
+     */
+    public String getDisplayVariant(ULocale displayLocale) {
+        return getDisplayVariantInternal(this, displayLocale);
+    }
+
+    /**
+     * Returns a locale's variant localized for display in the provided locale.
+     * This is a cover for the ICU4C API.
+     * @param localeID the id of the locale whose variant will be displayed
+     * @param displayLocaleID the id of the locale in which to display the name.
+     * @return the localized variant name.
+     * @stable ICU 3.0
+     */
+    public static String getDisplayVariant(String localeID, String displayLocaleID){
+        return getDisplayVariantInternal(new ULocale(localeID), new ULocale(displayLocaleID));
+    }
+
+    /**
+     * Returns a locale's variant localized for display in the provided locale.
+     * This is a cover for the ICU4C API.
+     * @param localeID the id of the locale whose variant will be displayed.
+     * @param displayLocale the locale in which to display the name.
+     * @return the localized variant name.
+     * @stable ICU 3.0
+     */
+    public static String getDisplayVariant(String localeID, ULocale displayLocale) {
+        return getDisplayVariantInternal(new ULocale(localeID), displayLocale);
+    }
+
+    private static String getDisplayVariantInternal(ULocale locale, ULocale displayLocale) {
+        //#com.ibm.icu.base
+        return locale.toLocale().getDisplayVariant(displayLocale.toLocale());
+    }
+
+    /**
+     * {@icu} Returns a keyword localized for display in the default <code>DISPLAY</code> locale.
+     * @param keyword the keyword to be displayed.
+     * @return the localized keyword name.
+     * @see #getKeywords()
+     * @see Category#DISPLAY
+     * @stable ICU 3.0
+     */
+    public static String getDisplayKeyword(String keyword) {
+        return getDisplayKeywordInternal(keyword, getDefault(Category.DISPLAY));
+    }
+
+    /**
+     * {@icu} Returns a keyword localized for display in the specified locale.
+     * @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(String)
+     * @stable ICU 3.0
+     */
+    public static String getDisplayKeyword(String keyword, String displayLocaleID) {
+        return getDisplayKeywordInternal(keyword, new ULocale(displayLocaleID));
+    }
+
+    /**
+     * {@icu} Returns a keyword localized for display in the specified locale.
+     * @param keyword the keyword to be displayed.
+     * @param displayLocale the locale in which to display the keyword.
+     * @return the localized keyword name.
+     * @see #getKeywords(String)
+     * @stable ICU 3.0
+     */
+    public static String getDisplayKeyword(String keyword, ULocale displayLocale) {
+        return getDisplayKeywordInternal(keyword, displayLocale);
+    }
+
+    private static String getDisplayKeywordInternal(String keyword, ULocale displayLocale) {
+        //#com.ibm.icu.base
+        // No localization
+        return keyword;
+    }
+
+    /**
+     * {@icu} Returns a keyword value localized for display in the default <code>DISPLAY</code> locale.
+     * @param keyword the keyword whose value is to be displayed.
+     * @return the localized value name.
+     * @see Category#DISPLAY
+     * @stable ICU 3.0
+     */
+    public String getDisplayKeywordValue(String keyword) {
+        return getDisplayKeywordValueInternal(this, keyword, getDefault(Category.DISPLAY));
+    }
+
+    /**
+     * {@icu} Returns a keyword value localized for display in the specified locale.
+     * @param keyword the keyword whose value is to be displayed.
+     * @param displayLocale the locale in which to display the value.
+     * @return the localized value name.
+     * @stable ICU 3.0
+     */
+    public String getDisplayKeywordValue(String keyword, ULocale displayLocale) {
+        return getDisplayKeywordValueInternal(this, keyword, displayLocale);
+    }
+
+    /**
+     * {@icu} Returns a keyword value localized for display in the specified locale.
+     * This is a cover for the ICU4C API.
+     * @param localeID the id of the locale whose keyword value is to be displayed.
+     * @param keyword the keyword whose value is to be displayed.
+     * @param displayLocaleID the id of the locale in which to display the value.
+     * @return the localized value name.
+     * @stable ICU 3.0
+     */
+    public static String getDisplayKeywordValue(String localeID, String keyword,
+            String displayLocaleID) {
+        return getDisplayKeywordValueInternal(new ULocale(localeID), keyword,
+                new ULocale(displayLocaleID));
+    }
+
+    /**
+     * {@icu} Returns a keyword value localized for display in the specified locale.
+     * This is a cover for the ICU4C API.
+     * @param localeID the id of the locale whose keyword value is to be displayed.
+     * @param keyword the keyword whose value is to be displayed.
+     * @param displayLocale the id of the locale in which to display the value.
+     * @return the localized value name.
+     * @stable ICU 3.0
+     */
+    public static String getDisplayKeywordValue(String localeID, String keyword,
+            ULocale displayLocale) {
+        return getDisplayKeywordValueInternal(new ULocale(localeID), keyword, displayLocale);
+    }
+
+    // displayLocaleID is canonical, localeID need not be since parsing will fix this.
+    private static String getDisplayKeywordValueInternal(ULocale locale, String keyword,
+            ULocale displayLocale) {
+        //#com.ibm.icu.base
+        keyword = AsciiUtil.toLowerString(keyword.trim());
+        String value = locale.getKeywordValue(keyword);
+        // No localization
+        return value;
+    }
+
+    /**
+     * Returns this locale name localized for display in the default <code>DISPLAY</code> locale.
+     * @return the localized locale name.
+     * @see Category#DISPLAY
+     * @stable ICU 3.0
+     */
+    public String getDisplayName() {
+        return getDisplayNameInternal(this, getDefault(Category.DISPLAY));
+    }
+
+    /**
+     * Returns this locale name localized for display in the provided locale.
+     * @param displayLocale the locale in which to display the locale name.
+     * @return the localized locale name.
+     * @stable ICU 3.0
+     */
+    public String getDisplayName(ULocale displayLocale) {
+        return getDisplayNameInternal(this, displayLocale);
+    }
+
+    /**
+     * Returns the locale ID localized for display in the provided locale.
+     * This is a cover for the ICU4C API.
+     * @param localeID the locale whose name is to be displayed.
+     * @param displayLocaleID the id of the locale in which to display the locale name.
+     * @return the localized locale name.
+     * @stable ICU 3.0
+     */
+    public static String getDisplayName(String localeID, String displayLocaleID) {
+        return getDisplayNameInternal(new ULocale(localeID), new ULocale(displayLocaleID));
+    }
+
+    /**
+     * Returns the locale ID localized for display in the provided locale.
+     * This is a cover for the ICU4C API.
+     * @param localeID the locale whose name is to be displayed.
+     * @param displayLocale the locale in which to display the locale name.
+     * @return the localized locale name.
+     * @stable ICU 3.0
+     */
+    public static String getDisplayName(String localeID, ULocale displayLocale) {
+        return getDisplayNameInternal(new ULocale(localeID), displayLocale);
+    }
+
+    private static String getDisplayNameInternal(ULocale locale, ULocale displayLocale) {
+        //#com.ibm.icu.base
+        return locale.toLocale().getDisplayName(displayLocale.toLocale());
+    }
+
+    /**
+     * {@icu} Returns this locale name localized for display in the default <code>DISPLAY</code> locale.
+     * If a dialect name is present in the locale data, then it is returned.
+     * @return the localized locale name.
+     * @see Category#DISPLAY
+     * @stable ICU 4.4
+     */
+    public String getDisplayNameWithDialect() {
+        return getDisplayNameWithDialectInternal(this, getDefault(Category.DISPLAY));
+    }
+
+    /**
+     * {@icu} Returns this locale name localized for display in the provided locale.
+     * If a dialect name is present in the locale data, then it is returned.
+     * @param displayLocale the locale in which to display the locale name.
+     * @return the localized locale name.
+     * @stable ICU 4.4
+     */
+    public String getDisplayNameWithDialect(ULocale displayLocale) {
+        return getDisplayNameWithDialectInternal(this, displayLocale);
+    }
+
+    /**
+     * {@icu} Returns the locale ID localized for display in the provided locale.
+     * If a dialect name is present in the locale data, then it is returned.
+     * This is a cover for the ICU4C API.
+     * @param localeID the locale whose name is to be displayed.
+     * @param displayLocaleID the id of the locale in which to display the locale name.
+     * @return the localized locale name.
+     * @stable ICU 4.4
+     */
+    public static String getDisplayNameWithDialect(String localeID, String displayLocaleID) {
+        return getDisplayNameWithDialectInternal(new ULocale(localeID),
+                new ULocale(displayLocaleID));
+    }
+
+    /**
+     * {@icu} Returns the locale ID localized for display in the provided locale.
+     * If a dialect name is present in the locale data, then it is returned.
+     * This is a cover for the ICU4C API.
+     * @param localeID the locale whose name is to be displayed.
+     * @param displayLocale the locale in which to display the locale name.
+     * @return the localized locale name.
+     * @stable ICU 4.4
+     */
+    public static String getDisplayNameWithDialect(String localeID, ULocale displayLocale) {
+        return getDisplayNameWithDialectInternal(new ULocale(localeID), displayLocale);
+    }
+
+    private static String getDisplayNameWithDialectInternal(ULocale locale, ULocale displayLocale) {
+        //#com.ibm.icu.base
+        // No dialect handling
+        return locale.toLocale().getDisplayName(displayLocale.toLocale());
+    }
+
+    /**
+     * {@icu} 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.
+     * @stable ICU 4.0
+     */
+    public String getCharacterOrientation() {
+        //#com.ibm.icu.base
+        // Hardcoded
+        String lang = getLanguage();
+        if (lang.equals("ar") || lang.equals("fa") || lang.equals("he") || lang.equals("ps") || lang.equals("ur")) {
+            return "right-to-left";
+        }
+        String script = getScript();
+        if (script.equals("Arab")) {
+            return "right-to-left";
+        }
+        return "left-to-right";
+    }
+
+    /**
+     * {@icu} 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.
+     * @stable ICU 4.0
+     */
+    public String getLineOrientation() {
+        //#com.ibm.icu.base
+        return "top-to-bottom";
+    }
+
+    /**
+     * {@icu} 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();
+
+    /**
+     * {@icu} 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() {}
+    }
+
+  /**
+    * {@icu} 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 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.
+    * @param acceptLanguageList list in HTTP "Accept-Language:" format of acceptable locales
+    * @param availableLocales list of available locales. One of these will be returned.
+    * @param fallback if non-null, a 1-element array containing a boolean to be set with
+    * the fallback status
+    * @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) {
+        if (acceptLanguageList == null) {
+            throw new NullPointerException();
+        }
+        ULocale acceptList[] = null;
+        try {
+            acceptList = parseAcceptLanguage(acceptLanguageList, true);
+        } catch (ParseException pe) {
+            acceptList = null;
+        }
+        if (acceptList == null) {
+            return null;
+        }
+        return acceptLanguage(acceptList, availableLocales, fallback);
+    }
+
+    /**
+    * {@icu} 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 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 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.
+    * @param acceptLanguageList list of acceptable locales
+    * @param availableLocales list of available locales. One of these will be returned.
+    * @param fallback if non-null, a 1-element array containing a boolean to be set with
+    * the fallback status
+    * @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) {
+        // fallbacklist
+        int i,j;
+        if(fallback != null) {
+            fallback[0]=true;
+        }
+        for(i=0;i<acceptLanguageList.length;i++) {
+            ULocale aLocale = acceptLanguageList[i];
+            boolean[] setFallback = fallback;
+            do {
+                for(j=0;j<availableLocales.length;j++) {
+                    if(availableLocales[j].equals(aLocale)) {
+                        if(setFallback != null) {
+                            setFallback[0]=false; // first time with this locale - not a fallback.
+                        }
+                        return availableLocales[j];
+                    }
+                    // compare to scriptless alias, so locales such as
+                    // zh_TW, zh_CN are considered as available locales - see #7190
+                    if (aLocale.getScript().length() == 0
+                            && availableLocales[j].getScript().length() > 0
+                            && availableLocales[j].getLanguage().equals(aLocale.getLanguage())
+                            && availableLocales[j].getCountry().equals(aLocale.getCountry())
+                            && availableLocales[j].getVariant().equals(aLocale.getVariant())) {
+                        ULocale minAvail = ULocale.minimizeSubtags(availableLocales[j]);
+                        if (minAvail.getScript().length() == 0) {
+                            if(setFallback != null) {
+                                setFallback[0] = false; // not a fallback.
+                            }
+                            return aLocale;
+                        }
+                    }
+                }
+                Locale loc = aLocale.toLocale();
+                Locale parent = LocaleUtility.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;
+    }
+
+   /**
+    * {@icu} 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 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.
+    * @param acceptLanguageList list in HTTP "Accept-Language:" format of acceptable locales
+    * @param fallback if non-null, a 1-element array containing a boolean to be set with
+    * the fallback status
+    * @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);
+    }
+
+   /**
+    * {@icu} Based on an ordered array 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 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.
+    * @param acceptLanguageList ordered array of acceptable locales (preferred are listed first)
+    * @param fallback if non-null, a 1-element array containing a boolean to be set with
+    * the fallback status
+    * @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);
+    }
+
+    /**
+     * Package local method used for parsing Accept-Language string
+     */
+    static ULocale[] parseAcceptLanguage(String acceptLanguage, boolean isLenient) 
+        throws ParseException {
+        class ULocaleAcceptLanguageQ implements Comparable<ULocaleAcceptLanguageQ> {
+            private double q;
+            private double serial;
+            public ULocaleAcceptLanguageQ(double theq, int theserial) {
+                q = theq;
+                serial = theserial;
+            }
+            public int compareTo(ULocaleAcceptLanguageQ other) {
+                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<ULocaleAcceptLanguageQ, ULocale> map = 
+            new TreeMap<ULocaleAcceptLanguageQ, ULocale>();
+        StringBuilder languageRangeBuf = new StringBuilder();
+        StringBuilder qvalBuf = new StringBuilder();
+        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);
+                    // sort in reverse order..   1.0, 0.9, 0.8 .. etc
+                    map.put(entry, new ULocale(canonicalize(languageRangeBuf.toString())));
+                }
+
+                // 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[] = map.values().toArray(new ULocale[map.size()]);
+        return acceptList;
+    }
+
+    private static final String UNDEFINED_LANGUAGE = "und";
+
+    /**
+     * {@icu} Adds 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.
+     * @stable ICU 4.0
+     */
+    public static ULocale addLikelySubtags(ULocale loc) {
+        //#com.ibm.icu.base
+        return loc;
+    }
+
+    /**
+     * {@icu} Minimizes the subtags for a provided locale ID, per the algorithm described
+     * in the following CLDR technical report:<blockquote>
+     *
+     *   <a href="http://www.unicode.org/reports/tr35/#Likely_Subtags"
+     *>http://www.unicode.org/reports/tr35/#Likely_Subtags</a></blockquote>
+     *
+     * 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:<pre>
+     *
+     * "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".) </pre>
+     *
+     * @param loc The ULocale to minimize
+     * @return The minimized ULocale instance.
+     * @stable ICU 4.0
+     */
+    public static ULocale minimizeSubtags(ULocale loc) {
+        //#com.ibm.icu.base
+        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 StringBuilder, 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, StringBuilder 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) {
+
+        LocaleIDParser parser = null;
+        boolean regionAppended = false;
+
+        StringBuilder tag = new StringBuilder();
+
+        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 LocaleIDParser(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 LocaleIDParser(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 LocaleIDParser(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);
+    }
+
+    // --------------------------------
+    //      BCP47/OpenJDK APIs
+    // --------------------------------
+
+    /**
+     * {@icu} The key for the private use locale extension ('x').
+     *
+     * @see #getExtension(char)
+     * @see Builder#setExtension(char, String)
+     *
+     * @draft ICU 4.2
+     * @provisional This API might change or be removed in a future release.
+     */
+    public static final char PRIVATE_USE_EXTENSION = 'x';
+
+    /**
+     * {@icu} The key for Unicode locale extension ('u').
+     *
+     * @see #getExtension(char)
+     * @see Builder#setExtension(char, String)
+     *
+     * @draft ICU 4.2
+     * @provisional This API might change or be removed in a future release.
+     */
+    public static final char UNICODE_LOCALE_EXTENSION = 'u';
+
+    /**
+     * {@icu} Returns the extension (or private use) value associated with
+     * the specified key, or null if there is no extension
+     * associated with the key. To be well-formed, the key must be one
+     * of <code>[0-9A-Za-z]</code>. Keys are case-insensitive, so
+     * for example 'z' and 'Z' represent the same extension.
+     *
+     * @param key the extension key
+     * @return The extension, or null if this locale defines no
+     * extension for the specified key.
+     * @throws IllegalArgumentException if key is not well-formed
+     * @see #PRIVATE_USE_EXTENSION
+     * @see #UNICODE_LOCALE_EXTENSION
+     *
+     * @draft ICU 4.2
+     * @provisional This API might change or be removed in a future release.
+     */
+    public String getExtension(char key) {
+        if (!LocaleExtensions.isValidKey(key)) {
+            throw new IllegalArgumentException("Invalid extension key: " + key);
+        }
+        return extensions().getExtensionValue(key);
+    }
+
+    /**
+     * {@icu} Returns the set of extension keys associated with this locale, or the
+     * empty set if it has no extensions. The returned set is unmodifiable.
+     * The keys will all be lower-case.
+     *
+     * @return the set of extension keys, or the empty set if this locale has
+     * no extensions
+     * @draft ICU 4.2
+     * @provisional This API might change or be removed in a future release.
+     */
+    public Set<Character> getExtensionKeys() {
+        return extensions().getKeys();
+    }
+
+    /**
+     * {@icu} Returns the set of unicode locale attributes associated with
+     * this locale, or the empty set if it has no attributes. The
+     * returned set is unmodifiable.
+     *
+     * @return The set of attributes.
+     * @draft ICU 4.6
+     * @provisional This API might change or be removed in a future release.
+     */
+    public Set<String> getUnicodeLocaleAttributes() {
+        return extensions().getUnicodeLocaleAttributes();
+    }
+
+    /**
+     * {@icu} Returns the Unicode locale type associated with the specified Unicode locale key
+     * for this locale. Returns the empty string for keys that are defined with no type.
+     * Returns null if the key is not defined. Keys are case-insensitive. The key must
+     * be two alphanumeric characters ([0-9a-zA-Z]), or an IllegalArgumentException is
+     * thrown.
+     *
+     * @param key the Unicode locale key
+     * @return The Unicode locale type associated with the key, or null if the
+     * locale does not define the key.
+     * @throws IllegalArgumentException if the key is not well-formed
+     * @throws NullPointerException if <code>key</code> is null
+     * 
+     * @draft ICU 4.4
+     * @provisional This API might change or be removed in a future release.
+     */
+    public String getUnicodeLocaleType(String key) {
+        if (!LocaleExtensions.isValidUnicodeLocaleKey(key)) {
+            throw new IllegalArgumentException("Invalid Unicode locale key: " + key);
+        }
+        return extensions().getUnicodeLocaleType(key);
+    }
+
+    /**
+     * {@icu} Returns the set of Unicode locale keys defined by this locale, or the empty set if
+     * this locale has none.  The returned set is immutable.  Keys are all lower case.
+     *
+     * @return The set of Unicode locale keys, or the empty set if this locale has
+     * no Unicode locale keywords.
+     * 
+     * @draft ICU 4.4
+     * @provisional This API might change or be removed in a future release.
+     */
+    public Set<String> getUnicodeLocaleKeys() {
+        return extensions().getUnicodeLocaleKeys();
+    }
+
+    /**
+     * {@icu} Returns a well-formed IETF BCP 47 language tag representing
+     * this locale.
+     *
+     * <p>If this <code>ULocale</code> has a language, script, country, or
+     * variant that does not satisfy the IETF BCP 47 language tag
+     * syntax requirements, this method handles these fields as
+     * described below:
+     *
+     * <p><b>Language:</b> If language is empty, or not well-formed
+     * (for example "a" or "e2"), it will be emitted as "und" (Undetermined).
+     *
+     * <p><b>Script:</b> If script is not well-formed (for example "12"
+     * or "Latin"), it will be omitted.
+     * 
+     * <p><b>Country:</b> If country is not well-formed (for example "12"
+     * or "USA"), it will be omitted.
+     *
+     * <p><b>Variant:</b> If variant <b>is</b> well-formed, each sub-segment
+     * (delimited by '-' or '_') is emitted as a subtag.  Otherwise:
+     * <ul>
+     *
+     * <li>if all sub-segments match <code>[0-9a-zA-Z]{1,8}</code>
+     * (for example "WIN" or "Oracle_JDK_Standard_Edition"), the first
+     * ill-formed sub-segment and all following will be appended to
+     * the private use subtag.  The first appended subtag will be
+     * "lvariant", followed by the sub-segments in order, separated by
+     * hyphen. For example, "x-lvariant-WIN",
+     * "Oracle-x-lvariant-JDK-Standard-Edition".
+     *
+     * <li>if any sub-segment does not match
+     * <code>[0-9a-zA-Z]{1,8}</code>, the variant will be truncated
+     * and the problematic sub-segment and all following sub-segments
+     * will be omitted.  If the remainder is non-empty, it will be
+     * emitted as a private use subtag as above (even if the remainder
+     * turns out to be well-formed).  For example,
+     * "Solaris_isjustthecoolestthing" is emitted as
+     * "x-lvariant-Solaris", not as "solaris".</li></ul>
+     *
+     * <p><b>Note:</b> Although the language tag created by this
+     * method is well-formed (satisfies the syntax requirements
+     * defined by the IETF BCP 47 specification), it is not
+     * necessarily a valid BCP 47 language tag.  For example,
+     * <pre>
+     *   new Locale("xx", "YY").toLanguageTag();</pre>
+     * 
+     * will return "xx-YY", but the language subtag "xx" and the
+     * region subtag "YY" are invalid because they are not registered
+     * in the IANA Language Subtag Registry.
+     *
+     * @return a BCP47 language tag representing the locale
+     * @see #forLanguageTag(String)
+     *
+     * @draft ICU 4.2
+     * @provisional This API might change or be removed in a future release.
+     */
+    public String toLanguageTag() {
+        BaseLocale base = base();
+        LocaleExtensions exts = extensions();
+
+        if (base.getVariant().equalsIgnoreCase("POSIX")) {
+            // special handling for variant POSIX
+            base = BaseLocale.getInstance(base.getLanguage(), base.getScript(), base.getRegion(), "");
+            if (exts.getUnicodeLocaleType("va") == null) {
+                // add va-posix
+                InternalLocaleBuilder ilocbld = new InternalLocaleBuilder();
+                try {
+                    ilocbld.setLocale(BaseLocale.ROOT, exts);
+                    ilocbld.setUnicodeLocaleKeyword("va", "posix");
+                    exts = ilocbld.getLocaleExtensions();
+                } catch (LocaleSyntaxException e) {
+                    // this should not happen
+                    throw new RuntimeException(e);
+                }
+            }
+        }
+
+        LanguageTag tag = LanguageTag.parseLocale(base, exts);
+
+        StringBuilder buf = new StringBuilder();
+        String subtag = tag.getLanguage();
+        if (subtag.length() > 0) {
+            buf.append(LanguageTag.canonicalizeLanguage(subtag));
+        }
+ 
+        subtag = tag.getScript();
+        if (subtag.length() > 0) {
+            buf.append(LanguageTag.SEP);
+            buf.append(LanguageTag.canonicalizeScript(subtag));
+        }
+
+        subtag = tag.getRegion();
+        if (subtag.length() > 0) {
+            buf.append(LanguageTag.SEP);
+            buf.append(LanguageTag.canonicalizeRegion(subtag));
+        }
+
+        List<String>subtags = tag.getVariants();
+        for (String s : subtags) {
+            buf.append(LanguageTag.SEP);
+            buf.append(LanguageTag.canonicalizeVariant(s));
+        }
+
+        subtags = tag.getExtensions();
+        for (String s : subtags) {
+            buf.append(LanguageTag.SEP);
+            buf.append(LanguageTag.canonicalizeExtension(s));
+        }
+
+        subtag = tag.getPrivateuse();
+        if (subtag.length() > 0) {
+            if (buf.length() > 0) {
+                buf.append(LanguageTag.SEP);
+            }
+            buf.append(LanguageTag.PRIVATEUSE).append(LanguageTag.SEP);
+            buf.append(LanguageTag.canonicalizePrivateuse(subtag));
+        }
+
+        return buf.toString();
+    }
+
+    /**
+     * {@icu} Returns a locale for the specified IETF BCP 47 language tag string.
+     *
+     * <p>If the specified language tag contains any ill-formed subtags,
+     * the first such subtag and all following subtags are ignored.  Compare
+     * to {@link ULocale.Builder#setLanguageTag} which throws an exception
+     * in this case.
+     *
+     * <p>The following <b>conversions</b> are performed:<ul>
+     *
+     * <li>The language code "und" is mapped to language "".
+     *
+     * <li>The portion of a private use subtag prefixed by "lvariant",
+     * if any, is removed and appended to the variant field in the
+     * result locale (without case normalization).  If it is then
+     * empty, the private use subtag is discarded:
+     *
+     * <pre>
+     *     ULocale loc;
+     *     loc = ULocale.forLanguageTag("en-US-x-lvariant-icu4j);
+     *     loc.getVariant(); // returns "ICU4J"
+     *     loc.getExtension('x'); // returns null
+     *
+     *     loc = Locale.forLanguageTag("de-icu4j-x-URP-lvariant-Abc-Def");
+     *     loc.getVariant(); // returns "ICU4J_ABC_DEF"
+     *     loc.getExtension('x'); // returns "urp"
+     * </pre>
+     *
+     * <li>When the languageTag argument contains an extlang subtag,
+     * the first such subtag is used as the language, and the primary
+     * language subtag and other extlang subtags are ignored:
+     *
+     * <pre>
+     *     ULocale.forLanguageTag("ar-aao").getLanguage(); // returns "aao"
+     *     ULocale.forLanguageTag("en-abc-def-us").toString(); // returns "abc_US"
+     * </pre>
+     *
+     * <li>Case is normalized. Language is normalized to lower case,
+     * script to title case, country to upper case, variant to upper case,
+     * and extensions to lower case.
+     *
+     * <p>This implements the 'Language-Tag' production of BCP47, and
+     * so supports grandfathered (regular and irregular) as well as
+     * private use language tags.  Stand alone private use tags are
+     * represented as empty language and extension 'x-whatever',
+     * and grandfathered tags are converted to their canonical replacements
+     * where they exist.  
+     *
+     * <p>Grandfathered tags with canonical replacements are as follows:
+     *
+     * <table>
+     * <tbody align="center">
+     * <tr><th>grandfathered tag</th><th>&nbsp;</th><th>modern replacement</th></tr>
+     * <tr><td>art-lojban</td><td>&nbsp;</td><td>jbo</td></tr>
+     * <tr><td>i-ami</td><td>&nbsp;</td><td>ami</td></tr>
+     * <tr><td>i-bnn</td><td>&nbsp;</td><td>bnn</td></tr>
+     * <tr><td>i-hak</td><td>&nbsp;</td><td>hak</td></tr>
+     * <tr><td>i-klingon</td><td>&nbsp;</td><td>tlh</td></tr>
+     * <tr><td>i-lux</td><td>&nbsp;</td><td>lb</td></tr>
+     * <tr><td>i-navajo</td><td>&nbsp;</td><td>nv</td></tr>
+     * <tr><td>i-pwn</td><td>&nbsp;</td><td>pwn</td></tr>
+     * <tr><td>i-tao</td><td>&nbsp;</td><td>tao</td></tr>
+     * <tr><td>i-tay</td><td>&nbsp;</td><td>tay</td></tr>
+     * <tr><td>i-tsu</td><td>&nbsp;</td><td>tsu</td></tr>
+     * <tr><td>no-bok</td><td>&nbsp;</td><td>nb</td></tr>
+     * <tr><td>no-nyn</td><td>&nbsp;</td><td>nn</td></tr>
+     * <tr><td>sgn-BE-FR</td><td>&nbsp;</td><td>sfb</td></tr>
+     * <tr><td>sgn-BE-NL</td><td>&nbsp;</td><td>vgt</td></tr>
+     * <tr><td>sgn-CH-DE</td><td>&nbsp;</td><td>sgg</td></tr>
+     * <tr><td>zh-guoyu</td><td>&nbsp;</td><td>cmn</td></tr>
+     * <tr><td>zh-hakka</td><td>&nbsp;</td><td>hak</td></tr>
+     * <tr><td>zh-min-nan</td><td>&nbsp;</td><td>nan</td></tr>
+     * <tr><td>zh-xiang</td><td>&nbsp;</td><td>hsn</td></tr>
+     * </tbody>
+     * </table>
+     *
+     * <p>Grandfathered tags with no modern replacement will be
+     * converted as follows:
+     *
+     * <table>
+     * <tbody align="center">
+     * <tr><th>grandfathered tag</th><th>&nbsp;</th><th>converts to</th></tr>
+     * <tr><td>cel-gaulish</td><td>&nbsp;</td><td>xtg-x-cel-gaulish</td></tr>
+     * <tr><td>en-GB-oed</td><td>&nbsp;</td><td>en-GB-x-oed</td></tr>
+     * <tr><td>i-default</td><td>&nbsp;</td><td>en-x-i-default</td></tr>
+     * <tr><td>i-enochian</td><td>&nbsp;</td><td>und-x-i-enochian</td></tr>
+     * <tr><td>i-mingo</td><td>&nbsp;</td><td>see-x-i-mingo</td></tr>
+     * <tr><td>zh-min</td><td>&nbsp;</td><td>nan-x-zh-min</td></tr>
+     * </tbody>
+     * </table>
+     *
+     * <p>For a list of all grandfathered tags, see the
+     * IANA Language Subtag Registry (search for "Type: grandfathered").
+     *
+     * <p><b>Note</b>: there is no guarantee that <code>toLanguageTag</code>
+     * and <code>forLanguageTag</code> will round-trip.
+     *
+     * @param languageTag the language tag
+     * @return The locale that best represents the language tag.
+     * @throws NullPointerException if <code>languageTag</code> is <code>null</code>
+     * @see #toLanguageTag()
+     * @see ULocale.Builder#setLanguageTag(String)
+     *
+     * @draft ICU 4.2
+     * @provisional This API might change or be removed in a future release.
+     */
+    public static ULocale forLanguageTag(String languageTag) {
+        LanguageTag tag = LanguageTag.parse(languageTag, null);
+        InternalLocaleBuilder bldr = new InternalLocaleBuilder();
+        bldr.setLanguageTag(tag);
+        return getInstance(bldr.getBaseLocale(), bldr.getLocaleExtensions());
+    }
+
+
+    /**
+     * <code>Builder</code> is used to build instances of <code>ULocale</code>
+     * from values configured by the setters.  Unlike the <code>ULocale</code>
+     * constructors, the <code>Builder</code> checks if a value configured by a
+     * setter satisfies the syntax requirements defined by the <code>ULocale</code>
+     * class.  A <code>ULocale</code> object created by a <code>Builder</code> is
+     * well-formed and can be transformed to a well-formed IETF BCP 47 language tag
+     * without losing information.
+     *
+     * <p><b>Note:</b> The <code>ULocale</code> class does not provide any
+     * syntactic restrictions on variant, while BCP 47 requires each variant
+     * subtag to be 5 to 8 alphanumerics or a single numeric followed by 3
+     * alphanumerics.  The method <code>setVariant</code> throws
+     * <code>IllformedLocaleException</code> for a variant that does not satisfy
+     * this restriction. If it is necessary to support such a variant, use a
+     * ULocale constructor.  However, keep in mind that a <code>ULocale</code>
+     * object created this way might lose the variant information when
+     * transformed to a BCP 47 language tag.
+     *
+     * <p>The following example shows how to create a <code>Locale</code> object
+     * with the <code>Builder</code>.
+     * <blockquote>
+     * <pre>
+     *     ULocale aLocale = new Builder().setLanguage("sr").setScript("Latn").setRegion("RS").build();
+     * </pre>
+     * </blockquote>
+     *
+     * <p>Builders can be reused; <code>clear()</code> resets all
+     * fields to their default values.
+     *
+     * @see ULocale#toLanguageTag()
+     *
+     * @draft ICU 4.2
+     * @provisional This API might change or be removed in a future release.
+     */
+    public static final class Builder {
+
+        private final InternalLocaleBuilder _locbld;
+
+        /**
+         * Constructs an empty Builder. The default value of all
+         * fields, extensions, and private use information is the
+         * empty string.
+         *
+         * @draft ICU 4.2
+         * @provisional This API might change or be removed in a future release.
+         */
+        public Builder() {
+            _locbld = new InternalLocaleBuilder();
+        }
+
+        /**
+         * Resets the <code>Builder</code> to match the provided
+         * <code>locale</code>.  Existing state is discarded.
+         *
+         * <p>All fields of the locale must be well-formed, see {@link Locale}.
+         *
+         * <p>Locales with any ill-formed fields cause
+         * <code>IllformedLocaleException</code> to be thrown.
+         *
+         * @param locale the locale
+         * @return This builder.
+         * @throws IllformedLocaleException if <code>locale</code> has
+         * any ill-formed fields.
+         * @throws NullPointerException if <code>locale</code> is null.
+         *
+         * @draft ICU 4.2
+         * @provisional This API might change or be removed in a future release.
+         */
+        public Builder setLocale(ULocale locale) {
+            try {
+                _locbld.setLocale(locale.base(), locale.extensions());
+            } catch (LocaleSyntaxException e) {
+                throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
+            }
+            return this;
+        }
+
+        /**
+         * Resets the Builder to match the provided IETF BCP 47
+         * language tag.  Discards the existing state.  Null and the
+         * empty string cause the builder to be reset, like {@link
+         * #clear}.  Grandfathered tags (see {@link
+         * ULocale#forLanguageTag}) are converted to their canonical
+         * form before being processed.  Otherwise, the language tag
+         * must be well-formed (see {@link ULocale}) or an exception is
+         * thrown (unlike <code>ULocale.forLanguageTag</code>, which
+         * just discards ill-formed and following portions of the
+         * tag).
+         *
+         * @param languageTag the language tag
+         * @return This builder.
+         * @throws IllformedLocaleException if <code>languageTag</code> is ill-formed
+         * @see ULocale#forLanguageTag(String)
+         *
+         * @draft ICU 4.2
+         * @provisional This API might change or be removed in a future release.
+         */
+        public Builder setLanguageTag(String languageTag) {
+            ParseStatus sts = new ParseStatus();
+            LanguageTag tag = LanguageTag.parse(languageTag, sts);
+            if (sts.isError()) {
+                throw new IllformedLocaleException(sts.getErrorMessage(), sts.getErrorIndex());
+            }
+            _locbld.setLanguageTag(tag);
+
+            return this;
+        }
+
+        /**
+         * Sets the language.  If <code>language</code> is the empty string or
+         * null, the language in this <code>Builder</code> is removed.  Otherwise,
+         * the language must be <a href="./Locale.html#def_language">well-formed</a>
+         * or an exception is thrown.
+         *
+         * <p>The typical language value is a two or three-letter language
+         * code as defined in ISO639.
+         *
+         * @param language the language
+         * @return This builder.
+         * @throws IllformedLocaleException if <code>language</code> is ill-formed
+         *
+         * @draft ICU 4.2
+         * @provisional This API might change or be removed in a future release.
+         */
+        public Builder setLanguage(String language) {
+            try {
+                _locbld.setLanguage(language);
+            } catch (LocaleSyntaxException e) {
+                throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
+            }
+            return this;
+        }
+
+        /**
+         * Sets the script. If <code>script</code> is null or the empty string,
+         * the script in this <code>Builder</code> is removed.
+         * Otherwise, the script must be well-formed or an exception is thrown.
+         *
+         * <p>The typical script value is a four-letter script code as defined by ISO 15924.
+         *
+         * @param script the script
+         * @return This builder.
+         * @throws IllformedLocaleException if <code>script</code> is ill-formed
+         *
+         * @draft ICU 4.2
+         * @provisional This API might change or be removed in a future release.
+         */
+        public Builder setScript(String script) {
+            try {
+                _locbld.setScript(script);
+            } catch (LocaleSyntaxException e) {
+                throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
+            }
+            return this;
+        }
+
+        /**
+         * Sets the region.  If region is null or the empty string, the region
+         * in this <code>Builder</code> is removed.  Otherwise,
+         * the region must be well-formed or an exception is thrown.
+         *
+         * <p>The typical region value is a two-letter ISO 3166 code or a
+         * three-digit UN M.49 area code.
+         *
+         * <p>The country value in the <code>Locale</code> created by the
+         * <code>Builder</code> is always normalized to upper case.
+         *
+         * @param region the region
+         * @return This builder.
+         * @throws IllformedLocaleException if <code>region</code> is ill-formed
+         *
+         * @draft ICU 4.2
+         * @provisional This API might change or be removed in a future release.
+         */
+        public Builder setRegion(String region) {
+            try {
+                _locbld.setRegion(region);
+            } catch (LocaleSyntaxException e) {
+                throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
+            }
+            return this;
+        }
+
+        /**
+         * Sets the variant.  If variant is null or the empty string, the
+         * variant in this <code>Builder</code> is removed.  Otherwise, it
+         * must consist of one or more well-formed subtags, or an exception is thrown.
+         *
+         * <p><b>Note:</b> This method checks if <code>variant</code>
+         * satisfies the IETF BCP 47 variant subtag's syntax requirements,
+         * and normalizes the value to lowercase letters.  However,
+         * the <code>ULocale</code> class does not impose any syntactic
+         * restriction on variant.  To set such a variant,
+         * use a ULocale constructor.
+         *
+         * @param variant the variant
+         * @return This builder.
+         * @throws IllformedLocaleException if <code>variant</code> is ill-formed
+         *
+         * @draft ICU 4.2
+         * @provisional This API might change or be removed in a future release.
+         */
+        public Builder setVariant(String variant) {
+            try {
+                _locbld.setVariant(variant);
+            } catch (LocaleSyntaxException e) {
+                throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
+            }
+            return this;
+        }
+
+        /**
+         * Sets the extension for the given key. If the value is null or the
+         * empty string, the extension is removed.  Otherwise, the extension
+         * must be well-formed or an exception is thrown.
+         *
+         * <p><b>Note:</b> The key {@link ULocale#UNICODE_LOCALE_EXTENSION
+         * UNICODE_LOCALE_EXTENSION} ('u') is used for the Unicode locale extension.
+         * Setting a value for this key replaces any existing Unicode locale key/type
+         * pairs with those defined in the extension.
+         *
+         * <p><b>Note:</b> The key {@link ULocale#PRIVATE_USE_EXTENSION
+         * PRIVATE_USE_EXTENSION} ('x') is used for the private use code. To be
+         * well-formed, the value for this key needs only to have subtags of one to
+         * eight alphanumeric characters, not two to eight as in the general case.
+         *
+         * @param key the extension key
+         * @param value the extension value
+         * @return This builder.
+         * @throws IllformedLocaleException if <code>key</code> is illegal
+         * or <code>value</code> is ill-formed
+         * @see #setUnicodeLocaleKeyword(String, String)
+         *
+         * @draft ICU 4.2
+         * @provisional This API might change or be removed in a future release.
+         */
+        public Builder setExtension(char key, String value) {
+            try {
+                _locbld.setExtension(key, value);
+            } catch (LocaleSyntaxException e) {
+                throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
+            }
+            return this;
+        }
+
+        /**
+         * Sets the Unicode locale keyword type for the given key.  If the type
+         * is null, the Unicode keyword is removed.  Otherwise, the key must be
+         * non-null and both key and type must be well-formed or an exception
+         * is thrown.
+         *
+         * <p>Keys and types are converted to lower case.
+         *
+         * <p><b>Note</b>:Setting the 'u' extension via {@link #setExtension}
+         * replaces all Unicode locale keywords with those defined in the
+         * extension.
+         *
+         * @param key the Unicode locale key
+         * @param type the Unicode locale type
+         * @return This builder.
+         * @throws IllformedLocaleException if <code>key</code> or <code>type</code>
+         * is ill-formed
+         * @throws NullPointerException if <code>key</code> is null
+         * @see #setExtension(char, String)
+         *
+         * @draft ICU 4.4
+         * @provisional This API might change or be removed in a future release.
+         */
+        public Builder setUnicodeLocaleKeyword(String key, String type) {
+            try {
+                _locbld.setUnicodeLocaleKeyword(key, type);
+            } catch (LocaleSyntaxException e) {
+                throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
+            }
+            return this;
+        }
+
+        /**
+         * Adds a unicode locale attribute, if not already present, otherwise
+         * has no effect.  The attribute must not be null and must be well-formed
+         * or an exception is thrown.
+         *
+         * @param attribute the attribute
+         * @return This builder.
+         * @throws NullPointerException if <code>attribute</code> is null
+         * @throws IllformedLocaleException if <code>attribute</code> is ill-formed
+         * @see #setExtension(char, String)
+         *
+         * @draft ICU 4.6
+         * @provisional This API might change or be removed in a future release.
+         */
+        public Builder addUnicodeLocaleAttribute(String attribute) {
+            try {
+                _locbld.addUnicodeLocaleAttribute(attribute);
+            } catch (LocaleSyntaxException e) {
+                throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
+            }
+            return this;
+        }
+
+        /**
+         * Removes a unicode locale attribute, if present, otherwise has no
+         * effect.  The attribute must not be null and must be well-formed
+         * or an exception is thrown.
+         *
+         * <p>Attribute comparision for removal is case-insensitive.
+         *
+         * @param attribute the attribute
+         * @return This builder.
+         * @throws NullPointerException if <code>attribute</code> is null
+         * @throws IllformedLocaleException if <code>attribute</code> is ill-formed
+         * @see #setExtension(char, String)
+         *
+         * @draft ICU 4.6
+         * @provisional This API might change or be removed in a future release.
+         */
+        public Builder removeUnicodeLocaleAttribute(String attribute) {
+            try {
+                _locbld.removeUnicodeLocaleAttribute(attribute);
+            } catch (LocaleSyntaxException e) {
+                throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
+            }
+            return this;
+        }
+
+        /**
+         * Resets the builder to its initial, empty state.
+         *
+         * @return this builder
+         *
+         * @draft ICU 4.2
+         * @provisional This API might change or be removed in a future release.
+         */
+        public Builder clear() {
+            _locbld.clear();
+            return this;
+        }
+
+        /**
+         * Resets the extensions to their initial, empty state.
+         * Language, script, region and variant are unchanged.
+         *
+         * @return this builder
+         * @see #setExtension(char, String)
+         *
+         * @draft ICU 4.2
+         * @provisional This API might change or be removed in a future release.
+         */
+        public Builder clearExtensions() {
+            _locbld.clearExtensions();
+            return this;
+        }
+
+        /**
+         * Returns an instance of <code>ULocale</code> created from the fields set
+         * on this builder.
+         *
+         * @return a new Locale
+         *
+         * @draft ICU 4.4
+         * @provisional This API might change or be removed in a future release.
+         */
+        public ULocale build() {
+            return getInstance(_locbld.getBaseLocale(), _locbld.getLocaleExtensions());
+        }
+    }
+
+    private static ULocale getInstance(BaseLocale base, LocaleExtensions exts) {
+        String id = lscvToID(base.getLanguage(), base.getScript(), base.getRegion(),
+                base.getVariant());
+
+        Set<Character> extKeys = exts.getKeys();
+        if (!extKeys.isEmpty()) {
+            // legacy locale ID assume Unicode locale keywords and
+            // other extensions are at the same level.
+            // e.g. @a=ext-for-aa;calendar=japanese;m=ext-for-mm;x=priv-use
+
+            TreeMap<String, String> kwds = new TreeMap<String, String>();
+            for (Character key : extKeys) {
+                Extension ext = exts.getExtension(key);
+                if (ext instanceof UnicodeLocaleExtension) {
+                    UnicodeLocaleExtension uext = (UnicodeLocaleExtension)ext;
+                    Set<String> ukeys = uext.getUnicodeLocaleKeys();
+                    for (String bcpKey : ukeys) {
+                        String bcpType = uext.getUnicodeLocaleType(bcpKey);
+                        // convert to legacy key/type
+                        String lkey = bcp47ToLDMLKey(bcpKey);
+                        String ltype = bcp47ToLDMLType(lkey, ((bcpType.length() == 0) ? "true" : bcpType)); // use "true" as the value of typeless keywords
+                        // special handling for u-va-posix, since this is a variant, not a keyword
+                        if (lkey.equals("va") && ltype.equals("posix") && base.getVariant().length() == 0) {
+                            id = id + "_POSIX";
+                        } else {
+                            kwds.put(lkey, ltype);
+                        }
+                    }
+                    // Mapping Unicode locale attribute to the special keyword, attribute=xxx-yyy
+                    Set<String> uattributes = uext.getUnicodeLocaleAttributes();
+                    if (uattributes.size() > 0) {
+                        StringBuilder attrbuf = new StringBuilder();
+                        for (String attr : uattributes) {
+                            if (attrbuf.length() > 0) {
+                                attrbuf.append('-');
+                            }
+                            attrbuf.append(attr);
+                        }
+                        kwds.put(LOCALE_ATTRIBUTE_KEY, attrbuf.toString());
+                    }
+                } else {
+                    kwds.put(String.valueOf(key), ext.getValue());
+                }
+            }
+
+            if (!kwds.isEmpty()) {
+                StringBuilder buf = new StringBuilder(id);
+                buf.append("@");
+                Set<Map.Entry<String, String>> kset = kwds.entrySet();
+                boolean insertSep = false;
+                for (Map.Entry<String, String> kwd : kset) {
+                    if (insertSep) {
+                        buf.append(";");
+                    } else {
+                        insertSep = true;
+                    }
+                    buf.append(kwd.getKey());
+                    buf.append("=");
+                    buf.append(kwd.getValue());
+                }
+
+                id = buf.toString();
+            }
+        }
+        return new ULocale(id);
+    }
+
+    private BaseLocale base() {
+        if (baseLocale == null) {
+            String language = getLanguage();
+            if (equals(ULocale.ROOT)) {
+                language = "";
+            }
+            baseLocale = BaseLocale.getInstance(language, getScript(), getCountry(), getVariant());
+        }
+        return baseLocale;
+    }
+
+    private LocaleExtensions extensions() {
+        if (extensions == null) {
+            Iterator<String> kwitr = getKeywords();
+            if (kwitr == null) {
+                extensions = LocaleExtensions.EMPTY_EXTENSIONS;
+            } else {
+                InternalLocaleBuilder intbld = new InternalLocaleBuilder();
+                while (kwitr.hasNext()) {
+                    String key = kwitr.next();
+                    if (key.equals(LOCALE_ATTRIBUTE_KEY)) {
+                        // special keyword used for representing Unicode locale attributes
+                        String[] uattributes = getKeywordValue(key).split("[-_]");
+                        for (String uattr : uattributes) {
+                            try {
+                                intbld.addUnicodeLocaleAttribute(uattr);
+                            } catch (LocaleSyntaxException e) {
+                                // ignore and fall through
+                            }
+                        }
+                    } else if (key.length() >= 2) {
+                        String bcpKey = ldmlKeyToBCP47(key);
+                        String bcpType = ldmlTypeToBCP47(key, getKeywordValue(key));
+                        if (bcpKey != null && bcpType != null) {
+                            try {
+                                intbld.setUnicodeLocaleKeyword(bcpKey, bcpType);
+                            } catch (LocaleSyntaxException e) {
+                                // ignore and fall through
+                            }
+                        }
+                    } else if (key.length() == 1 && (key.charAt(0) != UNICODE_LOCALE_EXTENSION)) {
+                        try  {
+                            intbld.setExtension(key.charAt(0), getKeywordValue(key).replace("_",
+                                    LanguageTag.SEP));
+                        } catch (LocaleSyntaxException e) {
+                            // ignore and fall through
+                        }
+                    }
+                }
+                extensions = intbld.getLocaleExtensions();
+            }
+        }
+        return extensions;
+    }
+
+    //
+    // LDML legacy/BCP47 key and type mapping functions
+    //
+    private static String ldmlKeyToBCP47(String key) {
+        //#com.ibm.icu.base
+        // normalize key to lowercase
+        key = AsciiUtil.toLowerString(key);
+        String bcpKey = null;
+
+        for (int i = 0; i < KEYMAP.length; i += 2) {
+            if (key.equals(KEYMAP[i])) {
+                bcpKey = KEYMAP[i + 1];
+                break;
+            }
+        }
+
+        if (bcpKey == null) {
+            if (key.length() == 2 && LanguageTag.isExtensionSubtag(key)) {
+                return key;
+            }
+            return null;
+        }
+
+        return bcpKey;
+    }
+
+    private static String bcp47ToLDMLKey(String bcpKey) {
+        //#com.ibm.icu.base
+        // normalize bcp key to lowercase
+        bcpKey = AsciiUtil.toLowerString(bcpKey);
+        String key = null;
+
+        for (int i = 0; i < KEYMAP.length; i += 2) {
+            if (bcpKey.equals(KEYMAP[i + 1])) {
+                key = KEYMAP[i];
+                break;
+            }
+        }
+
+        if (key == null) {
+            return bcpKey;
+        }
+
+        return key;
+    }
+
+    private static String ldmlTypeToBCP47(String key, String type) {
+        //#com.ibm.icu.base
+
+        // keys are case-insensitive, while types are case-sensitive
+        key = AsciiUtil.toLowerString(key);
+        String bcpType = null;
+        String[] map = null;
+        String[] aliasMap = null;
+
+        if (key.equals("calendar")) {
+            map = TYPEMAP_CALENDAR;
+        } else if (key.equals("colalternate")) {
+            map = TYPEMAP_COLALTERNATE;
+        } else if (key.equals("colbackwards")) {
+            map = TYPEMAP_COLBACKWARDS;
+        } else if (key.equals("colcasefirst")) {
+            map = TYPEMAP_COLCASEFIRST;
+        } else if (key.equals("colcaselevel")) {
+            map = TYPEMAP_COLCASELEVEL;
+        } else if (key.equals("colhiraganaquaternary")) {
+            map = TYPEMAP_COLHIRAGANAQUATERNARY;
+        } else if (key.equals("collation")) {
+            map = TYPEMAP_COLLATION;
+        } else if (key.equals("colnormalization")) {
+            map = TYPEMAP_COLNORMALIZATION;
+        } else if (key.equals("colnumeric")) {
+            map = TYPEMAP_COLNUMERIC;
+        } else if (key.equals("colstrength")) {
+            map = TYPEMAP_COLSTRENGTH;
+            aliasMap = TYPEALIAS_COLSTRENGTH;
+        } else if (key.equals("timezone")) {
+            map = TYPEMAP_TIMEZONE;
+            aliasMap = TYPEALIAS_TIMEZONE;
+        }
+
+        // LDML alias -> LDML canonical
+        if (aliasMap != null) {
+            for (int i = 0; i < aliasMap.length; i += 2) {
+                if (type.equals(aliasMap[i])) {
+                    type = aliasMap[i + 1];
+                    break;
+                }
+            }
+        }
+
+        // LDML type -> BCP47 type
+        if (map != null) {
+            for (int i = 0; i < map.length; i += 2) {
+                if (type.equals(map[i])) {
+                    bcpType = map[i + 1];
+                    break;
+                }
+            }
+        }
+
+        if (bcpType == null) {
+            int typeLen = type.length();
+            if (typeLen >= 3 && typeLen <= 8 && LanguageTag.isExtensionSubtag(type)) {
+                return type;
+            }
+            return null;
+        }
+        return bcpType;
+    }
+
+    private static String bcp47ToLDMLType(String key, String bcpType) {
+        //#com.ibm.icu.base
+
+        // normalize key/bcpType to lowercase
+        key = AsciiUtil.toLowerString(key);
+        bcpType = AsciiUtil.toLowerString(bcpType);
+        String type = null;
+        String[] map = null;
+
+        if (key.equals("calendar")) {
+            map = TYPEMAP_CALENDAR;
+        } else if (key.equals("colalternate")) {
+            map = TYPEMAP_COLALTERNATE;
+        } else if (key.equals("colbackwards")) {
+            map = TYPEMAP_COLBACKWARDS;
+        } else if (key.equals("colcasefirst")) {
+            map = TYPEMAP_COLCASEFIRST;
+        } else if (key.equals("colcaselevel")) {
+            map = TYPEMAP_COLCASELEVEL;
+        } else if (key.equals("colhiraganaquaternary")) {
+            map = TYPEMAP_COLHIRAGANAQUATERNARY;
+        } else if (key.equals("collation")) {
+            map = TYPEMAP_COLLATION;
+        } else if (key.equals("colnormalization")) {
+            map = TYPEMAP_COLNORMALIZATION;
+        } else if (key.equals("colnumeric")) {
+            map = TYPEMAP_COLNUMERIC;
+        } else if (key.equals("colstrength")) {
+            map = TYPEMAP_COLSTRENGTH;
+        } else if (key.equals("timezone")) {
+            map = TYPEMAP_TIMEZONE;
+        }
+
+        if (map != null) {
+            for (int i = 0; i < map.length; i += 2) {
+                if (bcpType.equals(map[i + 1])) {
+                    type = map[i];
+                    break;
+                }
+            }
+        }
+
+        return (type != null) ? type : bcpType;
+    }
+
+    /*
+     * JDK Locale Helper
+     */
+    private static final class JDKLocaleHelper {
+        private static boolean isJava7orNewer = false;
+
+        /*
+         * New methods in Java 7 Locale class
+         */
+        private static Method mGetScript;
+        private static Method mGetExtensionKeys;
+        private static Method mGetExtension;
+        private static Method mGetUnicodeLocaleKeys;
+        private static Method mGetUnicodeLocaleAttributes;
+        private static Method mGetUnicodeLocaleType;
+        private static Method mForLanguageTag;
+
+        private static Method mGetDefault;
+        private static Method mSetDefault;
+        private static Object eDISPLAY;
+        private static Object eFORMAT;
+
+        /*
+         * This table is used for mapping between ICU and special Java
+         * 6 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[][] JAVA6_MAPDATA = {
+        //  { <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",    "numbers",  "thai",     "th"},
+        };
+
+        static {
+            do {
+                try {
+                    mGetScript = Locale.class.getMethod("getScript", (Class[]) null);
+                    mGetExtensionKeys = Locale.class.getMethod("getExtensionKeys", (Class[]) null);
+                    mGetExtension = Locale.class.getMethod("getExtension", char.class);
+                    mGetUnicodeLocaleKeys = Locale.class.getMethod("getUnicodeLocaleKeys", (Class[]) null);
+                    mGetUnicodeLocaleAttributes = Locale.class.getMethod("getUnicodeLocaleAttributes", (Class[]) null);
+                    mGetUnicodeLocaleType = Locale.class.getMethod("getUnicodeLocaleType", String.class);
+                    mForLanguageTag = Locale.class.getMethod("forLanguageTag", String.class);
+    
+                    Class<?> cCategory = null;
+                    Class<?>[] classes = Locale.class.getDeclaredClasses();
+                    for (Class<?> c : classes) {
+                        if (c.getName().equals("java.util.Locale$Category")) {
+                            cCategory = c;
+                            break;
+                        }
+                    }
+                    if (cCategory == null) {
+                        break;
+                    }
+                    mGetDefault = Locale.class.getDeclaredMethod("getDefault", cCategory);
+                    mSetDefault = Locale.class.getDeclaredMethod("setDefault", cCategory, Locale.class);
+    
+                    Method mName = cCategory.getMethod("name", (Class[]) null);
+                    Object[] enumConstants = cCategory.getEnumConstants();
+                    for (Object e : enumConstants) {
+                        String catVal = (String)mName.invoke(e, (Object[])null);
+                        if (catVal.equals("DISPLAY")) {
+                            eDISPLAY = e;
+                        } else if (catVal.equals("FORMAT")) {
+                            eFORMAT = e;
+                        }
+                    }
+                    if (eDISPLAY == null || eFORMAT == null) {
+                        break;
+                    }    
+                    isJava7orNewer = true;
+                } catch (NoSuchMethodException e) {
+                } catch (IllegalArgumentException e) {
+                } catch (IllegalAccessException e) {
+                } catch (InvocationTargetException e) {
+                } catch (SecurityException e) {
+                    // TODO : report?
+                }
+            } while (false);
+        }
+
+        private JDKLocaleHelper() {
+        }
+
+        public static boolean isJava7orNewer() {
+            return isJava7orNewer;
+        }
+
+        public static ULocale toULocale(Locale loc) {
+            return isJava7orNewer ? toULocale7(loc) : toULocale6(loc);
+        }
+
+        public static Locale toLocale(ULocale uloc) {
+            return isJava7orNewer ? toLocale7(uloc) : toLocale6(uloc);
+        }
+
+        private static ULocale toULocale7(Locale loc) {
+            String language = loc.getLanguage();
+            String script = "";
+            String country = loc.getCountry();
+            String variant = loc.getVariant();
+
+            Set<String> attributes = null;
+            Map<String, String> keywords = null;
+
+            try {
+                script = (String) mGetScript.invoke(loc, (Object[]) null);
+                @SuppressWarnings("unchecked")
+                Set<Character> extKeys = (Set<Character>) mGetExtensionKeys.invoke(loc, (Object[]) null);
+                if (!extKeys.isEmpty()) {
+                    for (Character extKey : extKeys) {
+                        if (extKey.charValue() == 'u') {
+                            // Found Unicode locale extension
+
+                            // attributes
+                            @SuppressWarnings("unchecked")
+                            Set<String> uAttributes = (Set<String>) mGetUnicodeLocaleAttributes.invoke(loc, (Object[]) null);
+                            if (!uAttributes.isEmpty()) {
+                                attributes = new TreeSet<String>();
+                                for (String attr : uAttributes) {
+                                    attributes.add(attr);
+                                }
+                            }
+
+                            // keywords
+                            @SuppressWarnings("unchecked")
+                            Set<String> uKeys = (Set<String>) mGetUnicodeLocaleKeys.invoke(loc, (Object[]) null);
+                            for (String kwKey : uKeys) {
+                                String kwVal = (String) mGetUnicodeLocaleType.invoke(loc, kwKey);
+                                if (kwVal != null) {
+                                    if (kwKey.equals("va")) {
+                                        // va-* is interpreted as a variant
+                                        variant = (variant.length() == 0) ? kwVal : kwVal + "_" + variant;
+                                    } else {
+                                        if (keywords == null) {
+                                            keywords = new TreeMap<String, String>();
+                                        }
+                                        keywords.put(kwKey, kwVal);
+                                    }
+                                }
+                            }
+                        } else {
+                            String extVal = (String) mGetExtension.invoke(loc, extKey);
+                            if (extVal != null) {
+                                if (keywords == null) {
+                                    keywords = new TreeMap<String, String>();
+                                }
+                                keywords.put(String.valueOf(extKey), extVal);
+                            }
+                        }
+                    }
+                }
+            } catch (IllegalAccessException e) {
+                throw new RuntimeException(e);
+            } catch (InvocationTargetException e) {
+                throw new RuntimeException(e);
+            }
+
+            // JDK locale no_NO_NY is not interpreted as Nynorsk by ICU,
+            // and it should be transformed to nn_NO.
+
+            // Note: JDK7+ unerstand both no_NO_NY and nn_NO. When convert
+            // ICU locale to JDK, we do not need to map nn_NO back to no_NO_NY.
+
+            if (language.equals("no") && country.equals("NO") && variant.equals("NY")) {
+                language = "nn";
+                variant = "";
+            }
+
+            // Constructing ID
+            StringBuilder buf = new StringBuilder(language);
+
+            if (script.length() > 0) {
+                buf.append('_');
+                buf.append(script);
+            }
+
+            if (country.length() > 0) {
+                buf.append('_');
+                buf.append(country);
+            }
+
+            if (variant.length() > 0) {
+                if (country.length() == 0) {
+                    buf.append('_');
+                }
+                buf.append('_');
+                buf.append(variant);
+            }
+
+            if (attributes != null) {
+                // transform Unicode attributes into a keyword
+                StringBuilder attrBuf = new StringBuilder();
+                for (String attr : attributes) {
+                    if (attrBuf.length() != 0) {
+                        attrBuf.append('-');
+                    }
+                    attrBuf.append(attr);
+                }
+                if (keywords == null) {
+                    keywords = new TreeMap<String, String>();
+                }
+                keywords.put(LOCALE_ATTRIBUTE_KEY, attrBuf.toString());
+            }
+
+            if (keywords != null) {
+                buf.append('@');
+                boolean addSep = false;
+                for (Entry<String, String> kwEntry : keywords.entrySet()) {
+                    String kwKey = kwEntry.getKey();
+                    String kwVal = kwEntry.getValue();
+
+                    if (kwKey.length() != 1) {
+                        // Unicode locale key
+                        kwKey = bcp47ToLDMLKey(kwKey);
+                        // use "true" as the value of typeless keywords
+                        kwVal = bcp47ToLDMLType(kwKey, ((kwVal.length() == 0) ? "true" : kwVal));
+                    }
+
+                    if (addSep) {
+                        buf.append(';');
+                    } else {
+                        addSep = true;
+                    }
+                    buf.append(kwKey);
+                    buf.append('=');
+                    buf.append(kwVal);
+                }
+            }
+
+            return new ULocale(getName(buf.toString()), loc);
+        }
+
+        private static ULocale toULocale6(Locale loc) {
+            ULocale uloc = null;
+            String locStr = loc.toString();
+            if (locStr.length() == 0) {
+                uloc = ULocale.ROOT;
+            } else {
+                for (int i = 0; i < JAVA6_MAPDATA.length; i++) {
+                    if (JAVA6_MAPDATA[i][0].equals(locStr)) {
+                        LocaleIDParser p = new LocaleIDParser(JAVA6_MAPDATA[i][1]);
+                        p.setKeywordValue(JAVA6_MAPDATA[i][2], JAVA6_MAPDATA[i][3]);
+                        locStr = p.getName();
+                        break;
+                    }
+                }
+                uloc = new ULocale(getName(locStr), loc);
+            }
+            return uloc;
+        }
+
+        private static Locale toLocale7(ULocale uloc) {
+            Locale loc = null;
+            String ulocStr = uloc.getName();
+            if (uloc.getScript().length() > 0 || ulocStr.contains("@")) {
+                // With script or keywords available, the best way
+                // to get a mapped Locale is to go through a language tag.
+                // A Locale with script or keywords can only have variants
+                // that is 1 to 8 alphanum. If this ULocale has a variant
+                // subtag not satisfying the criteria, the variant subtag
+                // will be lost.
+                String tag = uloc.toLanguageTag();
+
+                // Workaround for variant casing problem:
+                //
+                // The variant field in ICU is case insensitive and normalized
+                // to upper case letters by getVariant(), while
+                // the variant field in JDK Locale is case sensitive.
+                // ULocale#toLanguageTag use lower case characters for
+                // BCP 47 variant and private use x-lvariant.
+                //
+                // Locale#forLanguageTag in JDK preserves character casing
+                // for variant. Because ICU always normalizes variant to
+                // upper case, we convert language tag to upper case here.
+                tag = AsciiUtil.toUpperString(tag);
+
+                try {
+                    loc = (Locale)mForLanguageTag.invoke(null, tag);
+                } catch (IllegalAccessException e) {
+                    throw new RuntimeException(e);
+                } catch (InvocationTargetException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+            if (loc == null) {
+                // Without script or keywords, use a Locale constructor,
+                // so we can preserve any ill-formed variants.
+                loc = new Locale(uloc.getLanguage(), uloc.getCountry(), uloc.getVariant());
+            }
+            return loc;
+        }
+
+        private static Locale toLocale6(ULocale uloc) {
+            String locstr = uloc.getBaseName();
+            for (int i = 0; i < JAVA6_MAPDATA.length; i++) {
+                if (locstr.equals(JAVA6_MAPDATA[i][1]) || locstr.equals(JAVA6_MAPDATA[i][4])) {
+                    if (JAVA6_MAPDATA[i][2] != null) {
+                        String val = uloc.getKeywordValue(JAVA6_MAPDATA[i][2]);
+                        if (val != null && val.equals(JAVA6_MAPDATA[i][3])) {
+                            locstr = JAVA6_MAPDATA[i][0];
+                            break;
+                        }
+                    } else {
+                        locstr = JAVA6_MAPDATA[i][0];
+                        break;
+                    }
+                }
+            }
+            LocaleIDParser p = new LocaleIDParser(locstr);
+            String[] names = p.getLanguageScriptCountryVariant();
+            return new Locale(names[0], names[2], names[3]);
+        }
+
+        public static Locale getDefault(Category category) {
+            Locale loc = Locale.getDefault();
+            if (isJava7orNewer) {
+                Object cat = null;
+                switch (category) {
+                case DISPLAY:
+                    cat = eDISPLAY;
+                    break;
+                case FORMAT:
+                    cat = eFORMAT;
+                    break;
+                }
+                if (cat != null) {
+                    try {
+                        loc = (Locale)mGetDefault.invoke(null, cat);
+                    } catch (InvocationTargetException e) {
+                        // fall through - use the base default
+                    } catch (IllegalArgumentException e) {
+                        // fall through - use the base default
+                    } catch (IllegalAccessException e) {
+                        // fall through - use the base default
+                    }
+                }
+            }
+            return loc;
+        }
+
+        public static void setDefault(Category category, Locale newLocale) {
+            if (isJava7orNewer) {
+                Object cat = null;
+                switch (category) {
+                case DISPLAY:
+                    cat = eDISPLAY;
+                    break;
+                case FORMAT:
+                    cat = eFORMAT;
+                    break;
+                }
+                if (cat != null) {
+                    try {
+                        mSetDefault.invoke(null, cat, newLocale);
+                    } catch (InvocationTargetException e) {
+                        // fall through - no effects
+                    } catch (IllegalArgumentException e) {
+                        // fall through - no effects
+                    } catch (IllegalAccessException e) {
+                        // fall through - no effects
+                    }
+                }
+            }
+        }
+    }
+
+    private static final String[] KEYMAP = {
+        "calendar", "ca",
+        "colalternate", "ka",
+        "colbackwards", "kb",
+        "colcasefirst", "kf",
+        "colcaselevel", "kc",
+        "colhiraganaquaternary", "kh",
+        "collation", "co",
+        "colnormalization", "kk",
+        "colnumeric", "kn",
+        "colstrength", "ks",
+        "currency", "cu",
+        "numbers", "nu",
+        "timezone", "tz",
+        "variabletop", "vt",
+    };
+
+    private static final String[] TYPEMAP_CALENDAR = {
+        "ethiopic-amete-alem", "ethioaa",
+        "gregorian", "gregory",
+        "islamic-civil", "islamicc",
+    };
+
+    private static final String[] TYPEMAP_COLALTERNATE = {
+        "non-ignorable", "noignore",
+    };
+
+    private static final String[] TYPEMAP_COLBACKWARDS = {
+        "no", "false",
+        "yes", "true",
+    };
+
+    private static final String[] TYPEMAP_COLCASEFIRST = {
+        "no", "false",
+    };
+
+    private static final String[] TYPEMAP_COLCASELEVEL = {
+        "no", "false",
+        "yes", "true",
+    };
+
+    private static final String[] TYPEMAP_COLHIRAGANAQUATERNARY = {
+        "no", "false",
+        "yes", "true",
+    };
+
+    private static final String[] TYPEMAP_COLLATION = {
+        "dictionary", "dict",
+        "gb2312han", "gb2312",
+        "phonebook", "phonebk",
+        "traditional", "trad",
+    };
+
+    private static final String[] TYPEMAP_COLNORMALIZATION = {
+        "no", "false",
+        "yes", "true",
+    };
+
+    private static final String[] TYPEMAP_COLNUMERIC = {
+        "no", "false",
+        "yes", "true",
+    };
+
+    private static final String[] TYPEMAP_COLSTRENGTH = {
+        "identical", "identic",
+        "primary", "level1",
+        "quaternary", "level4",
+        "secondary", "level2",
+        "tertiary", "level3",
+    };
+
+    private static final String[] TYPEMAP_TIMEZONE = {
+        "Africa/Abidjan", "ciabj",
+        "Africa/Accra", "ghacc",
+        "Africa/Addis_Ababa", "etadd",
+        "Africa/Algiers", "dzalg",
+        "Africa/Asmera", "erasm",
+        "Africa/Bamako", "mlbko",
+        "Africa/Bangui", "cfbgf",
+        "Africa/Banjul", "gmbjl",
+        "Africa/Bissau", "gwoxb",
+        "Africa/Blantyre", "mwblz",
+        "Africa/Brazzaville", "cgbzv",
+        "Africa/Bujumbura", "bibjm",
+        "Africa/Cairo", "egcai",
+        "Africa/Casablanca", "macas",
+        "Africa/Ceuta", "esceu",
+        "Africa/Conakry", "gncky",
+        "Africa/Dakar", "sndkr",
+        "Africa/Dar_es_Salaam", "tzdar",
+        "Africa/Djibouti", "djjib",
+        "Africa/Douala", "cmdla",
+        "Africa/El_Aaiun", "eheai",
+        "Africa/Freetown", "slfna",
+        "Africa/Gaborone", "bwgbe",
+        "Africa/Harare", "zwhre",
+        "Africa/Johannesburg", "zajnb",
+        "Africa/Kampala", "ugkla",
+        "Africa/Khartoum", "sdkrt",
+        "Africa/Kigali", "rwkgl",
+        "Africa/Kinshasa", "cdfih",
+        "Africa/Lagos", "nglos",
+        "Africa/Libreville", "galbv",
+        "Africa/Lome", "tglfw",
+        "Africa/Luanda", "aolad",
+        "Africa/Lubumbashi", "cdfbm",
+        "Africa/Lusaka", "zmlun",
+        "Africa/Malabo", "gqssg",
+        "Africa/Maputo", "mzmpm",
+        "Africa/Maseru", "lsmsu",
+        "Africa/Mbabane", "szqmn",
+        "Africa/Mogadishu", "somgq",
+        "Africa/Monrovia", "lrmlw",
+        "Africa/Nairobi", "kenbo",
+        "Africa/Ndjamena", "tdndj",
+        "Africa/Niamey", "nenim",
+        "Africa/Nouakchott", "mrnkc",
+        "Africa/Ouagadougou", "bfoua",
+        "Africa/Porto-Novo", "bjptn",
+        "Africa/Sao_Tome", "sttms",
+        "Africa/Tripoli", "lytip",
+        "Africa/Tunis", "tntun",
+        "Africa/Windhoek", "nawdh",
+        "America/Adak", "usadk",
+        "America/Anchorage", "usanc",
+        "America/Anguilla", "aiaxa",
+        "America/Antigua", "aganu",
+        "America/Araguaina", "braux",
+        "America/Argentina/La_Rioja", "arirj",
+        "America/Argentina/Rio_Gallegos", "arrgl",
+        "America/Argentina/Salta", "arsla",
+        "America/Argentina/San_Juan", "aruaq",
+        "America/Argentina/San_Luis", "arluq",
+        "America/Argentina/Tucuman", "artuc",
+        "America/Argentina/Ushuaia", "arush",
+        "America/Aruba", "awaua",
+        "America/Asuncion", "pyasu",
+        "America/Bahia", "brssa",
+        "America/Bahia_Banderas", "mxpvr",
+        "America/Barbados", "bbbgi",
+        "America/Belem", "brbel",
+        "America/Belize", "bzbze",
+        "America/Blanc-Sablon", "caybx",
+        "America/Boa_Vista", "brbvb",
+        "America/Bogota", "cobog",
+        "America/Boise", "usboi",
+        "America/Buenos_Aires", "arbue",
+        "America/Cambridge_Bay", "caycb",
+        "America/Campo_Grande", "brcgr",
+        "America/Cancun", "mxcun",
+        "America/Caracas", "veccs",
+        "America/Catamarca", "arctc",
+        "America/Cayenne", "gfcay",
+        "America/Cayman", "kygec",
+        "America/Chicago", "uschi",
+        "America/Chihuahua", "mxchi",
+        "America/Coral_Harbour", "cayzs",
+        "America/Cordoba", "arcor",
+        "America/Costa_Rica", "crsjo",
+        "America/Cuiaba", "brcgb",
+        "America/Curacao", "ancur",
+        "America/Danmarkshavn", "gldkshvn",
+        "America/Dawson", "cayda",
+        "America/Dawson_Creek", "caydq",
+        "America/Denver", "usden",
+        "America/Detroit", "usdet",
+        "America/Dominica", "dmdom",
+        "America/Edmonton", "caedm",
+        "America/Eirunepe", "brern",
+        "America/El_Salvador", "svsal",
+        "America/Fortaleza", "brfor",
+        "America/Glace_Bay", "caglb",
+        "America/Godthab", "glgoh",
+        "America/Goose_Bay", "cagoo",
+        "America/Grand_Turk", "tcgdt",
+        "America/Grenada", "gdgnd",
+        "America/Guadeloupe", "gpbbr",
+        "America/Guatemala", "gtgua",
+        "America/Guayaquil", "ecgye",
+        "America/Guyana", "gygeo",
+        "America/Halifax", "cahal",
+        "America/Havana", "cuhav",
+        "America/Hermosillo", "mxhmo",
+        "America/Indiana/Knox", "usknx",
+        "America/Indiana/Marengo", "usaeg",
+        "America/Indiana/Petersburg", "uswsq",
+        "America/Indiana/Tell_City", "ustel",
+        "America/Indiana/Vevay", "usinvev",
+        "America/Indiana/Vincennes", "usoea",
+        "America/Indiana/Winamac", "uswlz",
+        "America/Indianapolis", "usind",
+        "America/Inuvik", "cayev",
+        "America/Iqaluit", "caiql",
+        "America/Jamaica", "jmkin",
+        "America/Jujuy", "arjuj",
+        "America/Juneau", "usjnu",
+        "America/Kentucky/Monticello", "usmoc",
+        "America/La_Paz", "bolpb",
+        "America/Lima", "pelim",
+        "America/Los_Angeles", "uslax",
+        "America/Louisville", "uslui",
+        "America/Maceio", "brmcz",
+        "America/Managua", "nimga",
+        "America/Manaus", "brmao",
+        "America/Marigot", "gpmsb",
+        "America/Martinique", "mqfdf",
+        "America/Matamoros", "mxmam",
+        "America/Mazatlan", "mxmzt",
+        "America/Mendoza", "armdz",
+        "America/Menominee", "usmnm",
+        "America/Merida", "mxmid",
+        "America/Metlakatla", "usmtm",
+        "America/Mexico_City", "mxmex",
+        "America/Miquelon", "pmmqc",
+        "America/Moncton", "camon",
+        "America/Monterrey", "mxmty",
+        "America/Montevideo", "uymvd",
+        "America/Montreal", "camtr",
+        "America/Montserrat", "msmni",
+        "America/Nassau", "bsnas",
+        "America/New_York", "usnyc",
+        "America/Nipigon", "canpg",
+        "America/Nome", "usome",
+        "America/Noronha", "brfen",
+        "America/North_Dakota/Beulah", "usxul",
+        "America/North_Dakota/Center", "usndcnt",
+        "America/North_Dakota/New_Salem", "usndnsl",
+        "America/Ojinaga", "mxoji",
+        "America/Panama", "papty",
+        "America/Pangnirtung", "capnt",
+        "America/Paramaribo", "srpbm",
+        "America/Phoenix", "usphx",
+        "America/Port-au-Prince", "htpap",
+        "America/Port_of_Spain", "ttpos",
+        "America/Porto_Velho", "brpvh",
+        "America/Puerto_Rico", "prsju",
+        "America/Rainy_River", "caffs",
+        "America/Rankin_Inlet", "cayek",
+        "America/Recife", "brrec",
+        "America/Regina", "careg",
+        "America/Resolute", "careb",
+        "America/Rio_Branco", "brrbr",
+        "America/Santa_Isabel", "mxstis",
+        "America/Santarem", "brstm",
+        "America/Santiago", "clscl",
+        "America/Santo_Domingo", "dosdq",
+        "America/Sao_Paulo", "brsao",
+        "America/Scoresbysund", "globy",
+        "America/Shiprock", "usnavajo",
+        "America/Sitka", "ussit",
+        "America/St_Barthelemy", "gpsbh",
+        "America/St_Johns", "casjf",
+        "America/St_Kitts", "knbas",
+        "America/St_Lucia", "lccas",
+        "America/St_Thomas", "vistt",
+        "America/St_Vincent", "vcsvd",
+        "America/Swift_Current", "cayyn",
+        "America/Tegucigalpa", "hntgu",
+        "America/Thule", "glthu",
+        "America/Thunder_Bay", "cathu",
+        "America/Tijuana", "mxtij",
+        "America/Toronto", "cator",
+        "America/Tortola", "vgtov",
+        "America/Vancouver", "cavan",
+        "America/Whitehorse", "cayxy",
+        "America/Winnipeg", "cawnp",
+        "America/Yakutat", "usyak",
+        "America/Yellowknife", "cayzf",
+        "Antarctica/Casey", "aqcas",
+        "Antarctica/Davis", "aqdav",
+        "Antarctica/DumontDUrville", "aqddu",
+        "Antarctica/Macquarie", "aumqi",
+        "Antarctica/Mawson", "aqmaw",
+        "Antarctica/McMurdo", "aqmcm",
+        "Antarctica/Palmer", "aqplm",
+        "Antarctica/Rothera", "aqrot",
+        "Antarctica/South_Pole", "aqams",
+        "Antarctica/Syowa", "aqsyw",
+        "Antarctica/Vostok", "aqvos",
+        "Arctic/Longyearbyen", "sjlyr",
+        "Asia/Aden", "yeade",
+        "Asia/Almaty", "kzala",
+        "Asia/Amman", "joamm",
+        "Asia/Anadyr", "rudyr",
+        "Asia/Aqtau", "kzaau",
+        "Asia/Aqtobe", "kzakx",
+        "Asia/Ashgabat", "tmasb",
+        "Asia/Baghdad", "iqbgw",
+        "Asia/Bahrain", "bhbah",
+        "Asia/Baku", "azbak",
+        "Asia/Bangkok", "thbkk",
+        "Asia/Beirut", "lbbey",
+        "Asia/Bishkek", "kgfru",
+        "Asia/Brunei", "bnbwn",
+        "Asia/Calcutta", "inccu",
+        "Asia/Choibalsan", "mncoq",
+        "Asia/Chongqing", "cnckg",
+        "Asia/Colombo", "lkcmb",
+        "Asia/Damascus", "sydam",
+        "Asia/Dhaka", "bddac",
+        "Asia/Dili", "tldil",
+        "Asia/Dubai", "aedxb",
+        "Asia/Dushanbe", "tjdyu",
+        "Asia/Gaza", "gaza",
+        "Asia/Harbin", "cnhrb",
+        "Asia/Hong_Kong", "hkhkg",
+        "Asia/Hovd", "mnhvd",
+        "Asia/Irkutsk", "ruikt",
+        "Asia/Jakarta", "idjkt",
+        "Asia/Jayapura", "iddjj",
+        "Asia/Jerusalem", "jeruslm",
+        "Asia/Kabul", "afkbl",
+        "Asia/Kamchatka", "rupkc",
+        "Asia/Karachi", "pkkhi",
+        "Asia/Kashgar", "cnkhg",
+        "Asia/Katmandu", "npktm",
+        "Asia/Krasnoyarsk", "rukra",
+        "Asia/Kuala_Lumpur", "mykul",
+        "Asia/Kuching", "mykch",
+        "Asia/Kuwait", "kwkwi",
+        "Asia/Macau", "momfm",
+        "Asia/Magadan", "rugdx",
+        "Asia/Makassar", "idmak",
+        "Asia/Manila", "phmnl",
+        "Asia/Muscat", "ommct",
+        "Asia/Nicosia", "cynic",
+        "Asia/Novokuznetsk", "runoz",
+        "Asia/Novosibirsk", "ruovb",
+        "Asia/Omsk", "ruoms",
+        "Asia/Oral", "kzura",
+        "Asia/Phnom_Penh", "khpnh",
+        "Asia/Pontianak", "idpnk",
+        "Asia/Pyongyang", "kpfnj",
+        "Asia/Qatar", "qadoh",
+        "Asia/Qyzylorda", "kzkzo",
+        "Asia/Rangoon", "mmrgn",
+        "Asia/Riyadh", "saruh",
+        "Asia/Saigon", "vnsgn",
+        "Asia/Sakhalin", "ruuus",
+        "Asia/Samarkand", "uzskd",
+        "Asia/Seoul", "krsel",
+        "Asia/Shanghai", "cnsha",
+        "Asia/Singapore", "sgsin",
+        "Asia/Taipei", "twtpe",
+        "Asia/Tashkent", "uztas",
+        "Asia/Tbilisi", "getbs",
+        "Asia/Tehran", "irthr",
+        "Asia/Thimphu", "btthi",
+        "Asia/Tokyo", "jptyo",
+        "Asia/Ulaanbaatar", "mnuln",
+        "Asia/Urumqi", "cnurc",
+        "Asia/Vientiane", "lavte",
+        "Asia/Vladivostok", "ruvvo",
+        "Asia/Yakutsk", "ruyks",
+        "Asia/Yekaterinburg", "ruyek",
+        "Asia/Yerevan", "amevn",
+        "Atlantic/Azores", "ptpdl",
+        "Atlantic/Bermuda", "bmbda",
+        "Atlantic/Canary", "eslpa",
+        "Atlantic/Cape_Verde", "cvrai",
+        "Atlantic/Faeroe", "fotho",
+        "Atlantic/Madeira", "ptfnc",
+        "Atlantic/Reykjavik", "isrey",
+        "Atlantic/South_Georgia", "gsgrv",
+        "Atlantic/St_Helena", "shshn",
+        "Atlantic/Stanley", "fkpsy",
+        "Australia/Adelaide", "auadl",
+        "Australia/Brisbane", "aubne",
+        "Australia/Broken_Hill", "aubhq",
+        "Australia/Currie", "aukns",
+        "Australia/Darwin", "audrw",
+        "Australia/Eucla", "aueuc",
+        "Australia/Hobart", "auhba",
+        "Australia/Lindeman", "auldc",
+        "Australia/Lord_Howe", "auldh",
+        "Australia/Melbourne", "aumel",
+        "Australia/Perth", "auper",
+        "Australia/Sydney", "ausyd",
+        "CST6CDT", "cst6cdt",
+        "EST5EDT", "est5edt",
+        "Etc/GMT", "utc",
+        "Etc/GMT+1", "utcw01",
+        "Etc/GMT+10", "utcw10",
+        "Etc/GMT+11", "utcw11",
+        "Etc/GMT+12", "utcw12",
+        "Etc/GMT+2", "utcw02",
+        "Etc/GMT+3", "utcw03",
+        "Etc/GMT+4", "utcw04",
+        "Etc/GMT+5", "utcw05",
+        "Etc/GMT+6", "utcw06",
+        "Etc/GMT+7", "utcw07",
+        "Etc/GMT+8", "utcw08",
+        "Etc/GMT+9", "utcw09",
+        "Etc/GMT-1", "utce01",
+        "Etc/GMT-10", "utce10",
+        "Etc/GMT-11", "utce11",
+        "Etc/GMT-12", "utce12",
+        "Etc/GMT-13", "utce13",
+        "Etc/GMT-14", "utce14",
+        "Etc/GMT-2", "utce02",
+        "Etc/GMT-3", "utce03",
+        "Etc/GMT-4", "utce04",
+        "Etc/GMT-5", "utce05",
+        "Etc/GMT-6", "utce06",
+        "Etc/GMT-7", "utce07",
+        "Etc/GMT-8", "utce08",
+        "Etc/GMT-9", "utce09",
+        "Etc/Unknown", "unk",
+        "Europe/Amsterdam", "nlams",
+        "Europe/Andorra", "adalv",
+        "Europe/Athens", "grath",
+        "Europe/Belgrade", "rsbeg",
+        "Europe/Berlin", "deber",
+        "Europe/Bratislava", "skbts",
+        "Europe/Brussels", "bebru",
+        "Europe/Bucharest", "robuh",
+        "Europe/Budapest", "hubud",
+        "Europe/Chisinau", "mdkiv",
+        "Europe/Copenhagen", "dkcph",
+        "Europe/Dublin", "iedub",
+        "Europe/Gibraltar", "gigib",
+        "Europe/Guernsey", "gggci",
+        "Europe/Helsinki", "fihel",
+        "Europe/Isle_of_Man", "imdgs",
+        "Europe/Istanbul", "trist",
+        "Europe/Jersey", "jesth",
+        "Europe/Kaliningrad", "rukgd",
+        "Europe/Kiev", "uaiev",
+        "Europe/Lisbon", "ptlis",
+        "Europe/Ljubljana", "silju",
+        "Europe/London", "gblon",
+        "Europe/Luxembourg", "lulux",
+        "Europe/Madrid", "esmad",
+        "Europe/Malta", "mtmla",
+        "Europe/Mariehamn", "fimhq",
+        "Europe/Minsk", "bymsq",
+        "Europe/Monaco", "mcmon",
+        "Europe/Moscow", "rumow",
+        "Europe/Oslo", "noosl",
+        "Europe/Paris", "frpar",
+        "Europe/Podgorica", "metgd",
+        "Europe/Prague", "czprg",
+        "Europe/Riga", "lvrix",
+        "Europe/Rome", "itrom",
+        "Europe/Samara", "rukuf",
+        "Europe/San_Marino", "smsai",
+        "Europe/Sarajevo", "basjj",
+        "Europe/Simferopol", "uasip",
+        "Europe/Skopje", "mkskp",
+        "Europe/Sofia", "bgsof",
+        "Europe/Stockholm", "sesto",
+        "Europe/Tallinn", "eetll",
+        "Europe/Tirane", "altia",
+        "Europe/Uzhgorod", "uauzh",
+        "Europe/Vaduz", "livdz",
+        "Europe/Vatican", "vavat",
+        "Europe/Vienna", "atvie",
+        "Europe/Vilnius", "ltvno",
+        "Europe/Volgograd", "ruvog",
+        "Europe/Warsaw", "plwaw",
+        "Europe/Zagreb", "hrzag",
+        "Europe/Zaporozhye", "uaozh",
+        "Europe/Zurich", "chzrh",
+        "Indian/Antananarivo", "mgtnr",
+        "Indian/Chagos", "iodga",
+        "Indian/Christmas", "cxxch",
+        "Indian/Cocos", "cccck",
+        "Indian/Comoro", "kmyva",
+        "Indian/Kerguelen", "tfpfr",
+        "Indian/Mahe", "scmaw",
+        "Indian/Maldives", "mvmle",
+        "Indian/Mauritius", "muplu",
+        "Indian/Mayotte", "ytmam",
+        "Indian/Reunion", "rereu",
+        "MST7MDT", "mst7mdt",
+        "PST8PDT", "pst8pdt",
+        "Pacific/Apia", "wsapw",
+        "Pacific/Auckland", "nzakl",
+        "Pacific/Chatham", "nzcht",
+        "Pacific/Easter", "clipc",
+        "Pacific/Efate", "vuvli",
+        "Pacific/Enderbury", "kipho",
+        "Pacific/Fakaofo", "tkfko",
+        "Pacific/Fiji", "fjsuv",
+        "Pacific/Funafuti", "tvfun",
+        "Pacific/Galapagos", "ecgps",
+        "Pacific/Gambier", "pfgmr",
+        "Pacific/Guadalcanal", "sbhir",
+        "Pacific/Guam", "gugum",
+        "Pacific/Honolulu", "ushnl",
+        "Pacific/Johnston", "umjon",
+        "Pacific/Kiritimati", "kicxi",
+        "Pacific/Kosrae", "fmksa",
+        "Pacific/Kwajalein", "mhkwa",
+        "Pacific/Majuro", "mhmaj",
+        "Pacific/Marquesas", "pfnhv",
+        "Pacific/Midway", "ummdy",
+        "Pacific/Nauru", "nrinu",
+        "Pacific/Niue", "nuiue",
+        "Pacific/Norfolk", "nfnlk",
+        "Pacific/Noumea", "ncnou",
+        "Pacific/Pago_Pago", "asppg",
+        "Pacific/Palau", "pwror",
+        "Pacific/Pitcairn", "pnpcn",
+        "Pacific/Ponape", "fmpni",
+        "Pacific/Port_Moresby", "pgpom",
+        "Pacific/Rarotonga", "ckrar",
+        "Pacific/Saipan", "mpspn",
+        "Pacific/Tahiti", "pfppt",
+        "Pacific/Tarawa", "kitrw",
+        "Pacific/Tongatapu", "totbu",
+        "Pacific/Truk", "fmtkk",
+        "Pacific/Wake", "umawk",
+        "Pacific/Wallis", "wfmau",
+    };
+
+    private static final String[] TYPEALIAS_COLSTRENGTH = {
+        "quarternary", "quaternary",
+    };
+
+    private static final String[] TYPEALIAS_TIMEZONE = {
+        "Africa/Asmara", "Africa/Asmera",
+        "Africa/Timbuktu", "Africa/Bamako",
+        "America/Argentina/Buenos_Aires", "America/Buenos_Aires",
+        "America/Argentina/Catamarca", "America/Catamarca",
+        "America/Argentina/ComodRivadavia", "America/Catamarca",
+        "America/Argentina/Cordoba", "America/Cordoba",
+        "America/Argentina/Jujuy", "America/Jujuy",
+        "America/Argentina/Mendoza", "America/Mendoza",
+        "America/Atikokan", "America/Coral_Harbour",
+        "America/Atka", "America/Adak",
+        "America/Ensenada", "America/Tijuana",
+        "America/Fort_Wayne", "America/Indianapolis",
+        "America/Indiana/Indianapolis", "America/Indianapolis",
+        "America/Kentucky/Louisville", "America/Louisville",
+        "America/Knox_IN", "America/Indiana/Knox",
+        "America/Porto_Acre", "America/Rio_Branco",
+        "America/Rosario", "America/Cordoba",
+        "America/Virgin", "America/St_Thomas",
+        "Asia/Ashkhabad", "Asia/Ashgabat",
+        "Asia/Chungking", "Asia/Chongqing",
+        "Asia/Dacca", "Asia/Dhaka",
+        "Asia/Ho_Chi_Minh", "Asia/Saigon",
+        "Asia/Istanbul", "Europe/Istanbul",
+        "Asia/Kathmandu", "Asia/Katmandu",
+        "Asia/Kolkata", "Asia/Calcutta",
+        "Asia/Macao", "Asia/Macau",
+        "Asia/Tel_Aviv", "Asia/Jerusalem",
+        "Asia/Thimbu", "Asia/Thimphu",
+        "Asia/Ujung_Pandang", "Asia/Makassar",
+        "Asia/Ulan_Bator", "Asia/Ulaanbaatar",
+        "Atlantic/Faroe", "Atlantic/Faeroe",
+        "Atlantic/Jan_Mayen", "Arctic/Longyearbyen",
+        "Australia/ACT", "Australia/Sydney",
+        "Australia/Canberra", "Australia/Sydney",
+        "Australia/LHI", "Australia/Lord_Howe",
+        "Australia/NSW", "Australia/Sydney",
+        "Australia/North", "Australia/Darwin",
+        "Australia/Queensland", "Australia/Brisbane",
+        "Australia/South", "Australia/Adelaide",
+        "Australia/Tasmania", "Australia/Hobart",
+        "Australia/Victoria", "Australia/Melbourne",
+        "Australia/West", "Australia/Perth",
+        "Australia/Yancowinna", "Australia/Broken_Hill",
+        "Brazil/Acre", "America/Rio_Branco",
+        "Brazil/DeNoronha", "America/Noronha",
+        "Brazil/East", "America/Sao_Paulo",
+        "Brazil/West", "America/Manaus",
+        "Canada/Atlantic", "America/Halifax",
+        "Canada/Central", "America/Winnipeg",
+        "Canada/East-Saskatchewan", "America/Regina",
+        "Canada/Eastern", "America/Toronto",
+        "Canada/Mountain", "America/Edmonton",
+        "Canada/Newfoundland", "America/St_Johns",
+        "Canada/Pacific", "America/Vancouver",
+        "Canada/Saskatchewan", "America/Regina",
+        "Canada/Yukon", "America/Whitehorse",
+        "Chile/Continental", "America/Santiago",
+        "Chile/EasterIsland", "Pacific/Easter",
+        "Cuba", "America/Havana",
+        "EST", "Etc/GMT+5",
+        "Egypt", "Africa/Cairo",
+        "Eire", "Europe/Dublin",
+        "Etc/GMT+0", "Etc/GMT",
+        "Etc/GMT-0", "Etc/GMT",
+        "Etc/GMT0", "Etc/GMT",
+        "Etc/Greenwich", "Etc/GMT",
+        "Etc/UCT", "Etc/GMT",
+        "Etc/UTC", "Etc/GMT",
+        "Etc/Universal", "Etc/GMT",
+        "Etc/Zulu", "Etc/GMT",
+        "Europe/Belfast", "Europe/London",
+        "Europe/Nicosia", "Asia/Nicosia",
+        "Europe/Tiraspol", "Europe/Chisinau",
+        "GB", "Europe/London",
+        "GB-Eire", "Europe/London",
+        "GMT", "Etc/GMT",
+        "GMT+0", "Etc/GMT",
+        "GMT-0", "Etc/GMT",
+        "GMT0", "Etc/GMT",
+        "Greenwich", "Etc/GMT",
+        "HST", "Etc/GMT+10",
+        "Hongkong", "Asia/Hong_Kong",
+        "Iceland", "Atlantic/Reykjavik",
+        "Iran", "Asia/Tehran",
+        "Israel", "Asia/Jerusalem",
+        "Jamaica", "America/Jamaica",
+        "Japan", "Asia/Tokyo",
+        "Kwajalein", "Pacific/Kwajalein",
+        "Libya", "Africa/Tripoli",
+        "MST", "Etc/GMT+7",
+        "Mexico/BajaNorte", "America/Tijuana",
+        "Mexico/BajaSur", "America/Mazatlan",
+        "Mexico/General", "America/Mexico_City",
+        "NZ", "Pacific/Auckland",
+        "NZ-CHAT", "Pacific/Chatham",
+        "Navajo", "America/Shiprock",
+        "PRC", "Asia/Shanghai",
+        "Pacific/Chuuk", "Pacific/Truk",
+        "Pacific/Pohnpei", "Pacific/Ponape",
+        "Pacific/Samoa", "Pacific/Pago_Pago",
+        "Pacific/Yap", "Pacific/Truk",
+        "Poland", "Europe/Warsaw",
+        "Portugal", "Europe/Lisbon",
+        "ROC", "Asia/Taipei",
+        "ROK", "Asia/Seoul",
+        "Singapore", "Asia/Singapore",
+        "Turkey", "Europe/Istanbul",
+        "UCT", "Etc/GMT",
+        "US/Alaska", "America/Anchorage",
+        "US/Aleutian", "America/Adak",
+        "US/Arizona", "America/Phoenix",
+        "US/Central", "America/Chicago",
+        "US/East-Indiana", "America/Indianapolis",
+        "US/Eastern", "America/New_York",
+        "US/Hawaii", "Pacific/Honolulu",
+        "US/Indiana-Starke", "America/Indiana/Knox",
+        "US/Michigan", "America/Detroit",
+        "US/Mountain", "America/Denver",
+        "US/Pacific", "America/Los_Angeles",
+        "US/Pacific-New", "America/Los_Angeles",
+        "US/Samoa", "Pacific/Pago_Pago",
+        "UTC", "Etc/GMT",
+        "Universal", "Etc/GMT",
+        "W-SU", "Europe/Moscow",
+        "Zulu", "Etc/GMT",
+    };
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/VersionInfo.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/VersionInfo.java
index 0bac81d..22af593 100644
--- a/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/VersionInfo.java
+++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/VersionInfo.java
@@ -1,14 +1,14 @@
-/*
- *******************************************************************************
- * Copyright (C) 2011, International Business Machines Corporation and         *
- * others. All Rights Reserved.                                                *
- *******************************************************************************
- */
-package com.ibm.icu.util;
-
-/*
- * Empty stub
- */
-public final class VersionInfo {
-    private VersionInfo() {}
-}
+/*
+ *******************************************************************************
+ * Copyright (C) 2011, International Business Machines Corporation and         *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+package com.ibm.icu.util;
+
+/*
+ * Empty stub
+ */
+public final class VersionInfo {
+    private VersionInfo() {}
+}
diff --git a/eclipse-build/plugins.template/com.ibm.icu/.classpath b/eclipse-build/plugins.template/com.ibm.icu/.classpath
index 751c8f2..304e861 100644
--- a/eclipse-build/plugins.template/com.ibm.icu/.classpath
+++ b/eclipse-build/plugins.template/com.ibm.icu/.classpath
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
 	<classpathentry kind="src" path="src"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/main/classes/charset/.settings/org.eclipse.core.resources.prefs b/main/classes/charset/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..54aa8e7
--- /dev/null
+++ b/main/classes/charset/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Wed Aug 31 03:48:17 EDT 2011
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/main/classes/collate/.settings/org.eclipse.core.resources.prefs b/main/classes/collate/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..6d667eb
--- /dev/null
+++ b/main/classes/collate/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Wed Aug 31 03:48:30 EDT 2011
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/main/classes/core/.settings/org.eclipse.core.resources.prefs b/main/classes/core/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..1c4a86f
--- /dev/null
+++ b/main/classes/core/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Wed Aug 31 03:48:42 EDT 2011
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/main/classes/currdata/.settings/org.eclipse.core.resources.prefs b/main/classes/currdata/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..7e42ab3
--- /dev/null
+++ b/main/classes/currdata/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Wed Aug 31 03:48:52 EDT 2011
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/main/classes/langdata/.settings/org.eclipse.core.resources.prefs b/main/classes/langdata/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..dc583d4
--- /dev/null
+++ b/main/classes/langdata/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Wed Aug 31 03:48:58 EDT 2011
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/main/classes/localespi/.settings/org.eclipse.core.resources.prefs b/main/classes/localespi/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..4b89392
--- /dev/null
+++ b/main/classes/localespi/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Wed Aug 31 03:49:04 EDT 2011
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/main/classes/regiondata/.settings/org.eclipse.core.resources.prefs b/main/classes/regiondata/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..8313969
--- /dev/null
+++ b/main/classes/regiondata/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Wed Aug 31 03:49:21 EDT 2011
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/main/classes/translit/.settings/org.eclipse.core.resources.prefs b/main/classes/translit/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..e09cb62
--- /dev/null
+++ b/main/classes/translit/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Wed Aug 31 03:49:37 EDT 2011
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/main/shared/.settings/org.eclipse.core.resources.prefs b/main/shared/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..b425f9a
--- /dev/null
+++ b/main/shared/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Wed Aug 31 03:49:26 EDT 2011
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/main/shared/build/common-targets.xml b/main/shared/build/common-targets.xml
index bfaaf84..219d2a5 100644
--- a/main/shared/build/common-targets.xml
+++ b/main/shared/build/common-targets.xml
@@ -23,7 +23,7 @@
         <echo message="source:         ${javac.source}"/>
         <echo message="target:         ${javac.target}"/>
         <echo message="debug:          ${javac.debug}"/>
-        <echo message="encoding:       ${javac.encoding}"/>
+        <echo message="encoding:       ${java.src.encoding}"/>
         <echo message="compiler arg:   ${javac.compilerarg}"/>
         <echo message="----------------------------------------------------"/>
 
@@ -34,6 +34,7 @@
             classpathref="javac.classpathref"
             source="${javac.source}"
             target="${javac.target}"
+            encoding="${java.src.encoding}"
             debug="${javac.debug}">
             <compilerarg value="${javac.compilerarg}"/>
         </javac>
diff --git a/main/shared/build/common.properties b/main/shared/build/common.properties
index 46e293f..fe4dd02 100644
--- a/main/shared/build/common.properties
+++ b/main/shared/build/common.properties
@@ -22,8 +22,8 @@
 javac.source = 1.5
 javac.target = 1.5
 javac.debug = on
-javac.encoding = ascii
 javac.compilerarg = -Xlint:none
+java.src.encoding = UTF-8
 
 # Manifest attributes
 jar.spec.version = ${icu4j.spec.version}
diff --git a/main/shared/data/icudata.jar b/main/shared/data/icudata.jar
index 4c3f870..4ad226e 100755
--- a/main/shared/data/icudata.jar
+++ b/main/shared/data/icudata.jar
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:c35d58240ba0d7a92fce6316791c1808950d0a0ec01bc120174ae29aab9dace8
-size 6991911
+oid sha256:a27948afa5863dc9ba7a87f8514ac90bf79934f66f4c0f479ddf79cf243f7c4b
+size 6992059
diff --git a/main/tests/charset/.settings/org.eclipse.core.resources.prefs b/main/tests/charset/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..a283349
--- /dev/null
+++ b/main/tests/charset/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Wed Aug 31 03:48:23 EDT 2011
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/main/tests/collate/.settings/org.eclipse.core.resources.prefs b/main/tests/collate/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..48587b7
--- /dev/null
+++ b/main/tests/collate/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Wed Aug 31 03:48:36 EDT 2011
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/main/tests/core/.settings/org.eclipse.core.resources.prefs b/main/tests/core/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..ead970e
--- /dev/null
+++ b/main/tests/core/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Wed Aug 31 03:48:47 EDT 2011
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/main/tests/framework/.settings/org.eclipse.core.resources.prefs b/main/tests/framework/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..73b1196
--- /dev/null
+++ b/main/tests/framework/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Wed Aug 31 03:49:32 EDT 2011
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/main/tests/localespi/.settings/org.eclipse.core.resources.prefs b/main/tests/localespi/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..5fa83b0
--- /dev/null
+++ b/main/tests/localespi/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Wed Aug 31 03:49:10 EDT 2011
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/main/tests/packaging/.settings/org.eclipse.core.resources.prefs b/main/tests/packaging/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..9041229
--- /dev/null
+++ b/main/tests/packaging/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Wed Aug 31 03:49:15 EDT 2011
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/main/tests/translit/.settings/org.eclipse.core.resources.prefs b/main/tests/translit/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..ace814a
--- /dev/null
+++ b/main/tests/translit/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Wed Aug 31 03:49:43 EDT 2011
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/tools/build/.settings/org.eclipse.core.resources.prefs b/tools/build/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..1075bfd
--- /dev/null
+++ b/tools/build/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Wed Aug 31 03:51:40 EDT 2011
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/tools/misc/.settings/org.eclipse.core.resources.prefs b/tools/misc/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..a3a3a76
--- /dev/null
+++ b/tools/misc/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Wed Aug 31 03:51:30 EDT 2011
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
