diff --git a/.gitattributes b/.gitattributes
index 24dac1c..774b853 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -51,11 +51,8 @@
 /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
@@ -63,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
@@ -84,37 +67,6 @@
 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
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..d8a2b85 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,748 @@
-/*
- *******************************************************************************
- * 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;
+
+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]);
+    }
+}
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..7600914 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,180 @@
-/*
- *******************************************************************************
- * 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 (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/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..730d3f7 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,1949 @@
-/*
- *   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;
+
+/**
+ * {@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;
+    }
+}
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..7077e4b 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,840 @@
-/*
- *******************************************************************************
- * 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.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");
+    }
+}
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..9f80883 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,1312 @@
-/*
- *******************************************************************************
- * 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;
+
+/**
+ * {@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;
+    }
+}
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..b09abae 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,2345 @@
-/*
-*   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;
+
+/**
+ * {@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");
+        }
+    }
+}
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/TimeZone.java b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/TimeZone.java
index f775d29..6f5d08c 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,710 @@
-/*
- * @(#)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;
+
+/**
+ * {@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
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..4d49adf 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,2493 @@
-/*
-******************************************************************************
-* 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.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");
+        }
+    }
+}
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() {}
+}
