From d07c135485290ac00738ccfa719770c2b2aa09c1 Mon Sep 17 00:00:00 2001 From: Yoshito Umaoka Date: Fri, 28 Jan 2011 05:19:22 +0000 Subject: [PATCH] ICU-7946 Merging com.ibm.icu.base and com.ibm.icu.base.tests plug-in implementation and build scripts from trunk for Eclipse 3.7 X-SVN-Rev: 29378 --- .gitattributes | 62 + eclipse-build/build.properties | 2 +- eclipse-build/build.xml | 76 +- .../com.ibm.icu.base/.project | 17 + .../com.ibm.icu.base/build.properties | 20 + .../com.ibm.icu.base/feature.xml | 33 + .../com.ibm.icu.base.tests/.classpath | 7 + .../com.ibm.icu.base.tests/.project | 28 + .../.settings/org.eclipse.jdt.core.prefs | 78 + .../.settings/org.eclipse.jdt.ui.prefs | 3 + .../META-INF/MANIFEST.MF | 10 + .../com.ibm.icu.base.tests/build.properties | 17 + .../com.ibm.icu.base.tests/plugin.properties | 12 + .../com/ibm/icu/tests/BreakIteratorTest.java | 359 ++ .../src/com/ibm/icu/tests/CalendarTest.java | 565 +++ .../com/ibm/icu/tests/CollationKeyTest.java | 102 + .../src/com/ibm/icu/tests/CollatorTest.java | 205 + .../ibm/icu/tests/DateFormatSymbolsTest.java | 257 ++ .../src/com/ibm/icu/tests/DateFormatTest.java | 454 ++ .../icu/tests/DecimalFormatSymbolsTest.java | 344 ++ .../com/ibm/icu/tests/DecimalFormatTest.java | 242 + .../src/com/ibm/icu/tests/ICUTestCase.java | 286 ++ .../com/ibm/icu/tests/MessageFormatTest.java | 307 ++ .../com/ibm/icu/tests/NumberFormatTest.java | 447 ++ .../ibm/icu/tests/SimpleDateFormatTest.java | 202 + .../src/com/ibm/icu/tests/TimeZoneTest.java | 235 + .../src/com/ibm/icu/tests/ULocaleTest.java | 748 ++++ .../com.ibm.icu.base/.classpath | 7 + .../com.ibm.icu.base/.project | 28 + .../.settings/org.eclipse.jdt.core.prefs | 77 + .../.settings/org.eclipse.jdt.ui.prefs | 3 + .../com.ibm.icu.base/META-INF/MANIFEST.MF | 15 + .../com.ibm.icu.base/build.properties | 19 + .../com.ibm.icu.base/plugin.properties | 12 + .../src/com/ibm/icu/impl/ICUCache.java | 21 + .../src/com/ibm/icu/impl/LocaleIDParser.java | 741 ++++ .../src/com/ibm/icu/impl/LocaleIDs.java | 536 +++ .../src/com/ibm/icu/impl/LocaleUtility.java | 132 + .../src/com/ibm/icu/impl/SimpleCache.java | 73 + .../com/ibm/icu/impl/locale/AsciiUtil.java | 180 + .../src/com/ibm/icu/math/BigDecimal.java | 3880 +++++++++++++++++ .../src/com/ibm/icu/math/MathContext.java | 601 +++ .../src/com/ibm/icu/text/Bidi.java | 2586 +++++++++++ .../src/com/ibm/icu/text/BidiClassifier.java | 14 + .../src/com/ibm/icu/text/BidiRun.java | 14 + .../src/com/ibm/icu/text/BreakIterator.java | 833 ++++ .../src/com/ibm/icu/text/CollationKey.java | 415 ++ .../src/com/ibm/icu/text/Collator.java | 932 ++++ .../com/ibm/icu/text/CurrencyPluralInfo.java | 14 + .../src/com/ibm/icu/text/DateFormat.java | 1949 +++++++++ .../com/ibm/icu/text/DateFormatSymbols.java | 840 ++++ .../src/com/ibm/icu/text/DecimalFormat.java | 1762 ++++++++ .../ibm/icu/text/DecimalFormatSymbols.java | 350 ++ .../src/com/ibm/icu/text/MessageFormat.java | 1415 ++++++ .../src/com/ibm/icu/text/NumberFormat.java | 1312 ++++++ .../src/com/ibm/icu/text/RawCollationKey.java | 14 + .../com/ibm/icu/text/SimpleDateFormat.java | 514 +++ .../src/com/ibm/icu/text/UFormat.java | 80 + .../src/com/ibm/icu/text/UnicodeSet.java | 14 + .../src/com/ibm/icu/util/Calendar.java | 2345 ++++++++++ .../src/com/ibm/icu/util/Currency.java | 420 ++ .../src/com/ibm/icu/util/CurrencyAmount.java | 14 + .../src/com/ibm/icu/util/TimeZone.java | 710 +++ .../src/com/ibm/icu/util/ULocale.java | 2493 +++++++++++ .../src/com/ibm/icu/util/VersionInfo.java | 14 + 65 files changed, 30494 insertions(+), 3 deletions(-) create mode 100644 eclipse-build/features.template/com.ibm.icu.base/.project create mode 100644 eclipse-build/features.template/com.ibm.icu.base/build.properties create mode 100644 eclipse-build/features.template/com.ibm.icu.base/feature.xml create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base.tests/.classpath create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base.tests/.project create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base.tests/.settings/org.eclipse.jdt.core.prefs create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base.tests/.settings/org.eclipse.jdt.ui.prefs create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base.tests/META-INF/MANIFEST.MF create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base.tests/build.properties create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base.tests/plugin.properties create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/BreakIteratorTest.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/CalendarTest.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/CollationKeyTest.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/CollatorTest.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/DateFormatSymbolsTest.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/DateFormatTest.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/DecimalFormatSymbolsTest.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/DecimalFormatTest.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/ICUTestCase.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/MessageFormatTest.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/NumberFormatTest.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/SimpleDateFormatTest.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/TimeZoneTest.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/ULocaleTest.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base/.classpath create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base/.project create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base/.settings/org.eclipse.jdt.core.prefs create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base/.settings/org.eclipse.jdt.ui.prefs create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base/META-INF/MANIFEST.MF create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base/build.properties create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base/plugin.properties create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/ICUCache.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/LocaleIDParser.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/LocaleIDs.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/LocaleUtility.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/SimpleCache.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/locale/AsciiUtil.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/math/BigDecimal.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/math/MathContext.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/Bidi.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/BidiClassifier.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/BidiRun.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/BreakIterator.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/CollationKey.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/Collator.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/CurrencyPluralInfo.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/DateFormat.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/DateFormatSymbols.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/DecimalFormat.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/DecimalFormatSymbols.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/MessageFormat.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/NumberFormat.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/RawCollationKey.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/SimpleDateFormat.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/UFormat.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/UnicodeSet.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/Calendar.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/Currency.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/CurrencyAmount.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/TimeZone.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/ULocale.java create mode 100644 eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/VersionInfo.java diff --git a/.gitattributes b/.gitattributes index 74bee93cbe5..65b22c7b133 100644 --- a/.gitattributes +++ b/.gitattributes @@ -52,6 +52,68 @@ README text !eol 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 +eclipse-build/plugins.template/com.ibm.icu.base.tests/.settings/org.eclipse.jdt.ui.prefs -text +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 +eclipse-build/plugins.template/com.ibm.icu.base/.settings/org.eclipse.jdt.ui.prefs -text +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/build.properties b/eclipse-build/build.properties index 031f9134c6c..15f2f7c111e 100644 --- a/eclipse-build/build.properties +++ b/eclipse-build/build.properties @@ -5,4 +5,4 @@ icu4j.plugin.impl.version.string=4.4.2 copyright.eclipse=Licensed Materials - Property of IBM \n (C) Copyright IBM Corp. 2000, 2011. All Rights Reserved. \n IBM is a registered trademark of IBM Corp. icu4j.data.version.number=44 -icu4j.eclipse.build.version.string=4.4.2.v20110115 +icu4j.eclipse.build.version.string=4.4.2.v20110128 diff --git a/eclipse-build/build.xml b/eclipse-build/build.xml index 86d82e97fd0..282243fd826 100644 --- a/eclipse-build/build.xml +++ b/eclipse-build/build.xml @@ -27,7 +27,7 @@ @@ -44,6 +44,10 @@ + + + + @@ -262,7 +266,6 @@ - @@ -316,4 +319,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/eclipse-build/features.template/com.ibm.icu.base/.project b/eclipse-build/features.template/com.ibm.icu.base/.project new file mode 100644 index 00000000000..db8f9304a47 --- /dev/null +++ b/eclipse-build/features.template/com.ibm.icu.base/.project @@ -0,0 +1,17 @@ + + + com.ibm.icu.base-feature + + + + + + org.eclipse.pde.FeatureBuilder + + + + + + org.eclipse.pde.FeatureNature + + diff --git a/eclipse-build/features.template/com.ibm.icu.base/build.properties b/eclipse-build/features.template/com.ibm.icu.base/build.properties new file mode 100644 index 00000000000..9d55f55c5aa --- /dev/null +++ b/eclipse-build/features.template/com.ibm.icu.base/build.properties @@ -0,0 +1,20 @@ +############################################################################### +# Copyright (c) 2011 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +############################################################################### +bin.includes =\ +epl-v10.html,\ +eclipse_update_120.jpg,\ +feature.xml,\ +feature.properties,\ +license.html +outputUpdateJars = true + +generate.plugin@com.ibm.icu.base.source=com.ibm.icu.base + diff --git a/eclipse-build/features.template/com.ibm.icu.base/feature.xml b/eclipse-build/features.template/com.ibm.icu.base/feature.xml new file mode 100644 index 00000000000..367bcd27097 --- /dev/null +++ b/eclipse-build/features.template/com.ibm.icu.base/feature.xml @@ -0,0 +1,33 @@ + + + + + [Enter Feature Description here.] + + + + [Enter Copyright Description here.] + + + + [Enter License Description here.] + + + + + + + diff --git a/eclipse-build/plugins.template/com.ibm.icu.base.tests/.classpath b/eclipse-build/plugins.template/com.ibm.icu.base.tests/.classpath new file mode 100644 index 00000000000..45f024e850e --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base.tests/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/eclipse-build/plugins.template/com.ibm.icu.base.tests/.project b/eclipse-build/plugins.template/com.ibm.icu.base.tests/.project new file mode 100644 index 00000000000..3beefc76a2c --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base.tests/.project @@ -0,0 +1,28 @@ + + + com.ibm.icu.base.tests + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/eclipse-build/plugins.template/com.ibm.icu.base.tests/.settings/org.eclipse.jdt.core.prefs b/eclipse-build/plugins.template/com.ibm.icu.base.tests/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000000..9e89b12a05c --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base.tests/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,78 @@ +#Thu Jan 13 17:45:06 EST 2011 +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore +org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecation=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore +org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore +org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.problem.finalParameterBound=ignore +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning +org.eclipse.jdt.core.compiler.problem.nullReference=warning +org.eclipse.jdt.core.compiler.source=1.5 +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore +org.eclipse.jdt.core.compiler.problem.deadCode=ignore +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore +org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=error +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled diff --git a/eclipse-build/plugins.template/com.ibm.icu.base.tests/.settings/org.eclipse.jdt.ui.prefs b/eclipse-build/plugins.template/com.ibm.icu.base.tests/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 00000000000..d57be9d85cd --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base.tests/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,3 @@ +#Thu Dec 14 11:51:01 EST 2006 +eclipse.preferences.version=1 +internal.default.compliance=default diff --git a/eclipse-build/plugins.template/com.ibm.icu.base.tests/META-INF/MANIFEST.MF b/eclipse-build/plugins.template/com.ibm.icu.base.tests/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..fccd74066e3 --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base.tests/META-INF/MANIFEST.MF @@ -0,0 +1,10 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %pluginName +Bundle-SymbolicName: com.ibm.icu.base.tests +Bundle-Version: @BUILD_VERSION@ +Bundle-Vendor: %providerName +Fragment-Host: com.ibm.icu.base +Bundle-Copyright: @COPYRIGHT@ +Require-Bundle: org.junit +Bundle-RequiredExecutionEnvironment: J2SE-1.5 diff --git a/eclipse-build/plugins.template/com.ibm.icu.base.tests/build.properties b/eclipse-build/plugins.template/com.ibm.icu.base.tests/build.properties new file mode 100644 index 00000000000..b6bb464ebf8 --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base.tests/build.properties @@ -0,0 +1,17 @@ +############################################################################### +# Copyright (c) 2000, 2011 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +############################################################################### +source.. = src/ +output.. = bin/ +bin.includes = .,\ + about.html,\ + about_files/,\ + plugin.properties,\ + META-INF/ diff --git a/eclipse-build/plugins.template/com.ibm.icu.base.tests/plugin.properties b/eclipse-build/plugins.template/com.ibm.icu.base.tests/plugin.properties new file mode 100644 index 00000000000..a991df0374d --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base.tests/plugin.properties @@ -0,0 +1,12 @@ +############################################################################### +# Copyright (c) 2011 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +############################################################################### +pluginName = International Components for Unicode for Java (ICU4J) Replacement plug-in Tests +providerName = IBM Corporation \ No newline at end of file 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 new file mode 100644 index 00000000000..6b26f3b2f30 --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/BreakIteratorTest.java @@ -0,0 +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 + } +} 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 new file mode 100644 index 00000000000..69195a2a4e9 --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/CalendarTest.java @@ -0,0 +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()); + } +} 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 new file mode 100644 index 00000000000..45725be90c2 --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/CollationKeyTest.java @@ -0,0 +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); + } +} 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 new file mode 100644 index 00000000000..08349f18cbb --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/CollatorTest.java @@ -0,0 +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 + } +} 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 new file mode 100644 index 00000000000..2021969e0f1 --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/DateFormatSymbolsTest.java @@ -0,0 +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 + } +} 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 new file mode 100644 index 00000000000..37f5559f0aa --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/DateFormatTest.java @@ -0,0 +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 + } +} 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 new file mode 100644 index 00000000000..9cc7ce6837d --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/DecimalFormatSymbolsTest.java @@ -0,0 +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 + } +} 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 new file mode 100644 index 00000000000..23cc40d6f52 --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/DecimalFormatTest.java @@ -0,0 +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)); + } +} 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 new file mode 100644 index 00000000000..2e3de90a441 --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/ICUTestCase.java @@ -0,0 +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 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 lcls = lhs.getClass(); + Class 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 lcls = lhs.getClass(); + Class 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 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 new file mode 100644 index 00000000000..7f269fae9aa --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/MessageFormatTest.java @@ -0,0 +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 + } +} 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 new file mode 100644 index 00000000000..3c7b7dd9dca --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/NumberFormatTest.java @@ -0,0 +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 + } +} 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 new file mode 100644 index 00000000000..2bf36232777 --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/SimpleDateFormatTest.java @@ -0,0 +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")); + } +} 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 new file mode 100644 index 00000000000..d85d0a24ddc --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/TimeZoneTest.java @@ -0,0 +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 + } +} 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 new file mode 100644 index 00000000000..21cf50bfc54 --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base.tests/src/com/ibm/icu/tests/ULocaleTest.java @@ -0,0 +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 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 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/.classpath b/eclipse-build/plugins.template/com.ibm.icu.base/.classpath new file mode 100644 index 00000000000..02159672985 --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/.project b/eclipse-build/plugins.template/com.ibm.icu.base/.project new file mode 100644 index 00000000000..5e6c7c3bced --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base/.project @@ -0,0 +1,28 @@ + + + com.ibm.icu.base + + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.pde.PluginNature + + diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/.settings/org.eclipse.jdt.core.prefs b/eclipse-build/plugins.template/com.ibm.icu.base/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000000..852d94d7dfb --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,77 @@ +#Mon Aug 30 14:05:56 EDT 2010 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.assertIdentifier=ignore +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning +org.eclipse.jdt.core.compiler.problem.deadCode=warning +org.eclipse.jdt.core.compiler.problem.deprecation=ignore +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore +org.eclipse.jdt.core.compiler.problem.enumIdentifier=ignore +org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=error +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore +org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore +org.eclipse.jdt.core.compiler.problem.nullReference=warning +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore +org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore +org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning +org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.source=1.5 diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/.settings/org.eclipse.jdt.ui.prefs b/eclipse-build/plugins.template/com.ibm.icu.base/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 00000000000..22f322c51ad --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,3 @@ +#Thu Dec 14 11:50:17 EST 2006 +eclipse.preferences.version=1 +internal.default.compliance=default diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/META-INF/MANIFEST.MF b/eclipse-build/plugins.template/com.ibm.icu.base/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..fb58cf711ea --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base/META-INF/MANIFEST.MF @@ -0,0 +1,15 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %pluginName +Bundle-SymbolicName: com.ibm.icu.base; singleton:=true +Bundle-Version: @BUILD_VERSION@ +Bundle-Vendor: %providerName +Bundle-Localization: plugin +Bundle-Copyright: @COPYRIGHT@ +Export-Package: com.ibm.icu.text;base=true;version="@IMPL_VERSION@", + com.ibm.icu.util;base=true;version="@IMPL_VERSION@", + com.ibm.icu.math;base=true;version="@IMPL_VERSION@", + com.ibm.icu.impl;x-internal:=true, + com.ibm.icu.impl.locale;x-internal:=true +Eclipse-LazyStart: true +Bundle-RequiredExecutionEnvironment: J2SE-1.5 diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/build.properties b/eclipse-build/plugins.template/com.ibm.icu.base/build.properties new file mode 100644 index 00000000000..8b3ddc31ddb --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base/build.properties @@ -0,0 +1,19 @@ +############################################################################### +# Copyright (c) 2011 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +############################################################################### +source.. = src/ +output.. = bin/ +src.includes = about.html,\ + about_files/ +bin.includes = .,\ + about.html,\ + about_files/,\ + plugin.properties,\ + META-INF/ diff --git a/eclipse-build/plugins.template/com.ibm.icu.base/plugin.properties b/eclipse-build/plugins.template/com.ibm.icu.base/plugin.properties new file mode 100644 index 00000000000..05f97ff88b9 --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base/plugin.properties @@ -0,0 +1,12 @@ +############################################################################### +# Copyright (c) 2011 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +############################################################################### +pluginName = International Components for Unicode for Java (ICU4J) Replacement plug-in +providerName = IBM Corporation \ No newline at end of file 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 new file mode 100644 index 00000000000..c3ca4b5a207 --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/ICUCache.java @@ -0,0 +1,21 @@ +/* + *************************************************************************** + * Copyright (c) 2007-2011 International Business Machines Corporation and * + * others. All rights reserved. * + *************************************************************************** +*/ + +package com.ibm.icu.impl; + +public interface ICUCache { + // 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 new file mode 100644 index 00000000000..a9d0d306893 --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/LocaleIDParser.java @@ -0,0 +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 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 getKeyComparator() { + final Comparator comp = new Comparator() { + 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 getKeywordMap() { + if (keywords == null) { + TreeMap 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(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.emptyMap(); + } + + return keywords; + } + + + /** + * Parse the keywords and return start of the string in the buffer. + */ + private int parseKeywords() { + int oldBlen = blen; + Map m = getKeywordMap(); + if (!m.isEmpty()) { + boolean first = true; + for (Map.Entry 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 getKeywords() { + Map 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 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.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 m = getKeywordMap(); + if (m.isEmpty()) { // it is EMPTY_MAP + if (value != null) { + // force new map + keywords = new TreeMap(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.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 new file mode 100644 index 00000000000..8edd3d48003 --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/LocaleIDs.java @@ -0,0 +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 + * ftp://dkuug.dk/i18n/iso-639-2.txt + * @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 new file mode 100644 index 00000000000..f219f099676 --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/LocaleUtility.java @@ -0,0 +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]); + } +} 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 new file mode 100644 index 00000000000..fc431b05e19 --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/SimpleCache.java @@ -0,0 +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 implements ICUCache { + private static final int DEFAULT_CAPACITY = 16; + + private Reference> 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> ref = cacheRef; + if (ref != null) { + Map map = ref.get(); + if (map != null) { + return map.get(key); + } + } + return null; + } + + public void put(K key, V value) { + Reference> ref = cacheRef; + Map map = null; + if (ref != null) { + map = ref.get(); + } + if (map == null) { + map = Collections.synchronizedMap(new HashMap(capacity)); + if (type == ICUCache.WEAK) { + ref = new WeakReference>(map); + } else { + ref = new SoftReference>(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 new file mode 100644 index 00000000000..24383f0d39c --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/impl/locale/AsciiUtil.java @@ -0,0 +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; + } + } +} 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 new file mode 100644 index 00000000000..3dfa95bc2a7 --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/math/BigDecimal.java @@ -0,0 +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) ; 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 BigDecimal class implements immutable arbitrary-precision decimal numbers. The methods of the + * BigDecimal class provide operations for fixed and floating point arithmetic, comparison, format + * conversions, and hashing. + *

+ * 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 (char[]) objects, as well as conversions to and from the Java + * primitive types (which may not be exact) and BigInteger. + *

+ * In the descriptions of constructors and methods in this documentation, the value of a BigDecimal number + * object is shown as the result of invoking the toString() 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. + *

+ * The floating point arithmetic provided by this class is defined by the ANSI X3.274-1996 standard, and is also + * documented at http://www2.hursley.ibm.com/decimal
+ * [This URL will change.] + * + *

Operator methods

+ *

+ * Operations on BigDecimal numbers are controlled by a {@link MathContext} object, which provides the + * context (precision and other information) for the operation. Methods that can take a MathContext + * parameter implement the standard arithmetic operators for BigDecimal objects and are known as + * operator methods. The default settings provided by the constant {@link MathContext#DEFAULT} (digits=9, + * form=SCIENTIFIC, lostDigits=false, roundingMode=ROUND_HALF_UP) perform general-purpose floating point + * arithmetic to nine digits of precision. The MathContext parameter must not be null. + *

+ * Each operator method also has a version provided which does not take a MathContext parameter. For this + * version of each method, the context settings used are digits=0, + * form=PLAIN, lostDigits=false, roundingMode=ROUND_HALF_UP; these settings perform fixed point arithmetic with + * unlimited precision, as defined for the original BigDecimal class in Java 1.1 and Java 1.2. + *

+ * For monadic operators, only the optional MathContext parameter is present; the operation acts upon the + * current object. + *

+ * For dyadic operators, a BigDecimal parameter is always present; it must not be null. The + * operation acts with the current object being the left-hand operand and the BigDecimal parameter being + * the right-hand operand. + *

+ * For example, adding two BigDecimal objects referred to by the names award and + * extra could be written as any of: + *

+ * + * award.add(extra) + *
award.add(extra, MathContext.DEFAULT) + *
award.add(extra, acontext) + *
+ *

+ * (where acontext is a MathContext object), which would return a BigDecimal + * object whose value is the result of adding award and extra under the appropriate context + * settings. + *

+ * When a BigDecimal 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: + *

    + *
  • Results are normally calculated with up to some maximum number of significant digits. For example, if the + * MathContext parameter for an operation were MathContext.DEFAULT then the result would be + * rounded to 9 digits; the division of 2 by 3 would then result in 0.666666667.
    + * You can change the default of 9 significant digits by providing the method with a suitable MathContext + * object. This lets you calculate using as many digits as you need -- thousands, if necessary. Fixed point (scaled) + * arithmetic is indicated by using a digits setting of 0 (or omitting the MathContext + * parameter).
    + * Similarly, you can change the algorithm used for rounding from the default "classic" algorithm. + *
  • + * In standard arithmetic (that is, when the form setting is not PLAIN), a zero result is + * always expressed as the single digit '0' (that is, with no sign, decimal point, or exponent part). + *
  • + * 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).
    + * So, for example: + *

    + * + * new BigDecimal("2.40").add( new BigDecimal("2")) => "4.40" + *
    new BigDecimal("2.40").subtract(new BigDecimal("2")) => "0.40" + *
    new BigDecimal("2.40").multiply(new BigDecimal("2")) => "4.80" + *
    new BigDecimal("2.40").divide( new BigDecimal("2"), def) => "1.2" + *
    + *

    + * where the value on the right of the => would be the result of the operation, expressed as a + * String, and def (in this and following examples) refers to MathContext.DEFAULT + * ). 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. + *

  • + * In standard arithmetic, exponential form is used for a result depending on its value and the current setting of + * digits (the default is 9 digits). If the number of places needed before the decimal point exceeds the + * digits setting, or the absolute value of the number is less than 0.000001, then the number + * will be expressed in exponential notation; thus + *

    + * + * new BigDecimal("1e+6").multiply(new BigDecimal("1e+6"), def) + * + *

    + * results in 1E+12 instead of 1000000000000, and + *

    + * + * new BigDecimal("1").divide(new BigDecimal("3E+10"), def) + * + *

    + * results in 3.33333333E-11 instead of 0.0000000000333333333. + *

    + * The form of the exponential notation (scientific or engineering) is determined by the form setting. + * + *

    + * The names of methods in this class follow the conventions established by java.lang.Number, + * java.math.BigInteger, and java.math.BigDecimal 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 { + // private static final java.lang.String $0="BigDecimal.nrx"; + + /* ----- Constants ----- */ + /* properties constant public */// useful to others + /** + * The BigDecimal 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 BigDecimal 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 BigDecimal 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: + *

      + *
    • ispos -- the number is positive
    • iszero -- the number is zero
    • isneg -- the number is negative + *
    + * + * @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: + *
      + *
    • MathContext.PLAIN -- no exponent needed
    • MathContext.SCIENTIFIC -- scientific notation required
    • + * MathContext.ENGINEERING -- engineering notation required + *
    + *

    + * 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. + *

    + * Once constructed, this may become shared between several BigDecimal objects, so must not be altered. + *

    + * For efficiency (speed), this is a byte array, with each byte taking a value of 0 -> 9. + *

    + * 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. + *

    + * For fixed point arithmetic, scale is -exp, 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 BigDecimal object from a java.math.BigDecimal. + *

    + * Constructs a BigDecimal as though the parameter had been represented as a String (using + * its toString method) and the {@link #BigDecimal(java.lang.String)} constructor had then been used. + * The parameter must not be null. + *

    + * (Note: this constructor is provided only in the com.ibm.icu.math version of the BigDecimal class. + * It would not be present in a java.math version.) + * + * @param bd The BigDecimal to be translated. + * @stable ICU 2.0 + */ + + public BigDecimal(java.math.BigDecimal bd) { + this(bd.toString()); + return; + } + + /** + * Constructs a BigDecimal object from a BigInteger, with scale 0. + *

    + * Constructs a BigDecimal which is the exact decimal representation of the BigInteger, + * with a scale of zero. The value of the BigDecimal is identical to the value of the BigInteger + * . The parameter must not be null. + *

    + * The BigDecimal will contain only decimal digits, prefixed with a leading minus sign (hyphen) if the + * BigInteger is negative. A leading zero will be present only if the BigInteger is zero. + * + * @param bi The BigInteger to be converted. + * @stable ICU 2.0 + */ + + public BigDecimal(java.math.BigInteger bi) { + this(bi.toString(10)); + return; + } + + // exp remains 0 + + /** + * Constructs a BigDecimal object from a BigInteger and a scale. + *

    + * Constructs a BigDecimal which is the exact decimal representation of the BigInteger, + * scaled by the second parameter, which may not be negative. The value of the BigDecimal is the + * BigInteger divided by ten to the power of the scale. The BigInteger parameter must not be + * null. + *

    + * The BigDecimal will contain only decimal digits, (with an embedded decimal point followed by + * scale decimal digits if the scale is positive), prefixed with a leading minus sign (hyphen) if the + * BigInteger is negative. A leading zero will be present only if the BigInteger is zero. + * + * @param bi The BigInteger to be converted. + * @param scale The int 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 BigDecimal object from an array of characters. + *

    + * Constructs a BigDecimal as though a String had been constructed from the character + * array and the {@link #BigDecimal(java.lang.String)} constructor had then been used. The parameter must not be + * null. + *

    + * Using this constructor is faster than using the BigDecimal(String) constructor if the string is + * already available in character array form. + * + * @param inchars The char[] 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 BigDecimal object from an array of characters. + *

    + * Constructs a BigDecimal as though a String 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 null, and the subarray must be wholly contained within it. + *

    + * Using this constructor is faster than using the BigDecimal(String) constructor if the string is + * already available within a character array. + * + * @param inchars The char[] array containing the number to be converted. + * @param offset The int offset into the array of the start of the number to be converted. + * @param length The int 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 BigDecimal object directly from a double. + *

    + * Constructs a BigDecimal which is the exact decimal representation of the 64-bit signed binary + * floating point parameter. + *

    + * Note that this constructor it an exact conversion; it does not give the same result as converting num + * to a String using the Double.toString() 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 BigDecimal from a double. + * + * @param num The double 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 BigDecimal object directly from a int. + *

    + * Constructs a BigDecimal which is the exact decimal representation of the 32-bit signed binary + * integer parameter. The BigDecimal 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 int 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 BigDecimal object directly from a long. + *

    + * Constructs a BigDecimal which is the exact decimal representation of the 64-bit signed binary + * integer parameter. The BigDecimal 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 long 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 BigDecimal object from a String. + *

    + * Constructs a BigDecimal from the parameter, which must not be null and must represent a + * valid number, as described formally in the documentation referred to {@link BigDecimal above}. + *

    + * In summary, numbers in String 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. + *

    + * Some valid strings from which a BigDecimal might be constructed are: + * + *

    +     * 
    +     * "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
    +     * 
    +     * 
    + *

    + * (Exponential notation means that the number includes an optional sign and a power of ten following an + * 'E' that indicates how the decimal point will be shifted. Thus the "4E+9" above is + * just a short way of writing 4000000000, and the "0.73e-7" is short for + * 0.000000073.) + *

    + * The BigDecimal 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 e or an E), then the BigDecimal + * 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. + *

    + * Any digits in the parameter must be decimal; that is, Character.digit(c, 10) (where c + * is the character in question) would not return -1. + * + * @param string The String 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; + } + + /* Make a default BigDecimal object for local use. */ + + private BigDecimal() { + super(); + return; + } + + /* ---------------------------------------------------------------- */ + /* Operator methods [methods which take a context parameter] */ + /* ---------------------------------------------------------------- */ + + /** + * Returns a plain BigDecimal whose value is the absolute value of this BigDecimal. + *

    + * The same as {@link #abs(MathContext)}, where the context is new MathContext(0, MathContext.PLAIN). + *

    + * The length of the decimal part (the scale) of the result will be this.scale() + * + * @return A BigDecimal whose value is the absolute value of this BigDecimal. + * @stable ICU 2.0 + */ + + public com.ibm.icu.math.BigDecimal abs() { + return this.abs(plainMC); + } + + /** + * Returns a BigDecimal whose value is the absolute value of this BigDecimal. + *

    + * 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 MathContext arithmetic settings. + * @return A BigDecimal whose value is the absolute value of this BigDecimal. + * @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 BigDecimal whose value is this+rhs, using fixed point arithmetic. + *

    + * The same as {@link #add(BigDecimal, MathContext)}, where the BigDecimal is rhs, and the + * context is new MathContext(0, MathContext.PLAIN). + *

    + * 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 BigDecimal for the right hand side of the addition. + * @return A BigDecimal whose value is this+rhs, 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 BigDecimal whose value is this+rhs. + *

    + * Implements the addition (+) operator (as defined in the decimal documentation, see + * {@link BigDecimal class header}), and returns the result as a BigDecimal object. + * + * @param rhs The BigDecimal for the right hand side of the addition. + * @param set The MathContext arithmetic settings. + * @return A BigDecimal whose value is this+rhs. + * @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 BigDecimal to another, using unlimited precision. + *

    + * The same as {@link #compareTo(BigDecimal, MathContext)}, where the BigDecimal is rhs, + * and the context is new MathContext(0, MathContext.PLAIN). + * + * @param rhs The BigDecimal for the right hand side of the comparison. + * @return An int whose value is -1, 0, or 1 as this is numerically less than, equal to, + * or greater than rhs. + * @stable ICU 2.0 + */ + + public int compareTo(com.ibm.icu.math.BigDecimal rhs) { + return this.compareTo(rhs, plainMC); + } + + /** + * Compares this BigDecimal to another. + *

    + * Implements numeric comparison, (as defined in the decimal documentation, see {@link BigDecimal class header}), + * and returns a result of type int. + *

    + * The result will be: + * + * + * + * + * + * + * + * + * + * + *
    -1 if the current object is less than the first parameter
    0 if the current object is equal to the first parameter
    1 if the current object is greater than the first parameter.
    + *

    + * A {@link #compareTo(BigDecimal)} method is also provided. + * + * @param rhs The BigDecimal for the right hand side of the comparison. + * @param set The MathContext arithmetic settings. + * @return An int whose value is -1, 0, or 1 as this is numerically less than, equal to, + * or greater than rhs. + * @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 BigDecimal whose value is this/rhs, using fixed point arithmetic. + *

    + * The same as {@link #divide(BigDecimal, int)}, where the BigDecimal is rhs, 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 BigDecimal for the right hand side of the division. + * @return A plain BigDecimal whose value is this/rhs, using fixed point arithmetic. + * @throws ArithmeticException If rhs 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 BigDecimal whose value is this/rhs, using fixed point arithmetic and a + * rounding mode. + *

    + * The same as {@link #divide(BigDecimal, int, int)}, where the BigDecimal is rhs, and the + * second parameter is this.scale(), and the third is round. + *

    + * 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. + *

    + * + * @param rhs The BigDecimal for the right hand side of the division. + * @param round The int rounding mode to be used for the division (see the {@link MathContext} class). + * @return A plain BigDecimal whose value is this/rhs, using fixed point arithmetic and + * the specified rounding mode. + * @throws IllegalArgumentException if round is not a valid rounding mode. + * @throws ArithmeticException if rhs is zero. + * @throws ArithmeticException if round is {@link MathContext#ROUND_UNNECESSARY} and this.scale() 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 BigDecimal whose value is this/rhs, using fixed point arithmetic and a + * given scale and rounding mode. + *

    + * The same as {@link #divide(BigDecimal, MathContext)}, where the BigDecimal is rhs, + * new MathContext(0, MathContext.PLAIN, false, round), except that the length of the decimal part (the + * scale) to be used for the result is explicit rather than being taken from this. + *

    + * 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 BigDecimal for the right hand side of the division. + * @param scale The int scale to be used for the result. + * @param round The int rounding mode to be used for the division (see the {@link MathContext} class). + * @return A plain BigDecimal whose value is this/rhs, using fixed point arithmetic and + * the specified rounding mode. + * @throws IllegalArgumentException if round is not a valid rounding mode. + * @throws ArithmeticException if rhs is zero. + * @throws ArithmeticException if scale is negative. + * @throws ArithmeticException if round is {@link MathContext#ROUND_UNNECESSARY} and scale 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 BigDecimal whose value is this/rhs. + *

    + * Implements the division (/) operator (as defined in the decimal documentation, see + * {@link BigDecimal class header}), and returns the result as a BigDecimal object. + * + * @param rhs The BigDecimal for the right hand side of the division. + * @param set The MathContext arithmetic settings. + * @return A BigDecimal whose value is this/rhs. + * @throws ArithmeticException if rhs 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 BigDecimal whose value is the integer part of this/rhs. + *

    + * The same as {@link #divideInteger(BigDecimal, MathContext)}, where the BigDecimal is rhs + * , and the context is new MathContext(0, MathContext.PLAIN). + * + * @param rhs The BigDecimal for the right hand side of the integer division. + * @return A BigDecimal whose value is the integer part of this/rhs. + * @throws ArithmeticException if rhs 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 BigDecimal whose value is the integer part of this/rhs. + *

    + * Implements the integer division operator (as defined in the decimal documentation, see {@link BigDecimal class + * header}), and returns the result as a BigDecimal object. + * + * @param rhs The BigDecimal for the right hand side of the integer division. + * @param set The MathContext arithmetic settings. + * @return A BigDecimal whose value is the integer part of this/rhs. + * @throws ArithmeticException if rhs 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 BigDecimal whose value is the maximum of this and rhs. + *

    + * The same as {@link #max(BigDecimal, MathContext)}, where the BigDecimal is rhs, and the + * context is new MathContext(0, MathContext.PLAIN). + * + * @param rhs The BigDecimal for the right hand side of the comparison. + * @return A BigDecimal whose value is the maximum of this and rhs. + * @stable ICU 2.0 + */ + + public com.ibm.icu.math.BigDecimal max(com.ibm.icu.math.BigDecimal rhs) { + return this.max(rhs, plainMC); + } + + /** + * Returns a BigDecimal whose value is the maximum of this and rhs. + *

    + * Returns the larger of the current object and the first parameter. + *

    + * If calling the {@link #compareTo(BigDecimal, MathContext)} method with the same parameters would return 1 + * or 0, then the result of calling the {@link #plus(MathContext)} method on the current object + * (using the same MathContext parameter) is returned. Otherwise, the result of calling the + * {@link #plus(MathContext)} method on the first parameter object (using the same MathContext + * parameter) is returned. + * + * @param rhs The BigDecimal for the right hand side of the comparison. + * @param set The MathContext arithmetic settings. + * @return A BigDecimal whose value is the maximum of this and rhs. + * @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 BigDecimal whose value is the minimum of this and rhs. + *

    + * The same as {@link #min(BigDecimal, MathContext)}, where the BigDecimal is rhs, and the + * context is new MathContext(0, MathContext.PLAIN). + * + * @param rhs The BigDecimal for the right hand side of the comparison. + * @return A BigDecimal whose value is the minimum of this and rhs. + * @stable ICU 2.0 + */ + + public com.ibm.icu.math.BigDecimal min(com.ibm.icu.math.BigDecimal rhs) { + return this.min(rhs, plainMC); + } + + /** + * Returns a BigDecimal whose value is the minimum of this and rhs. + *

    + * Returns the smaller of the current object and the first parameter. + *

    + * If calling the {@link #compareTo(BigDecimal, MathContext)} method with the same parameters would return -1 + * or 0, then the result of calling the {@link #plus(MathContext)} method on the current object + * (using the same MathContext parameter) is returned. Otherwise, the result of calling the + * {@link #plus(MathContext)} method on the first parameter object (using the same MathContext + * parameter) is returned. + * + * @param rhs The BigDecimal for the right hand side of the comparison. + * @param set The MathContext arithmetic settings. + * @return A BigDecimal whose value is the minimum of this and rhs. + * @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 BigDecimal whose value is this*rhs, using fixed point arithmetic. + *

    + * The same as {@link #add(BigDecimal, MathContext)}, where the BigDecimal is rhs, and the + * context is new MathContext(0, MathContext.PLAIN). + *

    + * 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 BigDecimal for the right hand side of the multiplication. + * @return A BigDecimal whose value is this*rhs, 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 BigDecimal whose value is this*rhs. + *

    + * Implements the multiplication ( ) operator (as defined in the decimal documentation, see + * {@link BigDecimal class header}), and returns the result as a BigDecimal object. + * + * @param rhs The BigDecimal for the right hand side of the multiplication. + * @param set The MathContext arithmetic settings. + * @return A BigDecimal whose value is this*rhs. + * @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 BigDecimal whose value is -this. + *

    + * The same as {@link #negate(MathContext)}, where the context is new MathContext(0, MathContext.PLAIN) + * . + *

    + * The length of the decimal part (the scale) of the result will be be this.scale() + * + * + * @return A BigDecimal whose value is -this. + * @stable ICU 2.0 + */ + + public com.ibm.icu.math.BigDecimal negate() { + return this.negate(plainMC); + } + + /** + * Returns a BigDecimal whose value is -this. + *

    + * Implements the negation (Prefix -) operator (as defined in the decimal documentation, see + * {@link BigDecimal class header}), and returns the result as a BigDecimal object. + * + * @param set The MathContext arithmetic settings. + * @return A BigDecimal whose value is -this. + * @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 BigDecimal whose value is +this. Note that this is not + * necessarily a plain BigDecimal, but the result will always be. + *

    + * The same as {@link #plus(MathContext)}, where the context is new MathContext(0, MathContext.PLAIN). + *

    + * The length of the decimal part (the scale) of the result will be be this.scale() + * + * @return A BigDecimal whose value is +this. + * @stable ICU 2.0 + */ + + public com.ibm.icu.math.BigDecimal plus() { + return this.plus(plainMC); + } + + /** + * Returns a BigDecimal whose value is +this. + *

    + * Implements the plus (Prefix +) operator (as defined in the decimal documentation, see + * {@link BigDecimal class header}), and returns the result as a BigDecimal object. + *

    + * This method is useful for rounding or otherwise applying a context to a decimal value. + * + * @param set The MathContext arithmetic settings. + * @return A BigDecimal whose value is +this. + * @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 BigDecimal whose value is this**rhs, using fixed point arithmetic. + *

    + * The same as {@link #pow(BigDecimal, MathContext)}, where the BigDecimal is rhs, and the + * context is new MathContext(0, MathContext.PLAIN). + *

    + * The parameter is the power to which the this 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. + *

    + * In addition, the power must not be negative, as no MathContext is used and so the result would then + * always be 0. + * + * @param rhs The BigDecimal for the right hand side of the operation (the power). + * @return A BigDecimal whose value is this**rhs, using fixed point arithmetic. + * @throws ArithmeticException if rhs 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 BigDecimal whose value is this**rhs. + *

    + * Implements the power ( ) operator (as defined in the decimal documentation, see + * {@link BigDecimal class header}), and returns the result as a BigDecimal object. + *

    + * The first parameter is the power to which the this 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. + *

    + * If the digits setting of the MathContext parameter is 0, the power must be zero or + * positive. + * + * @param rhs The BigDecimal for the right hand side of the operation (the power). + * @param set The MathContext arithmetic settings. + * @return A BigDecimal whose value is this**rhs. + * @throws ArithmeticException if rhs 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 BigDecimal whose value is the remainder of this/rhs, using fixed point + * arithmetic. + *

    + * The same as {@link #remainder(BigDecimal, MathContext)}, where the BigDecimal is rhs, + * and the context is new MathContext(0, MathContext.PLAIN). + *

    + * This is not the modulo operator -- the result may be negative. + * + * @param rhs The BigDecimal for the right hand side of the remainder operation. + * @return A BigDecimal whose value is the remainder of this/rhs, using fixed point + * arithmetic. + * @throws ArithmeticException if rhs 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 BigDecimal whose value is the remainder of this/rhs. + *

    + * Implements the remainder operator (as defined in the decimal documentation, see {@link BigDecimal class header}), + * and returns the result as a BigDecimal object. + *

    + * This is not the modulo operator -- the result may be negative. + * + * @param rhs The BigDecimal for the right hand side of the remainder operation. + * @param set The MathContext arithmetic settings. + * @return A BigDecimal whose value is the remainder of this+rhs. + * @throws ArithmeticException if rhs 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 BigDecimal whose value is this-rhs, using fixed point arithmetic. + *

    + * The same as {@link #subtract(BigDecimal, MathContext)}, where the BigDecimal is rhs, + * and the context is new MathContext(0, MathContext.PLAIN). + *

    + * 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 BigDecimal for the right hand side of the subtraction. + * @return A BigDecimal whose value is this-rhs, 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 BigDecimal whose value is this-rhs. + *

    + * Implements the subtraction (-) operator (as defined in the decimal documentation, see + * {@link BigDecimal class header}), and returns the result as a BigDecimal object. + * + * @param rhs The BigDecimal for the right hand side of the subtraction. + * @param set The MathContext arithmetic settings. + * @return A BigDecimal whose value is this-rhs. + * @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 BigDecimal to a byte. If the BigDecimal has a non-zero + * decimal part or is out of the possible range for a byte (8-bit signed integer) result then an + * ArithmeticException is thrown. + * + * @return A byte equal in value to this. + * @throws ArithmeticException if this has a non-zero decimal part, or will not fit in a byte. + * @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 BigDecimal to a double. If the BigDecimal is out of the + * possible range for a double (64-bit signed floating point) result then an ArithmeticException + * is thrown. + *

    + * The double produced is identical to result of expressing the BigDecimal as a String and + * then converting it using the Double(String) constructor; this can result in values of + * Double.NEGATIVE_INFINITY or Double.POSITIVE_INFINITY. + * + * @return A double corresponding to this. + * @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 BigDecimal with rhs for equality. + *

    + * If the parameter is null, or is not an instance of the BigDecimal type, or is not exactly equal to + * the current BigDecimal object, then false is returned. Otherwise, true is returned. + *

    + * "Exactly equal", here, means that the String representations of the BigDecimal numbers + * are identical (they have the same characters in the same sequence). + *

    + * The {@link #compareTo(BigDecimal, MathContext)} method should be used for more general comparisons. + * + * @param obj The Object for the right hand side of the comparison. + * @return A boolean whose value true if and only if the operands have identical string + * representations. + * @throws ClassCastException if rhs cannot be cast to a BigDecimal 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 BigDecimal to a float. If the BigDecimal is out of the + * possible range for a float (32-bit signed floating point) result then an ArithmeticException + * is thrown. + *

    + * The float produced is identical to result of expressing the BigDecimal as a String and + * then converting it using the Float(String) constructor; this can result in values of + * Float.NEGATIVE_INFINITY or Float.POSITIVE_INFINITY. + * + * @return A float corresponding to this. + * @stable ICU 2.0 + */ + + public float floatValue() { + return java.lang.Float.valueOf(this.toString()).floatValue(); + } + + /** + * Returns the String representation of this BigDecimal, modified by layout parameters. + *

    + * This method is provided as a primitive for use by more sophisticated classes, such as DecimalFormat + * , 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. + * + *

    + * The parameters, for both forms of the format method are all of type int. A value of -1 + * for any parameter indicates that the default action or value for that parameter should be used. + *

    + * The parameters, before and after, 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. + *

    + * before 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 before is not large enough to + * contain the integer part of the number (including the sign, for negative numbers) an exception is thrown. + *

    + * after 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 after 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, MathContext.ROUND_HALF_UP. + *

    + * 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 int specifying the number of places before the decimal point. Use -1 for 'as many as are needed'. + * @param after The int specifying the number of places after the decimal point. Use -1 for 'as many as are needed'. + * @return A String representing this BigDecimal, 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 String representation of this BigDecimal, modified by layout parameters and + * allowing exponential notation. + *

    + * This method is provided as a primitive for use by more sophisticated classes, such as DecimalFormat + * , 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. + * + *

    + * The parameters are all of type int. A value of -1 for any parameter indicates that the default + * action or value for that parameter should be used. + *

    + * The first two parameters (before and after) 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. + *

    + * The remaining parameters control the use of exponential notation and rounding. Three (explaces, + * exdigits, and exform) 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. + *

    + * explaces 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 explaces is -1) being to use as many + * as are needed. If explaces is not -1, space is always reserved for an exponent; if one is not needed + * (for example, if the exponent will be 0) then explaces+2 blanks are appended to the result. If explaces + * is not -1 and is not large enough to contain the exponent, an exception is thrown. + *

    + * exdigits sets the trigger point for use of exponential notation. If, before any rounding, the number + * of places needed before the decimal point exceeds exdigits, or if the absolute value of the result + * is less than 0.000001, then exponential form will be used, provided that exdigits was + * specified. When exdigits is -1, exponential notation will never be used. If 0 is specified for + * exdigits, exponential notation is always used unless the exponent would be 0. + *

    + * exform 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 (before + * ). Otherwise, only one digit (plus sign, if negative) is needed. + *

    + * Finally, the sixth argument, exround, 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 ROUND_ + * . The default (ROUND_HALF_UP) may also be selected by using the value -1, as before. + *

    + * The special value MathContext.ROUND_UNNECESSARY may be used to detect whether non-zero digits are + * discarded -- if exround has this value than if non-zero digits would be discarded (rounded) during + * formatting then an ArithmeticException is thrown. + * + * @param before The int specifying the number of places before the decimal point. Use -1 for 'as many as + * are needed'. + * @param after The int specifying the number of places after the decimal point. Use -1 for 'as many as + * are needed'. + * @param explaces The int specifying the number of places to be used for any exponent. Use -1 for 'as many + * as are needed'. + * @param exdigits The int 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 int specifying the form of exponential notation to be used ( + * {@link MathContext#SCIENTIFIC} or {@link MathContext#ENGINEERING}). + * @param exround The int specifying the rounding mode to use. Use -1 for the default, + * {@link MathContext#ROUND_HALF_UP}. + * @return A String representing this BigDecimal, 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 BigDecimal. This hashcode is suitable for use by the + * java.util.Hashtable class. + *

    + * Note that two BigDecimal objects are only guaranteed to produce the same hashcode if they are + * exactly equal (that is, the String representations of the BigDecimal numbers are + * identical -- they have the same characters in the same sequence). + * + * @return An int that is the hashcode for this. + * @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 BigDecimal to an int. If the BigDecimal has a non-zero + * decimal part it is discarded. If the BigDecimal is out of the possible range for an int + * (32-bit signed integer) result then only the low-order 32 bits are used. (That is, the number may be + * decapitated.) To avoid unexpected errors when these conditions occur, use the {@link #intValueExact} + * method. + * + * @return An int converted from this, truncated and decapitated if necessary. + * @stable ICU 2.0 + */ + + public int intValue() { + return toBigInteger().intValue(); + } + + /** + * Converts this BigDecimal to an int. If the BigDecimal has a non-zero + * decimal part or is out of the possible range for an int (32-bit signed integer) result then an + * ArithmeticException is thrown. + * + * @return An int equal in value to this. + * @throws ArithmeticException if this has a non-zero decimal part, or will not fit in an int. + * @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=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 BigDecimal to a long. If the BigDecimal has a non-zero + * decimal part it is discarded. If the BigDecimal is out of the possible range for a long + * (64-bit signed integer) result then only the low-order 64 bits are used. (That is, the number may be + * decapitated.) To avoid unexpected errors when these conditions occur, use the {@link #longValueExact} + * method. + * + * @return A long converted from this, truncated and decapitated if necessary. + * @stable ICU 2.0 + */ + + public long longValue() { + return toBigInteger().longValue(); + } + + /** + * Converts this BigDecimal to a long. If the BigDecimal has a non-zero + * decimal part or is out of the possible range for a long (64-bit signed integer) result then an + * ArithmeticException is thrown. + * + * @return A long equal in value to this. + * @throws ArithmeticException if this has a non-zero decimal part, or will not fit in a long. + * @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=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 BigDecimal whose decimal point has been moved to the left by a specified number of + * positions. The parameter, n, specifies the number of positions to move the decimal point. That is, + * if n is 0 or positive, the number returned is given by: + *

    + * this.multiply(TEN.pow(new BigDecimal(-n))) + *

    + * n may be negative, in which case the method returns the same result as movePointRight(-n) + * . + * + * @param n The int specifying the number of places to move the decimal point leftwards. + * @return A BigDecimal derived from this, with the decimal point moved n + * 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 BigDecimal whose decimal point has been moved to the right by a specified number of + * positions. The parameter, n, specifies the number of positions to move the decimal point. That is, + * if n is 0 or positive, the number returned is given by: + *

    + * this.multiply(TEN.pow(new BigDecimal(n))) + *

    + * n may be negative, in which case the method returns the same result as movePointLeft(-n) + * . + * + * @param n The int specifying the number of places to move the decimal point rightwards. + * @return A BigDecimal derived from this, with the decimal point moved n + * 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 BigDecimal. Returns a non-negative int 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 int whose value is the scale of this BigDecimal. + * @stable ICU 2.0 + */ + + public int scale() { + if (exp >= 0) + return 0; // scale can never be negative + return -exp; + } + + /** + * Returns a plain BigDecimal with a given scale. + *

    + * 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 BigDecimal then trailing zeros will be added to the decimal part as necessary. + *

    + * If the given scale is less than the length of the decimal part (the scale) of this BigDecimal then + * trailing digits will be removed, and in this case an ArithmeticException is thrown if any discarded + * digits are non-zero. + *

    + * The same as {@link #setScale(int, int)}, where the first parameter is the scale, and the second is + * MathContext.ROUND_UNNECESSARY. + * + * @param scale The int specifying the scale of the resulting BigDecimal. + * @return A plain BigDecimal with the given scale. + * @throws ArithmeticException if scale 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 BigDecimal with a given scale. + *

    + * 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 BigDecimal then trailing zeros will be added to the decimal part as necessary. + *

    + * If the given scale is less than the length of the decimal part (the scale) of this BigDecimal 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 IllegalArgumentException is thrown if + * round is not a valid rounding mode. + *

    + * If round is MathContext.ROUND_UNNECESSARY, an ArithmeticException is + * thrown if any discarded digits are non-zero. + * + * @param scale The int specifying the scale of the resulting BigDecimal. + * @param round The int rounding mode to be used for the division (see the {@link MathContext} class). + * @return A plain BigDecimal with the given scale. + * @throws IllegalArgumentException if round is not a valid rounding mode. + * @throws ArithmeticException if scale is negative. + * @throws ArithmeticException if round is MathContext.ROUND_UNNECESSARY, 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 BigDecimal to a short. If the BigDecimal has a non-zero + * decimal part or is out of the possible range for a short (16-bit signed integer) result then an + * ArithmeticException is thrown. + * + * @return A short equal in value to this. + * @throws ArithmeticException if this has a non-zero decimal part, or will not fit in a short. + * @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 BigDecimal, as an int. This returns the signum function + * value that represents the sign of this BigDecimal. That is, -1 if the BigDecimal is + * negative, 0 if it is numerically equal to zero, or 1 if it is positive. + * + * @return An int which is -1 if the BigDecimal 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 BigDecimal to a java.math.BigDecimal. + *

    + * This is an exact conversion; the result is the same as if the BigDecimal were formatted as a plain + * number without any rounding or exponent and then the java.math.BigDecimal(java.lang.String) + * constructor were used to construct the result. + *

    + * (Note: this method is provided only in the com.ibm.icu.math version of the BigDecimal class. It + * would not be present in a java.math version.) + * + * @return The java.math.BigDecimal equal in value to this BigDecimal. + * @stable ICU 2.0 + */ + + public java.math.BigDecimal toBigDecimal() { + return new java.math.BigDecimal(this.unscaledValue(), this.scale()); + } + + /** + * Converts this BigDecimal to a java.math.BigInteger. + *

    + * Any decimal part is truncated (discarded). If an exception is desired should the decimal part be non-zero, use + * {@link #toBigIntegerExact()}. + * + * @return The java.math.BigInteger equal in value to the integer part of this BigDecimal. + * @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 BigDecimal to a java.math.BigInteger. + *

    + * An exception is thrown if the decimal part (if any) is non-zero. + * + * @return The java.math.BigInteger equal in value to the integer part of this BigDecimal. + * @throws ArithmeticException if this 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 BigDecimal as a character array. The result of this method is the same as using the + * sequence toString().toCharArray(), but avoids creating the intermediate String and + * char[] objects. + * + * @return The char[] array corresponding to this BigDecimal. + * @stable ICU 2.0 + */ + + public char[] toCharArray() { + return layout(); + } + + /** + * Returns the BigDecimal as a String. This returns a String that exactly + * represents this BigDecimal, as defined in the decimal documentation (see {@link BigDecimal class + * header}). + *

    + * By definition, using the {@link #BigDecimal(String)} constructor on the result String will create a + * BigDecimal that is exactly equal to the original BigDecimal. + * + * @return The String exactly corresponding to this BigDecimal. + * @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 BigInteger 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 BigInteger. + * + * @return The java.math.BigInteger equal in value to this BigDecimal multiplied by ten to + * the power of this.scale(). + * @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 double to a BigDecimal. + *

    + * Returns a BigDecimal 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 NumberFormatException is + * thrown. + *

    + * The number is constructed as though num had been converted to a String using the + * Double.toString() method and the {@link #BigDecimal(java.lang.String)} constructor had then been used. + * This is typically not an exact conversion. + * + * @param dub The double to be translated. + * @return The BigDecimal equal in value to dub. + * @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 long to a BigDecimal. That is, returns a plain BigDecimal + * whose value is equal to the given long. + * + * @param lint The long to be translated. + * @return The BigDecimal equal in value to lint. + * @stable ICU 2.0 + */ + + public static com.ibm.icu.math.BigDecimal valueOf(long lint) { + return valueOf(lint, 0); + } + + /** + * Translates a long to a BigDecimal with a given scale. That is, returns a plain + * BigDecimal whose unscaled value is equal to the given long, adjusted by the second parameter, + * scale. + *

    + * The result is given by: + *

    + * (new BigDecimal(lint)).divide(TEN.pow(new BigDecimal(scale))) + *

    + * A NumberFormatException is thrown if scale is negative. + * + * @param lint The long to be translated. + * @param scale The int scale to be applied. + * @return The BigDecimal equal in value to lint. + * @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 */ + /* ---------------------------------------------------------------- */ + + /* + * Return char array value of a BigDecimal (conversion from BigDecimal to laid-out canonical char array). + *

    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).

    We must not alter the mantissa, here.

    '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. + */ + + 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; + } + + /* + * Checks a BigDecimal argument to ensure it's a true integer in a given range.

    If OK, returns it as an + * int. + */ + // [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; + } + + /* Carry out division operations. */ + /* + * 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); + } + + /* Report a conversion exception. */ + + private void bad(char s[]) { + throw new java.lang.NumberFormatException("Not a number:" + " " + java.lang.String.valueOf(s)); + } + + /* + * Report a bad argument to a method. 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); + } + + /* + * Extend byte array to given length, padding with 0s. If no extension is required then return the same + * array. + * + * 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; + } + + /* + * Add or subtract two >=0 integers in byte arrays

    This routine performs the calculation:

     C=A+(BM)
    +     * 
    Where M is in the range -9 through +9

    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; + } + + /* + * Initializer for digit array properties (lookaside). 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; + } + + /* + * Create a copy of BigDecimal object for local use.

    This does NOT make a copy of the mantissa array. + * 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; + } + + /* + * Check one or two numbers for lost digits. 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()); + } + + /* + * Round to specified digits, if necessary. 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); + } + + /* + * 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. + */ + + 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; + } + + /* + * 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 + */ + + 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; + } + + /* + * Carry out final checks and canonicalization

    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. 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 new file mode 100644 index 00000000000..f7d2032c7c0 --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/math/MathContext.java @@ -0,0 +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 MathContext 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. + *

    + * The settings, which are not base-dependent, comprise: + *

      + *
    1. digits: + * the number of digits (precision) to be used for an operation + *
    2. form: + * the form of any exponent that results from the operation + *
    3. lostDigits: + * whether checking for lost digits is enabled + *
    4. roundingMode: + * the algorithm to be used for rounding. + *
    + *

    + * When provided, a MathContext object supplies the + * settings for an operation directly. + *

    + * When MathContext.DEFAULT is provided for a + * MathContext parameter then the default settings are used + * (9, SCIENTIFIC, false, ROUND_HALF_UP). + *

    + * In the BigDecimal class, all methods which accept a + * MathContext 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 (0, PLAIN, false, ROUND_HALF_UP). + *

    + * The instance variables are shared with default access (so they are + * directly accessible to the BigDecimal class), but must + * never be changed. + *

    + * The rounding mode constants have the same names and values as the + * constants of the same name in java.math.BigDecimal, to + * maintain compatibility with earlier versions of + * BigDecimal. + * + * @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 + * BigDecimal 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 + * BigDecimal 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 + * BigDecimal 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 + * BigDecimal operation. + *

    + * 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 + * BigDecimal operation. + *

    + * 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 + * BigDecimal operation. + *

    + * 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 + * BigDecimal operation. + *

    + * 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 + * BigDecimal operation. + *

    + * 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. + *

    + * 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 + * BigDecimal operation. + *

    + * 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 + * BigDecimal operation. + *

    + * Rounding (potential loss of information) is not permitted. + * If any of the discarded digits are non-zero then an + * ArithmeticException 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 + * BigDecimal operation. + *

    + * 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. + *

    + * 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. + *

    + * digits will always be non-negative. + * + * @serial + */ + int digits; + + /** + * The form of results from an operation. + *

    + * 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 true to enable checking, or + * to false to disable checking. + *

    + * When enabled, the {@link BigDecimal} operator methods check + * the precision of their operand or operands, and throw an + * ArithmeticException 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. + *

    + * 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 ROUND_. + * + * @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 MathContext object initialized to the default + * settings for general-purpose arithmetic. That is, + * digits=9 form=SCIENTIFIC lostDigits=false + * roundingMode=ROUND_HALF_UP. + * + * @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 MathContext with a specified + * precision. + * The other settings are set to the default values + * (see {@link #DEFAULT}). + * + * An IllegalArgumentException is thrown if the + * setdigits parameter is out of range + * (<0 or >999999999). + * + * @param setdigits The int digits setting + * for this MathContext. + * @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 MathContext with a specified + * precision and form. + * The other settings are set to the default values + * (see {@link #DEFAULT}). + * + * An IllegalArgumentException is thrown if the + * setdigits parameter is out of range + * (<0 or >999999999), or if the value given for the + * setform parameter is not one of the appropriate + * constants. + * + * @param setdigits The int digits setting + * for this MathContext. + * @param setform The int form setting + * for this MathContext. + * @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 MathContext with a specified + * precision, form, and lostDigits setting. + * The roundingMode setting is set to its default value + * (see {@link #DEFAULT}). + * + * An IllegalArgumentException is thrown if the + * setdigits parameter is out of range + * (<0 or >999999999), or if the value given for the + * setform parameter is not one of the appropriate + * constants. + * + * @param setdigits The int digits setting + * for this MathContext. + * @param setform The int form setting + * for this MathContext. + * @param setlostdigits The boolean lostDigits + * setting for this MathContext. + * @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 MathContext with a specified + * precision, form, lostDigits, and roundingMode setting. + * + * An IllegalArgumentException is thrown if the + * setdigits parameter is out of range + * (<0 or >999999999), or if the value given for the + * setform or setroundingmode parameters is + * not one of the appropriate constants. + * + * @param setdigits The int digits setting + * for this MathContext. + * @param setform The int form setting + * for this MathContext. + * @param setlostdigits The boolean lostDigits + * setting for this MathContext. + * @param setroundingmode The int roundingMode setting + * for this MathContext. + * @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 (setdigitsMAX_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 int 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 int 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 true (enabled) or + * false (disabled). + * + * @return a boolean 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 int which is the value of the roundingMode + * setting + * @stable ICU 2.0 + */ + + public int getRoundingMode(){ + return roundingMode; + } + + /** Returns the MathContext as a readable string. + * The String returned represents the settings of the + * MathContext object as four blank-delimited words + * separated by a single blank and with no leading or trailing blanks, + * as follows: + *

      + *
    1. + * digits=, immediately followed by + * the value of the digits setting as a numeric word. + *
    2. + * form=, immediately followed by + * the value of the form setting as an uppercase word + * (one of SCIENTIFIC, PLAIN, or + * ENGINEERING). + *
    3. + * lostDigits=, immediately followed by + * the value of the lostDigits setting + * (1 if enabled, 0 if disabled). + *
    4. + * roundingMode=, 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. + *
    + *

    + * For example: + *
    + * digits=9 form=SCIENTIFIC lostDigits=0 roundingMode=ROUND_HALF_UP + * + *

    + * Additional words may be appended to the result of + * toString in the future if more properties are added + * to the class. + * + * @return a String 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; + } + + + /* Test whether round is valid. */ + // 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 new file mode 100644 index 00000000000..cb72af42683 --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/Bidi.java @@ -0,0 +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; + +/** + * + *

    Bidi algorithm for ICU

    + * + * This is an implementation of the Unicode Bidirectional algorithm. The + * algorithm is defined in the Unicode Standard Annex #9, + * version 13, also described in The Unicode Standard, Version 4.0 . + *

    + * + * 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". + * + *

    General remarks about the API:

    + * + * The "limit" of a sequence of characters is the position just after + * their last character, i.e., one more than that position. + *

    + * + * Some of the API methods provide access to "runs". Such a + * "run" is defined as a sequence of characters that are at the same + * embedding level after performing the Bidi algorithm. + *

    + * + *

    Basic concept: paragraph

    + * A piece of text can be divided into several paragraphs by characters + * with the Bidi class Block Separator. For handling of + * paragraphs, see: + *
      + *
    • {@link #countParagraphs} + *
    • {@link #getParaLevel} + *
    • {@link #getParagraph} + *
    • {@link #getParagraphByIndex} + *
    + * + *

    Basic concept: text direction

    + * The direction of a piece of text may be: + *
      + *
    • {@link #LTR} + *
    • {@link #RTL} + *
    • {@link #MIXED} + *
    + * + *

    Basic concept: levels

    + * + * Levels in this API represent embedding levels according to the Unicode + * Bidirectional Algorithm. + * Their low-order bit (even/odd value) indicates the visual direction.

    + * + * Levels can be abstract values when used for the + * paraLevel and embeddingLevels + * arguments of setPara(); there: + *

      + *
    • the high-order bit of an embeddingLevels[] + * value indicates whether the using application is + * specifying the level of a character to override whatever the + * Bidi implementation would resolve it to.
    • + *
    • paraLevel can be set to the + * pseudo-level values LEVEL_DEFAULT_LTR + * and LEVEL_DEFAULT_RTL.
    • + *
    + * + *

    The related constants are not real, valid level values. + * DEFAULT_XXX can be used to specify + * a default for the paragraph level for + * when the setPara() method + * shall determine it but there is no + * strongly typed character in the input.

    + * + * Note that the value for LEVEL_DEFAULT_LTR is even + * and the one for LEVEL_DEFAULT_RTL 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. + * + *

      See Also: + *
    • {@link #LEVEL_DEFAULT_LTR} + *
    • {@link #LEVEL_DEFAULT_RTL} + *
    • {@link #LEVEL_OVERRIDE} + *
    • {@link #MAX_EXPLICIT_LEVEL} + *
    • {@link #setPara} + *
    + * + *

    Basic concept: Reordering Mode

    + * Reordering mode values indicate which variant of the Bidi algorithm to + * use. + * + *
      See Also: + *
    • {@link #setReorderingMode} + *
    • {@link #REORDER_DEFAULT} + *
    • {@link #REORDER_NUMBERS_SPECIAL} + *
    • {@link #REORDER_GROUP_NUMBERS_WITH_R} + *
    • {@link #REORDER_RUNS_ONLY} + *
    • {@link #REORDER_INVERSE_NUMBERS_AS_L} + *
    • {@link #REORDER_INVERSE_LIKE_DIRECT} + *
    • {@link #REORDER_INVERSE_FOR_NUMBERS_SPECIAL} + *
    + * + *

    Basic concept: Reordering Options

    + * Reordering options can be applied during Bidi text transformations. + *
      See Also: + *
    • {@link #setReorderingOptions} + *
    • {@link #OPTION_DEFAULT} + *
    • {@link #OPTION_INSERT_MARKS} + *
    • {@link #OPTION_REMOVE_CONTROLS} + *
    • {@link #OPTION_STREAMING} + *
    + * + * + * @author Simon Montagu, Matitiahu Allouche (ported from C code written by Markus W. Scherer) + * @stable ICU 3.8 + * + * + *

    Sample code for the ICU Bidi API

    + * + *
    Rendering a paragraph with the ICU Bidi API
    + * + * 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. + * + *

    + * The basic assumptions are: + *

    + *
      + *
    • Rendering is done from left to right on a horizontal line.
    • + *
    • A run of single-style, unidirectional text can be rendered at once. + *
    • + *
    • Such a run of text is passed to the graphics system with characters + * (code units) in logical order.
    • + *
    • The line-breaking algorithm is very complicated and Locale-dependent - + * and therefore its implementation omitted from this sample code.
    • + *
    + * + *
    + *
    + *  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);
    + *      }
    + *  }
    + *
    + * 
    + */ + +public class Bidi { + + private java.text.Bidi bidi; + + private Bidi(java.text.Bidi delegate) { + this.bidi = delegate; + } + + /** Paragraph level setting

    + * + * 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).

    + * + * If this value is used in conjunction with reordering modes + * REORDER_INVERSE_LIKE_DIRECT or + * REORDER_INVERSE_FOR_NUMBERS_SPECIAL, 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.

    + * + * If reordering option OPTION_INSERT_MARKS 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

    + * + * 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).

    + * + * If this value is used in conjunction with reordering modes + * REORDER_INVERSE_LIKE_DIRECT or + * REORDER_INVERSE_FOR_NUMBERS_SPECIAL, 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.

    + * + * If reordering option OPTION_INSERT_MARKS 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 MAX_EXPLICIT_LEVEL+1). + * @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 + * OPTION_REMOVE_CONTROLS is + * specified. This can also happen for the visual-to-logical mapping of a + * Bidi mark (LRM or RLM) inserted by option + * OPTION_INSERT_MARKS. + * @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 + * + *

    This option does not imply corresponding adjustment of the index + * mappings.

    + * + * @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) + * + *

    This option does not imply corresponding adjustment of the index + * mappings.

    + * + * @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 + * + *

    This has the same effect as calling writeReordered() + * first without this option, and then calling + * writeReverse() 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.

    + * + * @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.
    + * If this mode is set together with option + * OPTION_INSERT_MARKS, 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 setInverse(true). + * @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 + * REORDER_NUMBERS_SPECIAL Bidi algorithm. + * @see #setReorderingMode + * @stable ICU 3.8 + */ + public static final short REORDER_INVERSE_FOR_NUMBERS_SPECIAL = 6; + + /** + * Option value for setReorderingOptions: + * 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 setReorderingOptions: + * insert Bidi marks (LRM or RLM) when needed to ensure correct result of + * a reordering to a Logical order + * + *

    This option must be set or reset before calling + * setPara.

    + * + *

    This option is significant only with reordering modes which generate + * a result with Logical order, specifically.

    + *
      + *
    • REORDER_RUNS_ONLY
    • + *
    • REORDER_INVERSE_NUMBERS_AS_L
    • + *
    • REORDER_INVERSE_LIKE_DIRECT
    • + *
    • REORDER_INVERSE_FOR_NUMBERS_SPECIAL
    • + *
    + * + *

    If this option is set in conjunction with reordering mode + * REORDER_INVERSE_NUMBERS_AS_L or with calling + * setInverse(true), it implies option + * INSERT_LRM_FOR_NUMERIC in calls to method + * writeReordered().

    + * + *

    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 OPTION_REMOVE_CONTROLS set before calling + * setPara() or option + * REMOVE_BIDI_CONTROLS in + * writeReordered), the result will be identical to the + * source text in the first transformation. + * + *

    This option will be ignored if specified together with option + * OPTION_REMOVE_CONTROLS. It inhibits option + * REMOVE_BIDI_CONTROLS in calls to method + * writeReordered() and it implies option + * INSERT_LRM_FOR_NUMERIC in calls to method + * writeReordered() if the reordering mode is + * REORDER_INVERSE_NUMBERS_AS_L.

    + * + * @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 setReorderingOptions: + * remove Bidi control characters + * + *

    This option must be set or reset before calling + * setPara.

    + * + *

    This option nullifies option + * OPTION_INSERT_MARKS. It inhibits option + * INSERT_LRM_FOR_NUMERIC in calls to method + * writeReordered() and it implies option + * REMOVE_BIDI_CONTROLS in calls to that method.

    + * + * @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 setReorderingOptions: + * process the output as part of a stream to be continued + * + *

    This option must be set or reset before calling + * setPara.

    + * + *

    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.

    + * + *

    When this option bit is on, setPara() may process + * less than the full source text in order to truncate the text at a + * meaningful boundary. The caller should call + * getProcessedLength() immediately after calling + * setPara() 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 setPara. 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.
    + * If the last character of the source text constitutes a reasonable + * boundary, the whole text will be processed at once.
    + * If nowhere in the source text there exists + * such a reasonable boundary, the processed length will be zero.
    + * The caller should check for such an occurrence and do one of the following: + *

    • submit a larger amount of text with a better chance to include + * a reasonable boundary.
    • + *
    • resubmit the same text after turning off option + * OPTION_STREAMING.
    + * In all cases, this option should be turned off before processing the last + * part of the text.

    + * + *

    When the OPTION_STREAMING option is used, it is + * recommended to call orderParagraphsLTR(true) before calling + * setPara() so that later paragraphs may be concatenated to + * previous paragraphs on the right. + *

    + * + * @see #setReorderingMode + * @see #setReorderingOptions + * @see #getProcessedLength + * @stable ICU 3.8 + */ + public static final int OPTION_STREAMING = 4; + + /** + * Value returned by BidiClassifier 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 Bidi object. + * Such an object is initially empty. It is assigned + * the Bidi properties of a piece of text containing one or more paragraphs + * by setPara() + * or the Bidi properties of a line within a paragraph by + * setLine().

    + * This object can be reused.

    + * setPara() and setLine() 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 Bidi object with preallocated memory + * for internal structures. + * This method provides a Bidi object like the default constructor + * but it also preallocates memory for internal structures + * according to the sizings supplied by the caller.

    + * The preallocation can be limited to some of the internal memory + * by setting some values to 0 here. That means that if, e.g., + * maxRunCount cannot be reasonably predetermined and should not + * be set to maxLength (the only failproof value) to avoid + * wasting memory, then maxRunCount 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.

    + * The number of runs depends on the actual text and maybe anywhere between + * 1 and maxLength. 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 setPara(). + * + *

    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".

    + * + *

    With isInversed set to true, + * 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.

    + * + *

    Output runs should be retrieved using getVisualRun(). + * Since the actual input for "inverse Bidi" is visually ordered text and + * getVisualRun() gets the reordered runs, these are actually + * the runs of the logically ordered output.

    + * + *

    Calling this method with argument isInverse set to + * true is equivalent to calling setReorderingMode + * with argument reorderingMode + * set to REORDER_INVERSE_NUMBERS_AS_L.
    + * Calling this method with argument isInverse set to + * false is equivalent to calling setReorderingMode + * with argument reorderingMode + * set to REORDER_DEFAULT. + * + * @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 Bidi object set to perform the inverse Bidi + * algorithm? + *

    Note: calling this method after setting the reordering mode with + * setReorderingMode will return true if the + * reordering mode was set to + * REORDER_INVERSE_NUMBERS_AS_L, false + * for all other values.

    + * + * @return true if the Bidi 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 setPara(), and stays in + * effect until called again with a different argument. + * + *

    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.

    + * + *

    With the reordering mode set to a value other than + * REORDER_DEFAULT, 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.

    + * + *

    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.

    + * + *

    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.

    + * + *
      + *
    • When the Reordering Mode is set to + * REORDER_DEFAULT, + * the standard Bidi Logical to Visual algorithm is applied.
    • + * + *
    • When the reordering mode is set to + * REORDER_NUMBERS_SPECIAL, + * the algorithm used to perform Bidi transformations when calling + * setPara should approximate the algorithm used in Microsoft + * Windows XP rather than strictly conform to the Unicode Bidi algorithm. + *
      + * The differences between the basic algorithm and the algorithm addressed + * by this option are as follows: + *
        + *
      • 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.
      • + * + *
      • Arabic-Indic numbers (AN) are handled by the Windows algorithm just + * like regular numbers (EN).
      • + *
    • + * + *
    • When the reordering mode is set to + * REORDER_GROUP_NUMBERS_WITH_R, + * 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.
      + * The source text should not contain Bidi control characters other than LRM + * or RLM.
    • + * + *
    • When the reordering mode is set to + * REORDER_RUNS_ONLY, + * a "Logical to Logical" transformation must be performed: + *
        + *
      • If the default text level of the source text (argument + * paraLevel in setPara) 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.
      • + *
      • 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.
      • + *
      + * 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). + *
      + * 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. + *
      + * 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. + *
      + * The source text should not contain Bidi control characters other than LRM + * or RLM.
    • + * + *
    • When the reordering mode is set to + * REORDER_INVERSE_NUMBERS_AS_L, 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 INSERT_LRM_FOR_NUMERIC can + * be used with method writeReordered to this end. This mode + * is equivalent to calling setInverse() with + * argument isInverse set to true.
    • + * + *
    • When the reordering mode is set to + * REORDER_INVERSE_LIKE_DIRECT, the "direct" Logical to + * Visual Bidi algorithm is used as an approximation of an "inverse Bidi" + * algorithm. This mode is similar to mode + * REORDER_INVERSE_NUMBERS_AS_L but is closer to the + * regular Bidi algorithm. + *
      + * 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 REORDER_INVERSE_NUMBERS_AS_L.
      + * When used in conjunction with option + * OPTION_INSERT_MARKS, this mode generally + * adds Bidi marks to the output significantly more sparingly than mode + * REORDER_INVERSE_NUMBERS_AS_L.
      with option + * INSERT_LRM_FOR_NUMERIC in calls to + * writeReordered.
    • + * + *
    • When the reordering mode is set to + * REORDER_INVERSE_FOR_NUMBERS_SPECIAL, the Logical to Visual + * Bidi algorithm used in Windows XP is used as an approximation of an "inverse + * Bidi" algorithm. + *
      + * For example, an LTR paragraph with the content "abc FED123" (where + * upper case represents RTL characters) will be transformed to + * "abc 123DEF.
    • + *
    + * + *

    In all the reordering modes specifying an "inverse Bidi" algorithm + * (i.e. those with a name starting with REORDER_INVERSE), + * output runs should be retrieved using getVisualRun(), and + * the output text with writeReordered(). The caller should + * keep in mind that in "inverse Bidi" modes the input is actually visually + * ordered text and reordered output returned by getVisualRun() + * or writeReordered() are actually runs or character string + * of logically ordered output.
    + * For all the "inverse Bidi" modes, the source text should not contain + * Bidi control characters other than LRM or RLM.

    + * + *

    Note that option OUTPUT_REVERSE of + * writeReordered has no useful meaning and should not be used + * in conjunction with any value of the reordering mode specifying "inverse + * Bidi" or with value REORDER_RUNS_ONLY. + * + * @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: + * OPTION_DEFAULT, OPTION_INSERT_MARKS, + * OPTION_REMOVE_CONTROLS, OPTION_STREAMING. + * + * @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 + * Unicode Standard Annex #9, + * version 13, + * also described in The Unicode Standard, Version 4.0 .

    + * + * This method takes a piece of plain text containing one or more paragraphs, + * with or without externally specified embedding levels from styled + * text and computes the left-right-directionality of each character.

    + * + * 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.
    + * 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.

    + * + * 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 String, 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 getText() or + * getTextAsString.
    + * + * @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 paraLevel can be set to + * either LEVEL_DEFAULT_LTR + * or LEVEL_DEFAULT_RTL; 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 MAX_EXPLICIT_LEVEL + * 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 + * LEVEL_OVERRIDE bit set.

    + * Except for that bit, it must be + * paraLevel<=embeddingLevels[]<=MAX_EXPLICIT_LEVEL, + * with one exception: a level of zero may be specified for a + * paragraph separator even if paraLevel>0 when multiple + * paragraphs are submitted in the same call to setPara().

    + * Caution: A reference to this array, not a copy + * of the levels, will be stored in the Bidi object; + * the embeddingLevels + * should not be modified to avoid unexpected results on subsequent + * Bidi operations. However, the setPara() and + * setLine() methods may modify some or all of the + * levels.

    + * Note: the embeddingLevels array must + * have one entry for each character in text. + * + * @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 + * Unicode Standard Annex #9, + * version 13, + * also described in The Unicode Standard, Version 4.0 .

    + * + * This method takes a piece of plain text containing one or more paragraphs, + * with or without externally specified embedding levels from styled + * text and computes the left-right-directionality of each character.

    + * + * 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.
    + * 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.

    + * + * 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 getText() or + * getTextAsString.
    + * + * @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 paraLevel can be set to + * either LEVEL_DEFAULT_LTR + * or LEVEL_DEFAULT_RTL; 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 MAX_EXPLICIT_LEVEL + * 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 + * LEVEL_OVERRIDE bit set.

    + * Except for that bit, it must be + * paraLevel<=embeddingLevels[]<=MAX_EXPLICIT_LEVEL, + * with one exception: a level of zero may be specified for a + * paragraph separator even if paraLevel>0 when multiple + * paragraphs are submitted in the same call to setPara().

    + * Caution: A reference to this array, not a copy + * of the levels, will be stored in the Bidi object; + * the embeddingLevels + * should not be modified to avoid unexpected results on subsequent + * Bidi operations. However, the setPara() and + * setLine() methods may modify some or all of the + * levels.

    + * Note: the embeddingLevels array must + * have one entry for each character in text. + * + * @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 + * Unicode Standard Annex #9, + * version 13, + * also described in The Unicode Standard, Version 4.0 .

    + * + * 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.

    + * + * 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.

    + * + * 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.

    + * + * 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.
    + * 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.

    + * + * @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 setPara(). + * 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 Bidi object set to allocate level 0 to block + * separators so that successive paragraphs progress from left to right? + * + * @return true if the Bidi 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 LTR, RTL or MIXED + * 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 setPara or setLine + * + * @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 String containing the text that the + * Bidi object was created for. + * + * @throws IllegalStateException if this call is not preceded by a successful + * call to setPara or setLine + * + * @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 char array containing the text that the + * Bidi object was created for. + * + * @throws IllegalStateException if this call is not preceded by a successful + * call to setPara or setLine + * + * @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 Bidi object was + * created for. + * + * @throws IllegalStateException if this call is not preceded by a successful + * call to setPara or setLine + * @stable ICU 3.8 + */ + public int getLength() + { + return bidi.getLength(); + } + + /** + * Get the length of the source text processed by the last call to + * setPara(). This length may be different from the length of + * the source text if option OPTION_STREAMING has been + * set. + *
    + * 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 setPara (which receives unprocessed source text) + * and getLength (which returns the original length of the + * source text).
    + * In particular, the processed length is the one to consider in the + * following cases: + *

      + *
    • maximum value of the limit argument of + * setLine
    • + *
    • maximum value of the charIndex argument of + * getParagraph
    • + *
    • maximum value of the charIndex argument of + * getLevelAt
    • + *
    • number of elements in the array returned by getLevels + *
    • + *
    • maximum value of the logicalStart argument of + * getLogicalRun
    • + *
    • maximum value of the logicalIndex argument of + * getVisualIndex
    • + *
    • number of elements returned by getLogicalMap
    • + *
    • length of text processed by writeReordered
    • + *
    + * + * @return The length of the part of the source text processed by + * the last call to setPara. + * + * @throws IllegalStateException if this call is not preceded by a successful + * call to setPara or setLine + * + * @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 + * setPara(). This length may be different from the length + * of the source text if option OPTION_INSERT_MARKS + * or option OPTION_REMOVE_CONTROLS has been set. + *
    + * This resulting length is the one to consider in the following cases: + *
      + *
    • maximum value of the visualIndex argument of + * getLogicalIndex
    • + *
    • number of elements returned by getVisualMap
    • + *
    + * Note that this length stays identical to the source text length if + * Bidi marks are inserted or removed using option bits of + * writeReordered, or if option + * REORDER_INVERSE_NUMBERS_AS_L has been set. + * + * @return The length of the reordered text resulting from + * the last call to setPara. + * + * @throws IllegalStateException if this call is not preceded by a successful + * call to setPara or setLine + * + * @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 setPara or setLine + * + * @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 setPara or setLine + * @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.

    + * + * @param paraIndex is the number of the paragraph, in the + * range [0..countParagraphs()-1]. + * + * @return a BidiRun object with the details of the paragraph:
    + * start will receive the index of the first character + * of the paragraph in the text.
    + * limit will receive the limit of the paragraph.
    + * embeddingLevel will receive the level of the paragraph. + * + * @throws IllegalStateException if this call is not preceded by a successful + * call to setPara or setLine + * @throws IllegalArgumentException if paraIndex is not in the range + * [0..countParagraphs()-1] + * + * @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.
    + * Note: if the paragraph index is known, it is more efficient to + * retrieve the paragraph information using getParagraphByIndex().

    + * + * @param charIndex is the index of a character within the text, in the + * range [0..getProcessedLength()-1]. + * + * @return a BidiRun object with the details of the paragraph:
    + * start will receive the index of the first character + * of the paragraph in the text.
    + * limit will receive the limit of the paragraph.
    + * embeddingLevel will receive the level of the paragraph. + * + * @throws IllegalStateException if this call is not preceded by a successful + * call to setPara or setLine + * @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.

    + * + * @param charIndex is the index of a character within the text, in the + * range [0..getProcessedLength()-1]. + * + * @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 setPara or setLine + * @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 BidiClassifier + * + * @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. + *

    If a BidiClassifier is defined and returns a value + * other than CLASS_DEFAULT, that value is used; otherwise + * the default class determination mechanism is invoked.

    + * + * @param c The code point to get a Bidi class for. + * + * @return The Bidi class for the character c that is in effect + * for this Bidi instance. + * + * @see BidiClassifier + * @stable ICU 3.8 + */ + public int getCustomizedClass(int c) { + throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base"); + } + + /** + * setLine() returns a Bidi 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 Bidi object representing + * this information for a piece of text containing one or more paragraphs, + * and by specifying a range of indexes in this text.

    + * In the new line object, the indexes will range from 0 to limit-start-1.

    + * + * This is used after calling setPara() + * 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.

    + * + * After line-breaking, rules (L1) and (L2) for the treatment of + * trailing WS and for reordering are performed on + * a Bidi object that represents a line.

    + * + * Important: the line Bidi object may + * reference data within the global text Bidi 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 Bidi object that will now represent a line of the text. + * + * @throws IllegalStateException if this call is not preceded by a successful + * call to setPara + * @throws IllegalArgumentException if start and limit are not in the range + * 0<=start<limit<=getProcessedLength(), + * 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 charIndex. + * + * @throws IllegalStateException if this call is not preceded by a successful + * call to setPara or setLine + * @throws IllegalArgumentException if charIndex is not in the range + * 0<=charIndex<getProcessedLength() + * + * @see #getProcessedLength + * @stable ICU 3.8 + */ + public byte getLevelAt(int charIndex) + { + return (byte)bidi.getLevelAt(charIndex); + } + + /** + * Get an array of levels for each character.

    + * + * Note that this method may allocate memory under some + * circumstances, unlike getLevelAt(). + * + * @return The levels array for the text, + * or null if an error occurs. + * + * @throws IllegalStateException if this call is not preceded by a successful + * call to setPara or setLine + * @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.

    + * 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 start containing + * the first character of the run, limit containing + * the limit of the run, and embeddingLevel containing + * the level of the run. + * + * @throws IllegalStateException if this call is not preceded by a successful + * call to setPara or setLine + * @throws IllegalArgumentException if logicalPosition is not in the range + * 0<=logicalPosition<getProcessedLength() + * + * @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 + * Bidi object, after setPara() + * may have resolved only the levels of the text. Therefore, + * countRuns() 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 setPara or setLine + * @stable ICU 3.8 + */ + public int countRuns() + { + throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base"); + } + + /** + * + * Get a BidiRun 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.

    + * countRuns() is normally called + * before the runs are retrieved. + * + *

    + * Example: + *

    +     *  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 < 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 > 0);
    +     *      } else {
    +     *          logicalStart += length;  // logicalLimit
    +     *          do { // RTL
    +     *              show_char(text.charAt(--logicalStart), visualIndex++);
    +     *          } while (--length > 0);
    +     *      }
    +     *  }
    +     * 
    + *

    + * 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. + *

    + * Use of {@link #writeReordered}, optionally with the + * {@link #KEEP_BASE_COMBINING} option, can be considered in + * order to avoid these issues. + * + * @param runIndex is the number of the run in visual order, in the + * range [0..countRuns()-1]. + * + * @return a BidiRun object containing the details of the run. The + * directionality of the run is + * LTR==0 or RTL==1, + * never MIXED. + * + * @throws IllegalStateException if this call is not preceded by a successful + * call to setPara or setLine + * @throws IllegalArgumentException if runIndex is not in + * the range 0<=runIndex<countRuns() + * + * @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 + * Bidi object, then calling + * getLogicalMap() is more efficient. + *

    + * The value returned may be MAP_NOWHERE if there is no + * visual position because the corresponding text character is a Bidi + * control removed from output by the option + * OPTION_REMOVE_CONTROLS. + *

    + * When the visual output is altered by using options of + * writeReordered() such as INSERT_LRM_FOR_NUMERIC, + * KEEP_BASE_COMBINING, OUTPUT_REVERSE, + * REMOVE_BIDI_CONTROLS, 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}. + *

    + * 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 {@link #writeReordered}, optionally with the + * {@link #KEEP_BASE_COMBINING} 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 setPara or setLine + * @throws IllegalArgumentException if logicalIndex is not in + * the range 0<=logicalIndex<getProcessedLength() + * + * @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 + * Bidi object, then calling + * getVisualMap() is more efficient. + *

    + * The value returned may be MAP_NOWHERE if there is no + * logical position because the corresponding text character is a Bidi + * mark inserted in the output by option + * OPTION_INSERT_MARKS. + *

    + * This is the inverse method to getVisualIndex(). + *

    + * When the visual output is altered by using options of + * writeReordered() such as INSERT_LRM_FOR_NUMERIC, + * KEEP_BASE_COMBINING, OUTPUT_REVERSE, + * REMOVE_BIDI_CONTROLS, 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 setPara or setLine + * @throws IllegalArgumentException if visualIndex is not in + * the range 0<=visualIndex<getResultLength() + * + * @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 + * Bidi (paragraph or line) object. + *

    + * Some values in the map may be MAP_NOWHERE if the + * corresponding text characters are Bidi controls removed from the visual + * output by the option OPTION_REMOVE_CONTROLS. + *

    + * When the visual output is altered by using options of + * writeReordered() such as INSERT_LRM_FOR_NUMERIC, + * KEEP_BASE_COMBINING, OUTPUT_REVERSE, + * REMOVE_BIDI_CONTROLS, 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}. + *

    + * 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 {@link #writeReordered}, optionally with the + * {@link #KEEP_BASE_COMBINING} option can be considered instead + * of using the mapping, in order to avoid these issues. + * + * @return an array of getProcessedLength() + * indexes which will reflect the reordering of the characters.

    + * The index map will result in + * indexMap[logicalIndex]==visualIndex, where + * indexMap represents the returned array. + * + * @throws IllegalStateException if this call is not preceded by a successful + * call to setPara or setLine + * + * @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 + * Bidi (paragraph or line) object. + *

    + * Some values in the map may be MAP_NOWHERE if the + * corresponding text characters are Bidi marks inserted in the visual + * output by the option OPTION_INSERT_MARKS. + *

    + * When the visual output is altered by using options of + * writeReordered() such as INSERT_LRM_FOR_NUMERIC, + * KEEP_BASE_COMBINING, OUTPUT_REVERSE, + * REMOVE_BIDI_CONTROLS, 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 getResultLength() + * indexes which will reflect the reordering of the characters.

    + * The index map will result in + * indexMap[visualIndex]==logicalIndex, where + * indexMap represents the returned array. + * + * @throws IllegalStateException if this call is not preceded by a successful + * call to setPara or setLine + * + * @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 Bidi 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 getLogicalMap() on a + * Bidi object. + * + * @param levels is an array of levels that have been determined by + * the application. + * + * @return an array of levels.length + * indexes which will reflect the reordering of the characters.

    + * The index map will result in + * indexMap[logicalIndex]==visualIndex, where + * indexMap 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 Bidi 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 getVisualMap() on a + * Bidi object. + * + * @param levels is an array of levels that have been determined by + * the application. + * + * @return an array of levels.length + * indexes which will reflect the reordering of the characters.

    + * The index map will result in + * indexMap[visualIndex]==logicalIndex, where + * indexMap 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 MAP_NOWHERE. + * All elements must be >=0 or equal to MAP_NOWHERE. + * 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 MAP_NOWHERE). + * + * @return an array representing the inverse map. + * This array has a number of elements equal to 1 + the highest + * value in srcMap. + * 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 MAP_NOWHERE. + * If element with index i in srcMap has a value k different + * from MAP_NOWHERE, 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 MAP_NOWHERE. + * + * @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.

    + * + * 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.

    + * + * 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.

    + * + * 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.

    + * + * 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.

    + * + * 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 setPara + * @throws IllegalArgumentException if lineStart and lineLimit are not in the range + * 0<=lineStart<lineLimit<=getProcessedLength(), + * 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 setPara + * @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 setPara + * @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 setPara + * @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 setPara or setLine + * + * @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 setPara or setLine + * + * @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 setPara or setLine + * + * @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 countRuns()-1 + * + * @return the level of the run + * + * @throws IllegalStateException if this call is not preceded by a successful + * call to setPara or setLine + * @throws IllegalArgumentException if run is not in + * the range 0<=run<countRuns() + * @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 countRuns() + * + * @return the start of the run + * + * @throws IllegalStateException if this call is not preceded by a successful + * call to setPara or setLine + * @throws IllegalArgumentException if run is not in + * the range 0<=run<countRuns() + * @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 countRuns() + * + * @return the limit of the run + * + * @throws IllegalStateException if this call is not preceded by a successful + * call to setPara or setLine + * @throws IllegalArgumentException if run is not in + * the range 0<=run<countRuns() + * @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 index from + * objectStart up to objectStart + count 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 index - objectStart + levelStart). + * + * @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 Bidi object containing the reordering + * information for a piece of text (one or more paragraphs) set by + * setPara() or for a line of text set by setLine() + * and return a string containing the reordered text. + * + *

    The text may have been aliased (only a reference was stored + * without copying the contents), thus it must not have been modified + * since the setPara() call.

    + * + * 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 + * options 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: + * DO_MIRRORING, + * INSERT_LRM_FOR_NUMERIC, + * KEEP_BASE_COMBINING, + * OUTPUT_REVERSE, + * REMOVE_BIDI_CONTROLS, + * STREAMING + * + * @return The reordered text. + * If the INSERT_LRM_FOR_NUMERIC option is set, then + * the length of the returned string could be as large as + * getLength()+2*countRuns().
    + * If the REMOVE_BIDI_CONTROLS option is set, then the + * length of the returned string may be less than + * getLength().
    + * If none of these options is set, then the length of the returned + * string will be exactly getProcessedLength(). + * + * @throws IllegalStateException if this call is not preceded by a successful + * call to setPara or setLine + * + * @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 writeReordered(). For detailed descriptions + * of the parameters, see there. + * Since no Bidi controls are inserted here, the output string length + * will never exceed src.length(). + * + * @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 options parameter in writeReordered(). + * + * @return The reordered text. + * If the REMOVE_BIDI_CONTROLS option + * is set, then the length of the returned string may be less than + * src.length(). If this option is not set, + * then the length of the returned string will be exactly + * src.length(). + * + * @throws IllegalArgumentException if src 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 new file mode 100644 index 00000000000..5063e7ccde5 --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/BidiClassifier.java @@ -0,0 +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() {} +} 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 new file mode 100644 index 00000000000..484681654a8 --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/BidiRun.java @@ -0,0 +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() {} +} 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 new file mode 100644 index 00000000000..5b0922f9e8d --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/BreakIterator.java @@ -0,0 +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_} + * + *

    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: + *

    • getTitleInstance() returns a BreakIterator that locates boundaries + * between title breaks. + *
    • getSentenceInstance() returns a BreakIterator that locates boundaries + * between sentences. This is useful for triple-click selection, for example. + *
    • 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. + *
    • 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. + *
    • 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".
    + * + * 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: + *
    • The beginning and end of the text are always treated as boundary positions. + *
    • 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). + *
    • 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(). + *
    • 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. + *
    • 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.
    + * + * 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. + * + * Note: 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. + * + *

    + * Examples:

    + * Creating and using text boundaries + *

    + *
    + * 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);
    + *      }
    + * }
    + * 
    + *
    + * + * Print each element in order + *
    + *
    + * 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));
    + *     }
    + * }
    + * 
    + *
    + * + * Print each element in reverse order + *
    + *
    + * 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));
    + *     }
    + * }
    + * 
    + *
    + * + * Print first element + *
    + *
    + * public static void printFirst(BreakIterator boundary, String source) {
    + *     int start = boundary.first();
    + *     int end = boundary.next();
    + *     System.out.println(source.substring(start,end));
    + * }
    + * 
    + *
    + * + * Print last element + *
    + *
    + * public static void printLast(BreakIterator boundary, String source) {
    + *     int end = boundary.last();
    + *     int start = boundary.previous();
    + *     System.out.println(source.substring(start,end));
    + * }
    + * 
    + *
    + * + * Print the element at a specified position + *
    + *
    + * 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));
    + * }
    + * 
    + *
    + * + * Find the next word + *
    + *
    + * 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;
    + * }
    + * 
    + * (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.) + *
    + * + * @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 actual iterator being used by the BreakIterator, + * and therefore, this function's return value should be treated as + * const. 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 en_US_CALIFORNIA, the actual data may be + * drawn from en (the actual locale), and + * en_US may be the most specific locale that exists (the + * valid locale). + * + *

    Note: The actual locale is returned correctly, but the valid + * 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 type, 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 new file mode 100644 index 00000000000..5cdef2f3aeb --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/CollationKey.java @@ -0,0 +1,415 @@ +/** +******************************************************************************* +* Copyright (C) 1996-2011, International Business Machines Corporation and * +* others. All Rights Reserved. * +******************************************************************************* +*/ +package com.ibm.icu.text; + +/** + *

    A CollationKey represents a String + * under the rules of a specific Collator + * object. Comparing two CollationKeys returns the + * relative order of the Strings they represent.

    + * + *

    Since the rule set of Collators can differ, the + * sort orders of the same string under two different + * Collators might differ. Hence comparing + * CollationKeys generated from different + * Collators can give incorrect results.

    + + *

    Both the method + * CollationKey.compareTo(CollationKey) and the method + * Collator.compare(String, String) compare two strings + * and returns their relative order. The performance characterictics + * of these two approaches can differ.

    + * + *

    During the construction of a CollationKey, the + * entire source string is examined and processed into a series of + * bits terminated by a null, that are stored in the CollationKey. + * When CollationKey.compareTo(CollationKey) executes, it + * performs bitwise comparison on the bit sequences. This can incurs + * startup cost when creating the CollationKey, 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.

    + * + *

    On the other hand, implementations of + * Collator.compare(String, String) 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.

    + * + *

    More information about the composition of the bit sequence can + * be found in the + * + * user guide.

    + * + *

    The following example shows how CollationKeys can be used + * to sort a list of Strings.

    + *
    + *
    + * // 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 );
    + * 
    + * //... + *
    + * // Inside body of sort routine, compare keys this way + * if( keys[i].compareTo( keys[j] ) > 0 ) + * // swap keys[i] and keys[j] + *
    + * //... + *
    + * // 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() ); + *
    + *
    + *

    + *

    + * This class is not subclassable + *

    + * @see Collator + * @see RuleBasedCollator + * @author Syn Wee Quek + * @stable ICU 2.8 + */ +public final class CollationKey implements Comparable +{ + /** + * @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(); + } + + /** + *

    Duplicates and returns the value of this CollationKey as a sequence + * of big-endian bytes terminated by a null.

    + * + *

    If two CollationKeys can be legitimately compared, then one can + * compare the byte arrays of each to obtain the same result, e.g. + *

    +     * 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 < targetkey) {
    +     *         System.out.println("String 1 is less than string 2");
    +     *         return;
    +     *     }
    +     *     if (targetkey < key) {
    +     *         System.out.println("String 1 is more than string 2");
    +     *     }
    +     *     i ++;
    +     * } while (key != 0 && targetKey != 0);
    +     *
    +     * System.out.println("Strings are equal.");
    +     * 
    + *

    + * @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 ------------------------------------------------- + + /** + *

    Compare this CollationKey to another CollationKey. The + * collation rules of the Collator that created this key are + * applied.

    + * + *

    Note: Comparison between CollationKeys + * created by different Collators might return incorrect + * results. See class documentation.

    + * + * @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); + } + + /** + *

    Compare this CollationKey and the specified Object for + * equality. The collation rules of the Collator that created + * this key are applied.

    + * + *

    See note in compareTo(CollationKey) for warnings about + * possible incorrect results.

    + * + * @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); + } + + /** + *

    + * Compare this CollationKey and the argument target CollationKey for + * equality. + * The collation + * rules of the Collator object which created these objects are applied. + *

    + *

    + * See note in compareTo(CollationKey) for warnings of incorrect results + *

    + * @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); + } + + /** + *

    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. + *

    + * @return the hash value. + * @stable ICU 2.8 + */ + public int hashCode() + { + return key.hashCode(); + } + + /** + *

    + * 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. + *

    + *

    + * 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". + *

    + *

    + * 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. + *

    + *

    + * For more on usage, see example in test procedure + * + * src/com/ibm/icu/dev/test/collator/CollationAPITest/TestBounds. + * + *

    + *

    + * Collation keys produced may be compared using the compare API. + *

    + * @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"); + } + + /** + *

    + * 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. + *

    + *

    + * The strength levels are merged with their corresponding counterparts + * (PRIMARIES with PRIMARIES, SECONDARIES with SECONDARIES etc.). + *

    + *

    + * The merged String representation of the result CollationKey will be a + * concatenation of the String representations of the 2 source + * CollationKeys. + *

    + *

    + * Between the values from the same level a separator is inserted. + * example (uncompressed): + *

     
    +     * 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
    +     * 
    + *

    + *

    + * This allows for concatenating of first and last names for sorting, among + * other things. + *

    + *

    + * @param source CollationKey to merge with + * @return a CollationKey that contains the valid merged sorting order + * with a null String representation, + * i.e. new CollationKey(null, merge_sort_order) + * @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 new file mode 100644 index 00000000000..d9eaaeb8091 --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/Collator.java @@ -0,0 +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_} +* +*

    Collator performs locale-sensitive string comparison. A concrete +* subclass, RuleBasedCollator, allows customization of the collation +* ordering by the use of rule sets.

    +* +*

    Following the Unicode +* Consortium's specifications for the +* Unicode Collation +* Algorithm (UCA), there are 5 different levels of strength used +* in comparisons: +* +*

      +*
    • PRIMARY strength: Typically, this is used to denote differences between +* base characters (for example, "a" < "b"). +* It is the strongest difference. For example, dictionaries are divided +* into different sections by base character. +*
    • SECONDARY strength: Accents in the characters are considered secondary +* differences (for example, "as" < "às" < "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. +*
    • TERTIARY strength: Upper and lower case differences in characters are +* distinguished at tertiary strength (for example, "ao" < "Ao" < +* "aò"). In addition, a variant of a letter differs from the base +* form on the tertiary strength (such as "A" and "Ⓐ"). 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. +*
    • QUATERNARY strength: When punctuation is ignored +* +* (see Ignoring Punctuations in the user guide) at PRIMARY to TERTIARY +* strength, an additional strength level can +* be used to distinguish words with and without punctuation (for example, +* "ab" < "a-b" < "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. +*
    • 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. +*
    +* +* 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.

    +* +*

    For more information about the collation service see the +* users +* guide.

    +* +*

    Examples of use +*

    +* // 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("à\u0325", "a\u0325̀") != 0) {
    +*     System.out.println("à\u0325 is not equals to a\u0325̀ without decomposition");
    +*     myCollator.setDecomposition(CANONICAL_DECOMPOSITION);
    +*     if (myCollator.compare("à\u0325", "a\u0325̀") != 0) {
    +*         System.out.println("Error: à\u0325 should be equals to a\u0325̀ with decomposition");
    +*     }
    +*     else {
    +*         System.out.println("à\u0325 is equals to a\u0325̀ with decomposition");
    +*     }
    +* }
    +* else {
    +*     System.out.println("Error: à\u0325 should be not equals to a\u0325̀ without decomposition");
    +* }
    +* 
    +*

    +* @see RuleBasedCollator +* @see CollationKey +* @author Syn Wee Quek +* @stable ICU 2.8 +*/ +public class Collator implements Comparator, 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 + * + * (see Ignoring Punctuations in the user guide) 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. + *

    + *

    + * Note this value is different from JDK's + *

    + * @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.

    + * + *

    Note this value is different from the JDK's.

    + * @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.

    + * + *

    CANONICAL_DECOMPOSITION corresponds to Normalization Form D as + * described in + * Unicode Technical Report #15. + *

    + * @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.

    + * + *

    The default strength for the Collator is TERTIARY, unless specified + * otherwise by the locale used to create the Collator.

    + * + *

    See the Collator class description for an example of use.

    + * @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.

    + * + *

    Since a great many of the world's languages do not require + * text normalization, most locales set NO_DECOMPOSITION as the + * default decomposition mode.

    + * + * The default decompositon mode for the Collator is + * NO_DECOMPOSITON, unless specified otherwise by the locale used + * to create the Collator.

    + * + *

    See getDecomposition for a description of decomposition + * mode.

    + * + * @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. + *

    Note: 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 MUST 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. + * Note: 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. + *

    Note: 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 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 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 + * Locales and Services 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. + *

    + * {@icunote} This can return QUATERNARY strength, which is not supported by the + * JDK version. + *

    + * See the Collator class description for more details. + *

    + * @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. + *

    + *

    + * See the Collator class description for more details. + *

    + * @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. + *

    + * @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. + *

    + * @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); + } + + /** + *

    + * Transforms the String into a CollationKey suitable for efficient + * repeated comparison. The resulting key depends on the collator's + * rules, strength and decomposition mode. + *

    + *

    See the CollationKey class documentation for more information.

    + * @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. + *

    + *

    + * Sets the variable top to a collation element value of a string supplied. + *

    + * @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 en_US_CALIFORNIA, the actual data may be + * drawn from en (the actual locale), and + * en_US may be the most specific locale that exists (the + * valid locale). + * + *

    Note: This method will be implemented in ICU 3.0; ICU 2.8 + * contains a partial preview implementation. The * actual + * locale is returned correctly, but the valid 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 type, 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 new file mode 100644 index 00000000000..39f1fd123f4 --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/CurrencyPluralInfo.java @@ -0,0 +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() {} +} 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 new file mode 100644 index 00000000000..686d1dd3508 --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/DateFormat.java @@ -0,0 +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_} + * + *

    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 Date object or + * as the milliseconds since January 1, 1970, 00:00:00 GMT. + * + *

    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. + * + *

    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. + * + *

    To format a date for the current Locale, use one of the + * static factory methods: + *

    + *  myString = DateFormat.getDateInstance().format(myDate);
    + * 
    + *

    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. + *

    + *  DateFormat df = DateFormat.getDateInstance();
    + *  for (int i = 0; i < a.length; ++i) {
    + *    output.println(df.format(myDate[i]) + "; ");
    + *  }
    + * 
    + *

    To format a number for a different Locale, specify it in the + * call to getDateInstance(). + *

    + *  DateFormat df = DateFormat.getDateInstance(DateFormat.LONG, Locale.FRANCE);
    + * 
    + *

    You can use a DateFormat to parse also. + *

    + *  myDate = df.parse(myString);
    + * 
    + *

    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: + *

    • SHORT is completely numeric, such as 12.13.52 or 3:30pm + *
    • MEDIUM is longer, such as Jan 12, 1952 + *
    • LONG is longer, such as January 12, 1952 or 3:30:32pm + *
    • FULL is pretty completely specified, such as + * Tuesday, April 12, 1952 AD or 3:30:42pm PST. + *
    + * + *

    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. + * + *

    You can also use forms of the parse and format methods with + * ParsePosition and FieldPosition to + * allow you to + *

    • progressively parse through pieces of a string. + *
    • align any particular field, or find out where it is for selection + * on the screen. + *
    + * + *

    Synchronization

    + * + * 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. + * + *

    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). + * + *

    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 + * + *

    + * A skeleton + *

      + *
    • + * 1. only keeps the field pattern letter and ignores all other parts + * in a pattern, such as space, punctuations, and string literals. + *
    • + * 2. hides the order of fields. + *
    • + * 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. + *
    + */ + /** + * {@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 cal. + *

    + * @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 cal. + *

    + * @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 cal. + *

    + * Note: 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 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 cal. + *

    + * Note: 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 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 cal. + *

    + * Note: 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 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 cal. + *

    + * Note: 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 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. + *

    + * Note: When this functionality is moved into the core JDK, this method + * will probably be replaced by a new overload of {@link DateFormat#getInstance}. + *

    + * + * @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 cal. + * + *

    Note: 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. + * + *

    There is no public constructor to this class, the only instances are the + * constants defined here. + *

    + * @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 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(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 DateFormat.Field with the given name and + * the Calendar field which this attribute represents. Use -1 for + * calendarField if this field does not have a corresponding + * Calendar field. + * + * @param name Name of the attribute + * @param calendarField Calendar 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 Field constant that corresponds to the + * Calendar field calendarField. If there is no + * corresponding Field is available, null is returned. + * + * @param calendarField Calendar field constant + * @return Field associated with the calendarField, + * or null if no associated Field is available. + * @throws IllegalArgumentException if calendarField is not + * a valid Calendar 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 Calendar field associated with this attribute. + * If there is no corresponding Calendar available, this will + * return -1. + * + * @return Calendar 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 new file mode 100644 index 00000000000..ab0f9c95885 --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/DateFormatSymbols.java @@ -0,0 +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_} + * + *

    DateFormatSymbols 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. + * DateFormat and SimpleDateFormat both use + * DateFormatSymbols to encapsulate this information. + * + *

    Typically you shouldn't use DateFormatSymbols directly. + * Rather, you are encouraged to create a date-time formatter with the + * DateFormat class's factory methods: getTimeInstance, + * getDateInstance, or getDateTimeInstance. + * These methods automatically create a DateFormatSymbols for + * the formatter so that you don't have to. After the + * formatter is created, you may modify its format pattern using the + * setPattern method. For more information about + * creating formatters using DateFormat's factory methods, + * see {@link DateFormat}. + * + *

    If you decide to create a date-time formatter with a specific + * format pattern for a specific locale, you can do so with: + *

    + *
    + * new SimpleDateFormat(aPattern, new DateFormatSymbols(aLocale)).
    + * 
    + *
    + * + *

    DateFormatSymbols objects are clonable. When you obtain + * a DateFormatSymbols 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. + * + *

    New DateFormatSymbols subclasses may be added to support + * SimpleDateFormat 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 java.text.DateFormatSymbols#getInstance, + * this method simply returns new com.ibm.icu.text.DateFormatSymbols(). + * ICU does not support DateFormatSymbolsProvider 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 java.text.DateFormatSymbols#getInstance, + * this method simply returns new com.ibm.icu.text.DateFormatSymbols(locale). + * ICU does not support DateFormatSymbolsProvider 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 java.text.DateFormatSymbols#getInstance, + * this method simply returns new com.ibm.icu.text.DateFormatSymbols(locale). + * ICU does not support DateFormatSymbolsProvider 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 getInstance methods of + * this class can return localized instances. + * + * {@icunote} Unlike java.text.DateFormatSymbols#getAvailableLocales, + * this method simply returns the array of Locales available in this + * class. ICU does not support DateFormatSymbolsProvider introduced in + * Java 6 or its equivalent implementation for now. + * + * @return An array of Locales for which localized + * DateFormatSymbols 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 getInstance + * methods of this class can return localized instances. + * + * {@icunote} Unlike java.text.DateFormatSymbols#getAvailableLocales, + * this method simply returns the array of ULocales available in this + * class. ICU does not support DateFormatSymbolsProvider introduced in + * Java 6 or its equivalent implementation for now. + * + * @return An array of ULocales for which localized + * DateFormatSymbols 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 Calendar.SUNDAY, + * Calendar.MONDAY, 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 Calendar.SUNDAY, + * Calendar.MONDAY, 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 Calendar.SUNDAY, + * Calendar.MONDAY, 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 Calendar.SUNDAY, + * Calendar.MONDAY, 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 Calendar.SUNDAY, + * Calendar.MONDAY, 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. + * + *

    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. + *

    + * Subclassing:
    + * 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". + *

    + * Within the ResourceBundle, this method searches for five keys: + *

      + *
    • DayNames - + * An array of strings corresponding to each possible + * value of the DAY_OF_WEEK field. Even though + * DAY_OF_WEEK starts with SUNDAY = 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 DateFormatSymbols for the requested locale. + * + *
    • DayAbbreviations - + * 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 + * DateFormatSymbols for the locale. + * + *
    • MonthNames - + * An array of strings corresponding to each possible + * value of the MONTH field. If this key is not found + * in the bundle, the month names are inherited from the + * default DateFormatSymbols for the requested locale. + * + *
    • MonthAbbreviations - + * 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 + * DateFormatSymbols for the locale. + * + *
    • Eras - + * An array of strings corresponding to each possible + * value of the ERA field. If this key is not found + * in the bundle, the era names are inherited from the + * default DateFormatSymbols for the requested locale. + *
    + *

    + * @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. + *

    + * Subclassing:
    + * 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". + *

    + * Within the ResourceBundle, this method searches for five keys: + *

      + *
    • DayNames - + * An array of strings corresponding to each possible + * value of the DAY_OF_WEEK field. Even though + * DAY_OF_WEEK starts with SUNDAY = 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 DateFormatSymbols for the requested locale. + * + *
    • DayAbbreviations - + * 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 + * DateFormatSymbols for the locale. + * + *
    • MonthNames - + * An array of strings corresponding to each possible + * value of the MONTH field. If this key is not found + * in the bundle, the month names are inherited from the + * default DateFormatSymbols for the requested locale. + * + *
    • MonthAbbreviations - + * 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 + * DateFormatSymbols for the locale. + * + *
    • Eras - + * An array of strings corresponding to each possible + * value of the ERA field. If this key is not found + * in the bundle, the era names are inherited from the + * default DateFormatSymbols for the requested locale. + *
    + *

    + * @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 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 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. + *

    + * 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". + *

    + * Note: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 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. + *

    + * 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". + *

    + * Note: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 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. + *

    + * Note: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. + *

    + * Note: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 en_US_CALIFORNIA, the actual data may be + * drawn from en (the actual locale), and + * en_US may be the most specific locale that exists (the + * valid locale). + * + *

    Note: This method will be implemented in ICU 3.0; ICU 2.8 + * contains a partial preview implementation. The * actual + * locale is returned correctly, but the valid 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 type, 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 new file mode 100644 index 00000000000..21021b02dd2 --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/DecimalFormat.java @@ -0,0 +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_} + * + * DecimalFormat 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. + * + *

    To obtain a {@link NumberFormat} for a specific locale (including the default + * locale) call one of NumberFormat's factory methods such as {@link + * NumberFormat#getInstance}. Do not call the DecimalFormat constructors + * directly, unless you know what you are doing, since the {@link NumberFormat} factory + * methods may return subclasses other than DecimalFormat. If you need to + * customize the format object, do something like this: + * + *

    + * NumberFormat f = NumberFormat.getInstance(loc);
    + * if (f instanceof DecimalFormat) {
    + *     ((DecimalFormat) f).setDecimalSeparatorAlwaysShown(true);
    + * }
    + * + *

    Example Usage + * + * Print out a number using the localized number, currency, and percent + * format for each locale. + * + *

    + * 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) {}
    + *     }
    + * }
    + * + *

    Another example use getInstance(style).
    + * Print out a number using the localized number, currency, percent, + * scientific, integer, iso currency, and plural currency format for each locale. + * + *

    + * 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) {}
    + * }
    + * + *

    Patterns

    + * + *

    A DecimalFormat consists of a pattern and a set of + * symbols. 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. + * + *

    Special Pattern Characters

    + * + *

    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. + * + *

    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. + * + *

    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. + * + *

    + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    Symbol + * Location + * Localized? + * Meaning + *
    0 + * Number + * Yes + * Digit + *
    1-9 + * Number + * Yes + * '1' through '9' indicate rounding. + *
    @ + * Number + * No + * Significant digit + *
    # + * Number + * Yes + * Digit, zero shows as absent + *
    . + * Number + * Yes + * Decimal separator or monetary decimal separator + *
    - + * Number + * Yes + * Minus sign + *
    , + * Number + * Yes + * Grouping separator + *
    E + * Number + * Yes + * Separates mantissa and exponent in scientific notation. + * Need not be quoted in prefix or suffix. + *
    + + * Exponent + * Yes + * Prefix positive exponents with localized plus sign. + * Need not be quoted in prefix or suffix. + *
    ; + * Subpattern boundary + * Yes + * Separates positive and negative subpatterns + *
    % + * Prefix or suffix + * Yes + * Multiply by 100 and show as percentage + *
    \u2030 + * Prefix or suffix + * Yes + * Multiply by 1000 and show as per mille + *
    ¤ (\u00A4) + * Prefix or suffix + * No + * 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. + *
    ' + * Prefix or suffix + * No + * Used to quote special characters in a prefix or suffix, + * for example, "'#'#" formats 123 to + * "#123". To create a single quote + * itself, use two in a row: "# o''clock". + *
    * + * Prefix or suffix boundary + * Yes + * Pad escape, precedes pad character + *
    + *
    + * + *

    A DecimalFormat 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#)". + * + *

    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. + * + *

    The grouping separator 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 grouping size 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 primary grouping size, and one used for all + * others, the secondary grouping size. 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 "#,##,###,####" == "###,###,####" == + * "##,#,###,####". + * + *

    Illegal patterns, such as "#.#.#" or "#.###,###", will cause + * DecimalFormat to throw an {@link IllegalArgumentException} with a message + * that describes the problem. + * + *

    Pattern BNF

    + * + *
    + * pattern    := subpattern (';' subpattern)?
    + * subpattern := prefix? number exponent? suffix?
    + * number     := (integer ('.' fraction)?) | sigDigits
    + * prefix     := '\u0000'..'\uFFFD' - specialCharacters
    + * suffix     := '\u0000'..'\uFFFD' - specialCharacters
    + * integer    := '#'* '0'* '0'
    + * fraction   := '0'* '#'*
    + * sigDigits  := '#'* '@' '@'* '#'*
    + * exponent   := 'E' '+'? '0'* '0'
    + * padSpec    := '*' padChar
    + * padChar    := '\u0000'..'\uFFFD' - quote
    + *  
    + * 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
    + * 
    + * The first subpattern is for positive numbers. The second (optional) + * subpattern is for negative numbers. + * + *

    Not indicated in the BNF syntax above: + * + *

      + * + *
    • 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. + * + *
    • 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 "#,##,###" formats the number 123456789 as + * "12,34,56,789". + * + *
    • The pad specifier padSpec may appear before the prefix, after the + * prefix, before the suffix, after the suffix, or not at all. + * + *
    • In place of '0', the digits '1' through '9' may be used to indicate a rounding + * increment. + * + *
    + * + *

    Parsing

    + * + *

    DecimalFormat parses all Unicode characters that represent decimal + * digits, as defined by {@link UCharacter#digit}. In addition, + * DecimalFormat 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. + * + *

    During parsing, grouping separators are ignored. + * + *

    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". + * + *

    If {@link #parse(String, ParsePosition)} fails to parse a string, it returns + * null and leaves the parse position unchanged. The convenience method + * {@link #parse(String)} indicates parse failure by throwing a {@link + * java.text.ParseException}. + * + *

    Formatting

    + * + *

    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 scientific notation or significant + * digits. + * + *

    • If the number of actual integer digits exceeds the maximum integer + * digits, then only the least significant digits are shown. For example, 1997 is + * formatted as "97" if the maximum integer digits is set to 2. + * + *
    • If the number of actual integer digits is less than the minimum integer + * digits, then leading zeros are added. For example, 1997 is formatted as "01997" + * if the minimum integer digits is set to 5. + * + *
    • If the number of actual fraction digits exceeds the maximum fraction + * digits, 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. + * + *
    • If the number of actual fraction digits is less than the minimum fraction + * digits, then trailing zeros are added. For example, 0.125 is formatted as + * "0.1250" if the mimimum fraction digits is set to 4. + * + *
    • Trailing fractional zeros are not displayed if they occur j positions + * after the decimal, where j 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. + *
    + * + *

    Special Values + * + *

    NaN is represented as a single character, typically + * \uFFFD. This character is determined by the {@link + * DecimalFormatSymbols} object. This is the only value for which the prefixes and + * suffixes are not used. + * + *

    Infinity is represented as a single character, typically \u221E, + * with the positive or negative prefixes and suffixes applied. The infinity character is + * determined by the {@link DecimalFormatSymbols} object. + * + *

    Scientific Notation

    + * + *

    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 103. The + * mantissa is typically in the half-open interval [1.0, 10.0) or sometimes [0.0, 1.0), + * but it need not be. DecimalFormat supports arbitrary mantissas. + * DecimalFormat 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". + * + *

      + * + *
    • 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, not 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 '+'.) + * + *
    • 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. + * + *
    • The maximum number of integer digits, if present, specifies the exponent grouping. + * The most common use of this is to generate engineering notation, in which the + * exponent is a multiple of three, e.g., "##0.###E0". The number 12345 is formatted + * using "##0.####E0" as "12.345E3". + * + *
    • 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. + * + *
    • 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 + * minimum integer and maximum fraction 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. + * + *
    • Exponential patterns may not contain grouping separators. + * + *
    + * + *

    Significant Digits

    + * + * DecimalFormat 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: + * + *
    + * + * + * + * + * + * + *
    Pattern + * Minimum significant digits + * Maximum significant digits + * Number + * Output of format() + *
    @@@ + * 3 + * 3 + * 12345 + * 12300 + *
    @@@ + * 3 + * 3 + * 0.12345 + * 0.123 + *
    @@## + * 2 + * 4 + * 3.14159 + * 3.142 + *
    @@## + * 2 + * 4 + * 1.23004 + * 1.23 + *
    + *
    + * + *
      + * + *
    • Significant digit counts may be expressed using patterns that specify a minimum and + * maximum number of significant digits. These are indicated by the '@' and + * '#' characters. The minimum number of significant digits is the number of + * '@' characters. The maximum number of significant digits is the number of + * '@' characters plus the number of '#' characters following on + * the right. For example, the pattern "@@@" indicates exactly 3 significant + * digits. The pattern "@##" 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 + * "@##" formats the number 0.1203 as "0.12". + * + *
    • If a pattern uses significant digits, it may not contain a decimal separator, nor + * the '0' pattern character. Patterns such as "@00" or + * "@.###" are disallowed. + * + *
    • Any number of '#' characters may be prepended to the left of the + * leftmost '@' character. These have no effect on the minimum and maximum + * significant digits counts, but may be used to position grouping separators. For + * example, "#,#@#" indicates a minimum of one significant digits, a maximum + * of two significant digits, and a grouping size of three. + * + *
    • In order to enable significant digits formatting, use a pattern containing the + * '@' pattern character. Alternatively, call {@link + * #setSignificantDigitsUsed setSignificantDigitsUsed(true)}. + * + *
    • In order to disable significant digits formatting, use a pattern that does not + * contain the '@' pattern character. Alternatively, call {@link + * #setSignificantDigitsUsed setSignificantDigitsUsed(false)}. + * + *
    • The number of significant digits has no effect on parsing. + * + *
    • 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 getMinimumSignificantDigits() - + * 1, and a maximum fraction digit count of getMaximumSignificantDigits() - + * 1. For example, the pattern "@@###E0" is equivalent to + * "0.0###E0". + * + *
    • 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. + * + *
    + * + *

    Padding

    + * + *

    DecimalFormat 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, "$*x#,##0.00" formats + * 123 to "$xx123.00", and 1234 to "$1,234.00". + * + *

      + * + *
    • When padding is in effect, the width of the positive subpattern, including prefix + * and suffix, determines the format width. For example, in the pattern "* #0 + * o''clock", the format width is 10. + * + *
    • The width is counted in 16-bit code units (Java chars). + * + *
    • 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. + * + *
    • 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. + * + *
    • When specified in a pattern, the 16-bit char immediately following the + * pad escape is the pad character. This may be any character, including a special pattern + * character. That is, the pad escape escapes the following character. If there + * is no character after the pad escape, then the pattern is illegal. + * + *
    + * + *

    + * Rounding + * + *

    DecimalFormat 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. + * + *

      + * + *
    • Rounding only affects the string produced by formatting. It does not affect + * parsing or change any numerical values. + * + *
    • A rounding mode 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}. + * + *
    • Some locales use rounding in their currency formats to reflect the smallest + * currency denomination. + * + *
    • In a pattern, digits '1' through '9' specify rounding, but otherwise behave + * identically to digit '0'. + * + *
    + * + *

    Synchronization

    + * + *

    DecimalFormat 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. + * + *

    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. + * + *

    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. + * + *

    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. + * + *

    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 using the setters. + * + *

    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 Number object to represent the + * parsed value. Double objects are returned to represent non-integral + * values which cannot be stored in a BigDecimal. These are + * NaN, infinity, -infinity, and -0.0. If {@link #isParseBigDecimal()} is + * false (the default), all other values are returned as Long, + * BigInteger, or BigDecimal values, in that order of + * preference. If {@link #isParseBigDecimal()} is true, all other values are returned + * as BigDecimal 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 Number object with the parsed value or + * null 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. + * + *

    Examples: +123, $123, sFr123 + * @return the prefix + * @stable ICU 2.0 + */ + public String getPositivePrefix() { + return ((java.text.DecimalFormat)numberFormat).getPositivePrefix(); + } + + /** + * Sets the positive prefix. + * + *

    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. + * + *

    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. + * + *

    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. + * + *

    Example: 123% + * + * @return the suffix + * @stable ICU 2.0 + */ + public String getPositiveSuffix() { + return ((java.text.DecimalFormat)numberFormat).getPositiveSuffix(); + } + + /** + * Sets the positive suffix. + * + *

    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. + * + *

    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. + * + *

    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. + * + *

    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. + * + *

    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 null 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 null or + * BigDecimal(0.0) to disable rounding. + * @throws IllegalArgumentException if newValue 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 null or + * BigDecimal(0.0) to disable rounding. + * @throws IllegalArgumentException if newValue 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 newValue 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 BigDecimal.ROUND_UP and + * BigDecimal.ROUND_UNNECESSARY. + * @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 BigDecimal.ROUND_UP and + * BigDecimal.ROUND_UNNECESSARY. + * @exception IllegalArgumentException if roundingMode 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 format() 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 format() 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 + * format(), or zero to disable padding + * @exception IllegalArgumentException if width 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 format() is shorter + * than the format width. + * + * @return the pad position, one of PAD_BEFORE_PREFIX, + * PAD_AFTER_PREFIX, PAD_BEFORE_SUFFIX, or + * PAD_AFTER_SUFFIX. + * @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 format() is shorter + * than the format width. This has no effect unless padding is enabled. + * + * @param padPos the pad position, one of PAD_BEFORE_PREFIX, + * PAD_AFTER_PREFIX, PAD_BEFORE_SUFFIX, or + * PAD_AFTER_SUFFIX. + * @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 minExpDig < 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 getGroupingSize(). 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.)

    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.) + * + *

    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. + * + *

    + * 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 attributes = it.getAttributes(); + if (attributes != null) { + for (Entry 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. + * + *

    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 + * + *

    Example "#,#00.0#" -> 1,234.56 + * + *

    This means a minimum of 2 integer digits, 1 fraction digit, and a maximum of 2 + * fraction digits. + * + *

    Example: "#,#00.0#;(#,#00.0#)" for negatives in parentheses. + * + *

    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. + * + *

    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 + * + *

    Example "#,#00.0#" -> 1,234.56 + * + *

    This means a minimum of 2 integer digits, 1 fraction digit, and a maximum of 2 + * fraction digits. + * + *

    Example: "#,#00.0#;(#,#00.0#)" for negatives in parantheses. + * + *

    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 + * min is less than one then it is set to one. If the maximum significant + * digits count is less than min, then it is set to + * min. 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 + * max is less than one then it is set to one. If the minimum significant + * digits count is greater than max, then it is set to + * max. 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 Currency 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 new file mode 100644 index 00000000000..9436fa6a3da --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/DecimalFormatSymbols.java @@ -0,0 +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 DecimalFormat to format + * numbers. DecimalFormat creates for itself an instance of + * DecimalFormatSymbols from its locale data. If you need to + * change any of these symbols, you can get the + * DecimalFormatSymbols object from your DecimalFormat + * and modify it. + * + *

    This is an enhanced version of DecimalFormatSymbols that + * is based on the standard version in the JDK. New or changed functionality + * is labeled + * NEW. + * + * @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 new file mode 100644 index 00000000000..91bec490eb7 --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/MessageFormat.java @@ -0,0 +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_} + * + *

    MessageFormat produces concatenated messages in a language-neutral + * way. Use this whenever concatenating strings that are displayed to + * end users. + * + *

    A MessageFormat contains an array of subformats arranged + * within a template string. Together, the subformats and + * template string determine how the MessageFormat will operate during + * formatting and parsing. + * + *

    Typically, both the subformats and the template string are + * specified at once in a pattern. By using different + * patterns for different locales, messages may be localized. + * + *

    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. + * + *

    Note: + * MessageFormat differs from the other Format + * classes in that you create a MessageFormat object with one + * of its constructors (not with a getInstance style factory + * method). The factory methods aren't necessary because MessageFormat + * 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. + * + *

    Note: + * 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 + * :ID_START: and continue with characters in :ID_CONTINUE:, + * in particular they do not start with a digit. If named arguments + * are used, {@link #usesNamedArguments()} will return true. + * + *

    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 Maps use + * Strings that name the argument indices, e.g. "0", + * "1", "2"... etc. + * + *

    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. + * + *

    The API {@link #format(Object, StringBuffer, FieldPosition)} has + * been modified so that the Object argument can be + * either an Object array or a Map. If this + * format uses named arguments, this argument must not be an + * Object array otherwise an exception will be thrown. + * If the argument is a Map it can be used with Strings that + * represent indices as described above. + * + *

    Patterns and Their Interpretation

    + * + * MessageFormat uses patterns of the following form: + *
    + * MessageFormatPattern:
    + *         String
    + *         MessageFormatPattern FormatElement String
    + *
    + * FormatElement:
    + *         { ArgumentIndexOrName }
    + *         { ArgumentIndexOrName , FormatType }
    + *         { ArgumentIndexOrName , FormatType , FormatStyle }
    + *
    + * ArgumentIndexOrName: one of 
    + *         ['0'-'9']+
    + *         [:ID_START:][:ID_CONTINUE:]*
    + *
    + * FormatType: one of 
    + *         number date time choice spellout ordinal duration plural
    + *
    + * FormatStyle:
    + *         short
    + *         medium
    + *         long
    + *         full
    + *         integer
    + *         currency
    + *         percent
    + *         SubformatPattern
    + *         RulesetName
    + *
    + * String:
    + *         StringPartopt
    + *         String StringPart
    + *
    + * StringPart:
    + *         ''
    + *         ' QuotedString '
    + *         UnquotedString
    + *
    + * SubformatPattern:
    + *         SubformatPatternPartopt
    + *         SubformatPattern SubformatPatternPart
    + *
    + * SubFormatPatternPart:
    + *         ' QuotedPattern '
    + *         UnquotedPattern
    + * 
    + * + * RulesetName: + * UnquotedString + * + *

    Within a String, "''" represents a single + * quote. A QuotedString can contain arbitrary characters + * except single quotes; the surrounding single quotes are removed. + * An UnquotedString 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 + * "'''{'0}''" or "'''{0}'''". + * + *

    Within a SubformatPattern, different rules apply. + * A QuotedPattern can contain arbitrary characters + * except single quotes; but the surrounding single quotes are + * not removed, so they may be interpreted by the + * subformat. For example, "{1,number,$'#',##}" will + * produce a number format with the pound-sign quoted, with a result + * such as: "$#31,45". + * An UnquotedPattern can contain arbitrary characters + * except single quotes, but curly braces within it must be balanced. + * For example, "ab {0} de" and "ab '}' de" + * are valid subformat patterns, but "ab {0'}' de" and + * "ab } de" are not. + * + *

    Warning:
    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. + * + *
    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.

    + *
    + * + *

    The ArgumentIndex value is a non-negative integer written + * using the digits '0' through '9', and represents an index into the + * arguments array passed to the format methods + * or the result array returned by the parse methods. + * + *

    The FormatType and FormatStyle values are used to create + * a Format 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 SubformatPattern must + * be a valid pattern string for the Format subclass used. + * + *

    + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    Format Type + * Format Style + * Subformat Created + *
    (none) + * null + *
    number + * (none) + * NumberFormat.getInstance(getLocale()) + *
    integer + * NumberFormat.getIntegerInstance(getLocale()) + *
    currency + * NumberFormat.getCurrencyInstance(getLocale()) + *
    percent + * NumberFormat.getPercentInstance(getLocale()) + *
    SubformatPattern + * new DecimalFormat(subformatPattern, new DecimalFormatSymbols(getLocale())) + *
    date + * (none) + * DateFormat.getDateInstance(DateFormat.DEFAULT, getLocale()) + *
    short + * DateFormat.getDateInstance(DateFormat.SHORT, getLocale()) + *
    medium + * DateFormat.getDateInstance(DateFormat.DEFAULT, getLocale()) + *
    long + * DateFormat.getDateInstance(DateFormat.LONG, getLocale()) + *
    full + * DateFormat.getDateInstance(DateFormat.FULL, getLocale()) + *
    SubformatPattern + * new SimpleDateFormat(subformatPattern, getLocale()) + *
    time + * (none) + * DateFormat.getTimeInstance(DateFormat.DEFAULT, getLocale()) + *
    short + * DateFormat.getTimeInstance(DateFormat.SHORT, getLocale()) + *
    medium + * DateFormat.getTimeInstance(DateFormat.DEFAULT, getLocale()) + *
    long + * DateFormat.getTimeInstance(DateFormat.LONG, getLocale()) + *
    full + * DateFormat.getTimeInstance(DateFormat.FULL, getLocale()) + *
    SubformatPattern + * new SimpleDateFormat(subformatPattern, getLocale()) + *
    choice + * SubformatPattern + * new ChoiceFormat(subformatPattern) + *
    spellout + * RulesetName (optional) + * new RuleBasedNumberFormat(getLocale(), RuleBasedNumberFormat.SPELLOUT) + *
        .setDefaultRuleset(ruleset);
    + *
    ordinal + * RulesetName (optional) + * new RuleBasedNumberFormat(getLocale(), RuleBasedNumberFormat.ORDINAL) + *
        .setDefaultRuleset(ruleset);
    + *
    duration + * RulesetName (optional) + * new RuleBasedNumberFormat(getLocale(), RuleBasedNumberFormat.DURATION) + *
        .setDefaultRuleset(ruleset);
    + *
    plural + * SubformatPattern + * new PluralFormat(subformatPattern) + *
    select + * SubformatPattern + * new SelectFormat(subformatPattern) + *
    + *

    + * + *

    Usage Information

    + * + *

    Here are some examples of usage: + *

    + *
    + * 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);
    + *
    + * output: At 12:30 PM on Jul 3, 2053, there was a disturbance
    + *           in the Force on planet 7.
    + *
    + * 
    + *
    + * Typically, the message format will come from resources, and the + * arguments will be dynamically set at runtime. + * + *

    Example 2: + *

    + *
    + * 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
    + * output: The disk "MyDisk" contains 0 file(s).
    + * output: The disk "MyDisk" contains 1 file(s).
    + * output: The disk "MyDisk" contains 1,273 file(s).
    + * 
    + *
    + * + *

    For more sophisticated patterns, you can use a ChoiceFormat to get + * output such as: + *

    + *
    + * 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.
    + * 
    + *
    + * You can either do this programmatically, as in the above example, + * or by using a pattern (see + * {@link ChoiceFormat} + * for more information) as in: + *
    + *
    + * form.applyPattern(
    + *    "There {0,choice,0#are no files|1#is one file|1<are {0,number,integer} files}.");
    + * 
    + *
    + * + *

    Note: As we see above, the string produced + * by a ChoiceFormat in MessageFormat is treated specially; + * occurances of '{' are used to indicated subformats, and cause recursion. + * If you create both a MessageFormat and ChoiceFormat + * 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. + * + *

    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, + *

    + * 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)}
    + * 
    + * + *

    Likewise, parsing with a MessageFormat object using patterns containing + * multiple occurances of the same argument would return the last match. For + * example, + *

    + * 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")}
    + * 
    + * + *

    Synchronization

    + * + *

    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 + * class description. + * + * @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 + * class description. + * + * @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 + * class description. + * + * @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 + * format 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 + * format 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 + * class description. + *

    + * 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 + * format methods or returned from parse + * methods. The indices of elements in newFormats + * correspond to the argument indices used in the previously set + * pattern string. + * The order of formats in newFormats thus corresponds to + * the order of elements in the arguments array passed + * to the format methods or the result array returned + * by the parse methods. + *

    + * 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 newFormats.length 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 newFormats 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 + * format methods or returned from parse + * methods. The keys in newFormats are the argument + * names in the previously set pattern string, and the values + * are the formats. + *

    + * Only argument names from the pattern string are considered. + * Extra keys in newFormats 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. + *

    + * 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 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 newFormats corresponds to + * the order of format elements in the pattern string. + *

    + * 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 newFormats.length + * formats are replaced. + *

    + * 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 arguments array passed to + * the format methods or the result array returned by + * the parse methods. + * + * @param newFormats the new formats to use + * @exception NullPointerException if newFormats 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 arguments array passed + * to the format methods or the result array returned + * by the parse methods. + *

    + * 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. + *

    + * 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. + *

    + * This API may be used on formats that do not use named arguments. + * In this case argumentName 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. + *

    + * 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 + * format methods or returned from parse + * 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 arguments array passed + * to the format methods or the result array returned + * by the parse methods. + *

    + * 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. + *

    + * 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 arguments array passed to + * the format methods or the result array returned by + * the parse 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 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 MessageFormat's + * pattern, with format elements replaced by the formatted objects, to the + * provided StringBuffer. + *

    + * The text substituted for the individual format elements is derived from + * the current subformat of the format element and the + * arguments element at the format element's argument index + * as indicated by the first matching line of the following table. An + * argument is unavailable if arguments is + * null or has fewer than argumentIndex+1 elements. When + * an argument is unavailable no substitution is performed. + *

    + * + * + * + * + * + * + * + * + * + * + *
    Subformat + * Argument + * Formatted Text + *
    any + * unavailable + * "{" + argumentIndex + "}" + *
    any + * null + * "null" + *
    instanceof ChoiceFormat + * any + * subformat.format(argument).indexOf('{') >= 0 ?
    + * (new MessageFormat(subformat.format(argument), getLocale())).format(argument) : + * subformat.format(argument)
    + *
    != null + * any + * subformat.format(argument) + *
    null + * instanceof Number + * NumberFormat.getInstance(getLocale()).format(argument) + *
    null + * instanceof Date + * DateFormat.getDateTimeInstance(DateFormat.SHORT, + * DateFormat.SHORT, getLocale()).format(argument) + *
    null + * instanceof String + * argument + *
    null + * any + * argument.toString() + *
    + *

    + * If pos is non-null, and refers to + * Field.ARGUMENT, 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 + * arguments 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 MessageFormat's + * pattern, with format elements replaced by the formatted objects, to the + * provided StringBuffer. + *

    + * The text substituted for the individual format elements is derived from + * the current subformat of the format element and the + * arguments value corresopnding to the format element's + * argument name. + *

    + * This API may be called on formats that do not use named arguments. + * In this case the the keys in arguments must be numeric + * strings (e.g. "0", "1", "2"...). + *

    + * An argument is unavailable if arguments is + * null 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 + * arguments 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 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 + *

    + * (new {@link #MessageFormat(String) MessageFormat}(pattern)).{@link + * #format(java.lang.Object[], java.lang.StringBuffer, java.text.FieldPosition) + * format}(arguments, new StringBuffer(), null).toString() + *
    + * + * @throws IllegalArgumentException if the pattern is invalid, + * or if an argument in the arguments 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. + *

    + * @throws IllegalArgumentException if the pattern is invalid, + * or if an argument in the arguments 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 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 MessageFormat's + * pattern, with format elements replaced by the formatted objects, to the + * provided StringBuffer. + * This is equivalent to either of + *

    + * {@link #format(java.lang.Object[], java.lang.StringBuffer, + * java.text.FieldPosition) format}((Object[]) arguments, result, pos) + * {@link #format(java.util.Map, java.lang.StringBuffer, + * java.text.FieldPosition) format}((Map) arguments, result, pos) + *
    + * 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 + * arguments is not of the type + * expected by the format element(s) that use it + * @throws IllegalArgumentException if arguments 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 + * MessageFormat's pattern, producing an + * AttributedCharacterIterator. + * You can use the returned AttributedCharacterIterator + * to build the resulting String, as well as to determine information + * about the resulting String. + *

    + * The text of the returned AttributedCharacterIterator is + * the same that would be returned by + *

    + * {@link #format(java.lang.Object[], java.lang.StringBuffer, + * java.text.FieldPosition) format}(arguments, new StringBuffer(), null).toString() + *
    + *

    + * In addition, the AttributedCharacterIterator contains at + * least attributes indicating where text was generated from an + * argument in the arguments array. The keys of these attributes are of + * type MessageFormat.Field, their values are + * Integer objects indicating the index in the arguments + * array of the argument from which the text was generated. + *

    + * The attributes/value from the underlying Format + * instances that MessageFormat uses will also be + * placed in the resulting AttributedCharacterIterator. + * 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 arguments is null. + * @exception IllegalArgumentException if an argument in the + * arguments 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 attributes = it.getAttributes(); + if (attributes != null) { + for (Entry 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. + * + *

    Caveats: The parse may fail in a number of circumstances. + * For example: + *

      + *
    • If one of the arguments does not occur in the pattern. + *
    • If the format of an argument loses information, such as + * with a choice format where a large number formats to "many". + *
    • Does not yet handle recursion (where + * the substituted strings contain {n} references.) + *
    • 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"}. + *
    • If a single argument is parsed more than once in the string, + * then the later parse wins. + *
    + * 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. + *

    + * 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 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. + *

    + * See the {@link #parse(String, ParsePosition)} method for more information + * on message parsing. + * + * @param source A String whose beginning should be parsed. + * @return An Object 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. + * + *

    See the {@link #parse(String, ParsePosition)} method for more information on + * message parsing. + * + * @param source A String whose beginning should be parsed. + * @return A Map 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 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. + *

    + * The method attempts to parse text starting at the index given by + * pos. + * If parsing succeeds, then the index of pos 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 pos can be used to + * indicate the starting point for the next call to this method. + * If an error occurs, then the index of pos is not + * changed, the error index of pos is set to the index of + * the character where the error occurred, and null is returned. + *

    + * See the {@link #parse(String, ParsePosition)} method for more information + * on message parsing. + * + * @param source A String, part of which should be parsed. + * @param pos A ParsePosition object with index and error + * index information as described above. + * @return An Object parsed from the string, either an + * array of Object, or a Map, depending on whether named + * arguments are used. This can be queried using usesNamedArguments. + * In case of error, returns null. + * @throws NullPointerException if pos 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 + * AttributedCharacterIterator returned + * from MessageFormat.formatToCharacterIterator. + * + * @stable ICU 3.8 + */ + public static class Field extends Format.Field { + + private static final long serialVersionUID = 7510380454602616157L; + + /** + * Create a Field 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 formatToCharacterIterator. + * The value associated with the key will be an Integer + * indicating the index in the arguments 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. + * + *

    Note 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 new file mode 100644 index 00000000000..62f3202f043 --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/NumberFormat.java @@ -0,0 +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_} + * + * NumberFormat is the abstract base class for all number + * formats. This class provides the interface for formatting and parsing + * numbers. NumberFormat also provides methods for determining + * which locales have number formats, and what their names are. + * + * NumberFormat 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. + * + *

    + * To format a number for the current Locale, use one of the factory + * class methods: + *

    + *
    + *  myString = NumberFormat.getInstance().format(myNumber);
    + * 
    + *
    + * 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. + *
    + *
    + * NumberFormat nf = NumberFormat.getInstance();
    + * for (int i = 0; i < a.length; ++i) {
    + *     output.println(nf.format(myNumber[i]) + "; ");
    + * }
    + * 
    + *
    + * To format a number for a different Locale, specify it in the + * call to getInstance. + *
    + *
    + * NumberFormat nf = NumberFormat.getInstance(Locale.FRENCH);
    + * 
    + *
    + * You can also use a NumberFormat to parse numbers: + *
    + *
    + * myNumber = nf.parse(myString);
    + * 
    + *
    + * Use getInstance or getNumberInstance to get the + * normal number format. Use getIntegerInstance to get an + * integer number format. Use getCurrencyInstance to get the + * currency number format. And use getPercentInstance to get a + * format for displaying percentages. With this format, a fraction like + * 0.53 is displayed as 53%. + * + *

    + * 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". + * + * + *

    + * You can also control the display of numbers with such methods as + * setMinimumFractionDigits. + * If you want even more control over the format or parsing, + * or want to give your users more control, + * you can try casting the NumberFormat you get from the factory methods + * to a DecimalFormat. This will work for the vast majority + * of locales; just remember to put it in a try block in case you + * encounter an unusual one. + * + *

    + * 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, + *

    + * 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. + *

    + * You can also use forms of the parse and format + * methods with ParsePosition and FieldPosition to + * allow you to: + *

      + *
    • progressively parse through pieces of a string + *
    • align the decimal point and other areas + *
    + * For example, you can align numbers in two ways: + *
      + *
    1. If you are using a monospaced font with spacing for alignment, + * you can pass the FieldPosition in your format call, with + * field = INTEGER_FIELD. On output, + * getEndIndex 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. + * + *
    2. If you are using proportional fonts, + * instead of padding with spaces, measure the width + * of the string in pixels from the start to getEndIndex. + * 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. + *
    + * + *

    Synchronization

    + *

    + * 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. + *

    + * + *

    DecimalFormat

    + *

    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.

    + * + * 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 BigInteger + * and BigDecimal 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.#"):
      + *
    • Leading zeros
      + * '00', '0123' fail the parse, but '0' and '0.001' pass
    • + *
    • Leading or doubled grouping separators
      + * ',123' and '1,,234" fail
    • + *
    • Groups of incorrect length when grouping is used
      + * '1,23' and '1234,567' fail, but '1234' passes
    • + *
    • Grouping separators used in numbers followed by exponents
      + * '1,234E5' fails, but '1234E5' and '1,234E' pass ('E' is not an exponent when + * not followed by a number)
    • + *
    + * 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. + * + *

    Note: 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 MUST 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 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. + * Note: 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. + * Note: 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 Currency 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 Currency 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 UnsupportedOperationException. + * @return A rounding mode, between BigDecimal.ROUND_UP + * and BigDecimal.ROUND_UNNECESSARY. + * @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 UnsupportedOperationException. + * @param roundingMode A rounding mode, between + * BigDecimal.ROUND_UP and + * BigDecimal.ROUND_UNNECESSARY. + * @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. + *

    + * There is no public constructor to this class, the only instances are the + * constants defined here. + *

    + * @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 new file mode 100644 index 00000000000..71fcb59dda1 --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/RawCollationKey.java @@ -0,0 +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() {} +} 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 new file mode 100644 index 00000000000..befcaa6c762 --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/SimpleDateFormat.java @@ -0,0 +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_} + * + *

    SimpleDateFormat 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. + * + *

    + * SimpleDateFormat 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 + * getTimeInstance, getDateInstance, or + * getDateTimeInstance in DateFormat. 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 applyPattern methods as desired. + * For more information on using these methods, see + * {@link DateFormat}. + * + *

    + * Time Format Syntax: + *

    + * To specify the time format use a time pattern string. + * In this pattern, all ASCII letters are reserved as pattern letters, + * which are defined as the following: + *

    + *
    + * Symbol   Meaning                 Presentation        Example
    + * ------   -------                 ------------        -------
    + * G        era designator          (Text)              AD
    + * y†       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'
    + * 
    + *
    + * * These items are not supported by Java's SimpleDateFormat.
    + * ICU interprets a single 'y' differently than Java.

    + *

    + * The count of pattern letters determine the format. + *

    + * (Text): 4 or more pattern letters--use full form, + * < 4--use short or abbreviated form if one exists. + *

    + * (Number): 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. + *

    + * (Text & Number): 3 or over, use text, otherwise use number. + *

    + * 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. + *

    + * A pattern containing any invalid pattern letter will result in a thrown + * exception during formatting or parsing. + * + *

    + * Examples Using the US Locale: + *

    + *
    + * 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
    + * 
    + *
    + * Code Sample: + *
    + *
    + * 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);
    + * 
    + * // 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); + *
    + * // Parse the previous string back into a Date. + * ParsePosition pos = new ParsePosition(0); + * Date currentTime_2 = formatter.parse(dateString, pos); + *
    + *
    + * In the example, the time value currentTime_2 obtained from + * parsing will be equal to currentTime_1. 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. + * + *

    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. + * + *

    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. + * + *

    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. + * + *

    For time zones that have no names, use strings GMT+hours:minutes or + * GMT-hours:minutes. + * + *

    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. + * + *

    Synchronization

    + * + * 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. Note: 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. Note: 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. + * Note: 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. + * Note: 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 + * startDate to startDate + 100 years. + * @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. + *

    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 AttributedCharacterIterator 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 attributes = it.getAttributes(); + if (attributes != null) { + for (Entry 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 new file mode 100644 index 00000000000..9fc73a6f5dc --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/UFormat.java @@ -0,0 +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 getLocale() + * 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 en_US_CALIFORNIA, the actual data may be + * drawn from en (the actual locale), and + * en_US may be the most specific locale that exists (the + * valid locale). + * + *

    Note: This method will be implemented in ICU 3.0; ICU 2.8 + * contains a partial preview implementation. The actual + * locale is returned correctly, but the valid 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 type, 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 new file mode 100644 index 00000000000..1092ba99685 --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/text/UnicodeSet.java @@ -0,0 +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() {} +} 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 new file mode 100644 index 00000000000..739a040d8b6 --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/Calendar.java @@ -0,0 +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_} + * + *

    Calendar is an abstract base class for converting between + * a Date object and a set of integer fields such as + * YEAR, MONTH, DAY, HOUR, + * and so on. (A Date object represents a specific instant in + * time with millisecond precision. See + * {@link Date} + * for information about the Date class.) + * + *

    Subclasses of Calendar interpret a Date + * according to the rules of a specific calendar system. ICU4J contains + * several subclasses implementing different international calendar systems. + * + *

    + * Like other locale-sensitive classes, Calendar provides a + * class method, getInstance, for getting a generally useful + * object of this type. Calendar's getInstance method + * returns a calendar of a type appropriate to the locale, whose + * time fields have been initialized with the current date and time: + *

    + *
    Calendar rightNow = Calendar.getInstance()
    + *
    + * + *

    When a ULocale is used by getInstance, its + * 'calendar' 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:

    + *
    Calendar cal = Calendar.getInstance(new ULocale("en_US@calendar=japanese"));
    + *
    will return an instance of JapaneseCalendar (using en_US conventions for + * minimum days in first week, start day of week, et cetera). + * + *

    A Calendar 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). + * Calendar defines the range of values returned by certain fields, + * as well as their meaning. For example, the first month of the year has value + * MONTH == JANUARY for all calendars. Other values + * are defined by the concrete subclass, such as ERA and + * YEAR. See individual field documentation and subclass + * documentation for details. + * + *

    When a Calendar is lenient, it accepts a wider range + * of field values than it produces. For example, a lenient + * GregorianCalendar interprets MONTH == + * JANUARY, DAY_OF_MONTH == 32 as February 1. A + * non-lenient GregorianCalendar throws an exception when given + * out-of-range field settings. When calendars recompute field values for + * return by get(), they normalize them. For example, a + * GregorianCalendar always produces DAY_OF_MONTH + * values between 1 and the length of the month. + * + *

    Calendar 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 + * Calendar is constructed. They may also be specified explicitly + * through the API. + * + *

    When setting or getting the WEEK_OF_MONTH or + * WEEK_OF_YEAR fields, Calendar 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 + * getFirstDayOfWeek() and containing at least + * getMinimalDaysInFirstWeek() 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 get() may be + * different. For example, a specific Calendar subclass may + * designate the week before week 1 of a year as week n of the previous + * year. + * + *

    When computing a Date from time fields, two special + * circumstances may arise: there may be insufficient information to compute the + * Date (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). + * + *

    Insufficient information. 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. + * + *

    Inconsistent information. 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. + * + *

    + *
    + * 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
    + *
    + * + * For the time of day: + * + *
    + *
    + * HOUR_OF_DAY
    + * AM_PM + HOUR
    + *
    + * + *

    Note: 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 and day-of-week in some cases. + * + *

    Note: There are certain possible ambiguities in + * interpretation of certain singular times, which are resolved in the + * following ways: + *

      + *
    1. 24:00:00 "belongs" to the following day. That is, + * 23:59 on Dec 31, 1969 < 24:00 on Jan 1, 1970 < 24:01:00 on Jan 1, 1970 + * + *
    2. Although historically not precise, midnight also belongs to "am", + * and noon belongs to "pm", so on the same day, + * 12:00 am (midnight) < 12:01 am, and 12:00 pm (noon) < 12:01 pm + *
    + * + *

    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. + * + *

    Field manipulation methods

    + * + *

    Calendar fields can be changed using three methods: + * set(), add(), and roll().

    + * + *

    set(f, value) changes field + * f to value. In addition, it sets an + * internal member variable to indicate that field f has + * been changed. Although field f is changed immediately, + * the calendar's milliseconds is not recomputed until the next call to + * get(), getTime(), or + * getTimeInMillis() is made. Thus, multiple calls to + * set() do not trigger multiple, unnecessary + * computations. As a result of changing a field using + * set(), other fields may also change, depending on the + * field, the field value, and the calendar system. In addition, + * get(f) will not necessarily return value + * after the fields have been recomputed. The specifics are determined by + * the concrete calendar class.

    + * + *

    Example: Consider a GregorianCalendar + * originally set to August 31, 1999. Calling set(Calendar.MONTH, + * Calendar.SEPTEMBER) sets the calendar to September 31, + * 1999. This is a temporary internal representation that resolves to + * October 1, 1999 if getTime()is then called. However, a + * call to set(Calendar.DAY_OF_MONTH, 30) before the call to + * getTime() sets the calendar to September 30, 1999, since + * no recomputation occurs after set() itself.

    + * + *

    add(f, delta) adds delta + * to field f. This is equivalent to calling set(f, + * get(f) + delta) with two adjustments:

    + * + *
    + *

    Add rule 1. The value of field f + * after the call minus the value of field f before the + * call is delta, modulo any overflow that has occurred in + * field f. 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.

    + * + *

    Add rule 2. If a smaller field is expected to be + * invariant, but   it is impossible for it to be equal to its + * prior value because of changes in its minimum or maximum after field + * f 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. HOUR is a smaller field than + * DAY_OF_MONTH. 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.

    + *
    + * + *

    In addition, unlike set(), add() forces + * an immediate recomputation of the calendar's milliseconds and all + * fields.

    + * + *

    Example: Consider a GregorianCalendar + * originally set to August 31, 1999. Calling add(Calendar.MONTH, + * 13) sets the calendar to September 30, 2000. Add rule + * 1 sets the MONTH field to September, since + * adding 13 months to August gives September of the next year. Since + * DAY_OF_MONTH cannot be 31 in September in a + * GregorianCalendar, add rule 2 sets the + * DAY_OF_MONTH to 30, the closest possible value. Although + * it is a smaller field, DAY_OF_WEEK is not adjusted by + * rule 2, since it is expected to change when the month changes in a + * GregorianCalendar.

    + * + *

    roll(f, delta) adds + * delta to field f without changing larger + * fields. This is equivalent to calling add(f, delta) with + * the following adjustment:

    + * + *
    + *

    Roll rule. Larger fields are unchanged after the + * call. A larger field represents a larger unit of + * time. DAY_OF_MONTH is a larger field than + * HOUR.

    + *
    + * + *

    Example: Consider a GregorianCalendar + * originally set to August 31, 1999. Calling roll(Calendar.MONTH, + * 8) sets the calendar to April 30, 1999. Add + * rule 1 sets the MONTH field to April. Using a + * GregorianCalendar, the DAY_OF_MONTH cannot + * be 31 in the month April. Add rule 2 sets it to the closest possible + * value, 30. Finally, the roll rule maintains the + * YEAR field value of 1999.

    + * + *

    Example: Consider a GregorianCalendar + * originally set to Sunday June 6, 1999. Calling + * roll(Calendar.WEEK_OF_MONTH, -1) sets the calendar to + * Tuesday June 1, 1999, whereas calling + * add(Calendar.WEEK_OF_MONTH, -1) sets the calendar to + * Sunday May 30, 1999. This is because the roll rule imposes an + * additional constraint: The MONTH must not change when the + * WEEK_OF_MONTH 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 DAY_OF_WEEK, an invariant + * when changing the WEEK_OF_MONTH, is set to Tuesday, the + * closest possible value to Sunday (where Sunday is the first day of the + * week).

    + * + *

    Usage model. To motivate the behavior of + * add() and roll(), consider a user interface + * component with increment and decrement buttons for the month, day, and + * year, and an underlying GregorianCalendar. If the + * interface reads January 31, 1999 and the user presses the month + * increment button, what should it read? If the underlying + * implementation uses set(), 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 + * add() or roll(), depending on whether larger + * fields should be affected, the user interface can behave as most users + * will intuitively expect.

    + * + *

    Note: You should always use {@link #roll roll} and {@link #add add} rather + * than attempting to perform arithmetic operations directly on the fields + * of a Calendar. It is quite possible for Calendar subclasses + * to have fields with non-linear behavior, for example missing months + * or days during non-leap years. The subclasses' add and roll + * methods will take this into account, while simple arithmetic manipulations + * may give invalid results. + * + *

    Calendar Architecture in ICU4J

    + * + *

    Recently the implementation of Calendar has changed + * significantly in order to better support subclassing. The original + * Calendar class was designed to support subclassing, but + * it had only one implemented subclass, GregorianCalendar. + * With the implementation of several new calendar subclasses, including + * the BuddhistCalendar, ChineseCalendar, + * HebrewCalendar, IslamicCalendar, and + * JapaneseCalendar, the subclassing API has been reworked + * thoroughly. This section details the new subclassing API and other + * ways in which com.ibm.icu.util.Calendar differs from + * java.util.Calendar. + *

    + * + *

    Changes

    + * + *

    Overview of changes between the classic Calendar + * architecture and the new architecture. + * + *

      + * + *
    • The fields[] array is private now + * instead of protected. Subclasses must access it + * using the methods {@link #internalSet} and + * {@link #internalGet}. Motivation: Subclasses should + * not directly access data members.
    • + * + *
    • The time long word is private now + * instead of protected. Subclasses may access it using + * the method {@link #internalGetTimeInMillis}, which does not + * provoke an update. Motivation: Subclasses should not + * directly access data members.
    • + * + *
    • The scope of responsibility of subclasses has been drastically + * reduced. As much functionality as possible is implemented in the + * Calendar base class. As a result, it is much easier + * to subclass Calendar. Motivation: 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.
    • + * + *
    • The subclassing API has been completely redesigned.
    • + * + *
    • The Calendar base class contains some Gregorian + * calendar algorithmic support that subclasses can use (specifically + * in {@link #handleComputeFields}). Subclasses can use the + * methods getGregorianXxx() to obtain precomputed + * values. Motivation: This is required by all + * Calendar subclasses in order to implement consistent + * time zone behavior, and Gregorian-derived systems can use the + * already computed data.
    • + * + *
    • The FIELD_COUNT constant has been removed. Use + * {@link #getFieldCount}. In addition, framework API has been + * added to allow subclasses to define additional fields. + * Motivation: The number of fields is not constant across + * calendar systems.
    • + * + *
    • 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 + * Date(Long.MIN_VALUE) or + * Date(Long.MAX_VALUE). Instead, the + * Calendar protected constants should be used. + * Motivation: With + * the addition of the {@link #JULIAN_DAY} field, Julian day + * numbers must be restricted to a 32-bit int. 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 Long.MIN_VALUE and + * Long.MAX_VALUE.
    • + * + *
    • 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.
    • + * + *
    • Subclasses can access protected millisecond constants + * defined in Calendar.
    • + * + *
    • New API has been added to support calendar-specific subclasses + * of DateFormat.
    • + * + *
    • Several subclasses have been implemented, representing + * various international calendar systems.
    • + * + *
    + * + *

    Subclass API

    + * + *

    The original Calendar API was based on the experience + * of implementing a only a single subclass, + * GregorianCalendar. 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 fields and + * stamp. Instead, they have new API to access + * these. Subclasses are able to allocate the fields array + * through a protected framework method; this allows subclasses to + * specify additional fields.

    + * + *

    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) All calendars require basic + * Gregorian support in order to handle timezone computations.

    + * + *

    Common computations have been moved into + * Calendar. Subclasses no longer compute the week related + * fields and the time related fields. These are commonly handled for all + * calendars by the base class.

    + * + *

    Subclass computation of time => fields + * + *

    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 Calendar. + * + *

      + * + *
    • 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 Calendar, + * 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 + * Calendar implements a proleptic Gregorian + * calendar. Within this method, subclasses may call + * getGregorianXxx() to obtain the Gregorian calendar + * month, day of month, and extended year for the given date.
    • + * + *
    + * + *

    Subclass computation of fields => time + * + *

    The interpretation of most field values is handled entirely by + * Calendar. Calendar determines which fields + * are set, which are not, which are set more recently, and so on. In + * addition, Calendar 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. + * + *

      + * + *
    • 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}.
    • + * + *
    • 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.
    • + * + *
    + * + *

    Other methods + * + *

      + * + *
    • 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.
    • + * + *
    • Subclasses should implement {@link #handleGetYearLength} + * to return the number of days in the given + * extended year. This method is used by + * computeWeekFields to compute the + * {@link #WEEK_OF_YEAR} and {@link #YEAR_WOY} fields.
    • + * + *
    • Subclasses should implement {@link #handleGetLimit} + * to return the protected values of a field, depending on the value of + * limitType. 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.
    • + * + *
    • 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 + * IllegalArgumentException. The method may call + * super.validateField(field) to handle fields in a + * generic way, that is, to compare them to the range + * getMinimum(field)..getMaximum(field).
    • + * + *
    • Optionally, subclasses may override + * {@link #handleCreateFields} to create an int[] + * array large enough to hold the calendar's fields. This is only + * necessary if the calendar defines additional fields beyond those + * defined by Calendar. The length of the result must be + * be between the base and maximum field counts.
    • + * + *
    • Optionally, subclasses may override + * {@link #handleGetDateFormat} to create a + * DateFormat 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.
    • + * + *
    • 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 "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} 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.
    • + * + *
    + * + *

    Normalized behavior + * + *

    The behavior of certain fields has been made consistent across all + * calendar systems and implemented in Calendar. + * + *

      + * + *
    • Time is normalized. Even though some calendar systems transition + * between days at sunset or at other times, all ICU4J calendars + * transition between days at local zone midnight. This + * allows ICU4J to centralize the time computations in + * Calendar 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}.
    • + * + *
    • DST behavior is normalized. Daylight savings time behavior is + * computed the same for all calendar systems, and depends on the + * value of several GregorianCalendar fields: the + * {@link #YEAR}, {@link #MONTH}, and + * {@link #DAY_OF_MONTH}. As a result, Calendar + * always computes these fields, even for non-Gregorian calendar + * systems. These fields are available to subclasses.
    • + * + *
    • 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}, WEEK_OF_YEAR, + * WEEK_OF_MONTH, {@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.
    • + * + *
    + * + *

    Supported range + * + *

    The allowable range of Calendar has been + * narrowed. GregorianCalendar used to attempt to support + * the range of dates with millisecond values from + * Long.MIN_VALUE to Long.MAX_VALUE. This + * introduced awkward constructions (hacks) which slowed down + * performance. It also introduced non-uniform behavior at the + * boundaries. The new Calendar protocol specifies the + * maximum range of supportable dates as those having Julian day numbers + * of -0x7F000000 to +0x7F000000. This + * corresponds to years from ~5,000,000 BCE to ~5,000,000 CE. Programmers + * should use the protected constants in Calendar to + * specify an extremely early or extremely late date.

    + * + *

    General notes + * + *

      + * + *
    • Calendars implementations are proleptic. For example, + * even though the Gregorian calendar was not instituted until the + * 16th century, the GregorianCalendar class supports + * dates before the historical onset of the calendar by extending the + * calendar system backward in time. Similarly, the + * HebrewCalendar 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.
    • + * + *
    • Calendar system subclasses compute a extended + * year. 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 + * ERA==AD ? YEAR : 1-YEAR. Another example is the Mayan + * long count, which has years (KUN) and nested cycles + * of years (KATUN and BAKTUN). The Mayan + * {@link #EXTENDED_YEAR} is computed as TUN + 20 * (KATUN + * + 20 * BAKTUN). The Calendar base class uses + * the {@link #EXTENDED_YEAR} field to compute the week-related + * fields.
    • + * + *
    + * + * @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 { + 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 get and set 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 get and set 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 get and set indicating the + * month. This is a calendar-specific value. The first month of the year is + * JANUARY; 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 get and set 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 get and set 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 get and set 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 get and set 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 get and set 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 get and set 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 get and set 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 not depend on + * {@link #getFirstDayOfWeek()} or + * {@link #getMinimalDaysInFirstWeek()}. DAY_OF_MONTH 1 + * through 7 always correspond to DAY_OF_WEEK_IN_MONTH + * 1; 8 through 15 correspond to + * DAY_OF_WEEK_IN_MONTH 2, and so on. + * DAY_OF_WEEK_IN_MONTH 0 indicates the week before + * DAY_OF_WEEK_IN_MONTH 1. Negative values count back from the + * end of the month, so the last Sunday of a month is specified as + * DAY_OF_WEEK = SUNDAY, DAY_OF_WEEK_IN_MONTH = -1. 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, DAY_OF_WEEK_IN_MONTH -1 will overlap + * DAY_OF_WEEK_IN_MONTH 5 and the end of 4. + * @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 get and set indicating + * whether the HOUR is before or after noon. + * E.g., at 10:04:15.250 PM the AM_PM is PM. + * @see #AM + * @see #PM + * @see #HOUR + * @stable ICU 2.0 + */ + public final static int AM_PM = 9; + + /** + * Field number for get and set indicating the + * hour of the morning or afternoon. HOUR is used for the 12-hour + * clock. + * E.g., at 10:04:15.250 PM the HOUR is 10. + * @see #AM_PM + * @see #HOUR_OF_DAY + * @stable ICU 2.0 + */ + public final static int HOUR = 10; + + /** + * Field number for get and set indicating the + * hour of the day. HOUR_OF_DAY is used for the 24-hour clock. + * E.g., at 10:04:15.250 PM the HOUR_OF_DAY is 22. + * @see #HOUR + * @stable ICU 2.0 + */ + public final static int HOUR_OF_DAY = 11; + + /** + * Field number for get and set indicating the + * minute within the hour. + * E.g., at 10:04:15.250 PM the MINUTE is 4. + * @stable ICU 2.0 + */ + public final static int MINUTE = 12; + + /** + * Field number for get and set indicating the + * second within the minute. + * E.g., at 10:04:15.250 PM the SECOND is 15. + * @stable ICU 2.0 + */ + public final static int SECOND = 13; + + /** + * Field number for get and set indicating the + * millisecond within the second. + * E.g., at 10:04:15.250 PM the MILLISECOND is 250. + * @stable ICU 2.0 + */ + public final static int MILLISECOND = 14; + + /** + * Field number for get and set indicating the + * raw offset from GMT in milliseconds. + * @stable ICU 2.0 + */ + public final static int ZONE_OFFSET = 15; + + /** + * Field number for get and set indicating the + * daylight savings offset in milliseconds. + * @stable ICU 2.0 + */ + public final static int DST_OFFSET = 16; + + /** + * {@icu} Field number for get() and set() + * 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 get() and set() + * 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 get() and set() + * 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 get() and set() + * 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 get() and set() + * indicating the milliseconds in the day. This ranges from 0 to + * 23:59:59.999 (regardless of DST). This field behaves + * exactly 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 DAY_OF_WEEK field indicating + * Sunday. + * @stable ICU 2.0 + */ + public final static int SUNDAY = 1; + + /** + * Value of the DAY_OF_WEEK field indicating + * Monday. + * @stable ICU 2.0 + */ + public final static int MONDAY = 2; + + /** + * Value of the DAY_OF_WEEK field indicating + * Tuesday. + * @stable ICU 2.0 + */ + public final static int TUESDAY = 3; + + /** + * Value of the DAY_OF_WEEK field indicating + * Wednesday. + * @stable ICU 2.0 + */ + public final static int WEDNESDAY = 4; + + /** + * Value of the DAY_OF_WEEK field indicating + * Thursday. + * @stable ICU 2.0 + */ + public final static int THURSDAY = 5; + + /** + * Value of the DAY_OF_WEEK field indicating + * Friday. + * @stable ICU 2.0 + */ + public final static int FRIDAY = 6; + + /** + * Value of the DAY_OF_WEEK field indicating + * Saturday. + * @stable ICU 2.0 + */ + public final static int SATURDAY = 7; + + /** + * Value of the MONTH field indicating the + * first month of the year. + * @stable ICU 2.0 + */ + public final static int JANUARY = 0; + + /** + * Value of the MONTH field indicating the + * second month of the year. + * @stable ICU 2.0 + */ + public final static int FEBRUARY = 1; + + /** + * Value of the MONTH field indicating the + * third month of the year. + * @stable ICU 2.0 + */ + public final static int MARCH = 2; + + /** + * Value of the MONTH field indicating the + * fourth month of the year. + * @stable ICU 2.0 + */ + public final static int APRIL = 3; + + /** + * Value of the MONTH field indicating the + * fifth month of the year. + * @stable ICU 2.0 + */ + public final static int MAY = 4; + + /** + * Value of the MONTH field indicating the + * sixth month of the year. + * @stable ICU 2.0 + */ + public final static int JUNE = 5; + + /** + * Value of the MONTH field indicating the + * seventh month of the year. + * @stable ICU 2.0 + */ + public final static int JULY = 6; + + /** + * Value of the MONTH field indicating the + * eighth month of the year. + * @stable ICU 2.0 + */ + public final static int AUGUST = 7; + + /** + * Value of the MONTH field indicating the + * ninth month of the year. + * @stable ICU 2.0 + */ + public final static int SEPTEMBER = 8; + + /** + * Value of the MONTH field indicating the + * tenth month of the year. + * @stable ICU 2.0 + */ + public final static int OCTOBER = 9; + + /** + * Value of the MONTH field indicating the + * eleventh month of the year. + * @stable ICU 2.0 + */ + public final static int NOVEMBER = 10; + + /** + * Value of the MONTH field indicating the + * twelfth month of the year. + * @stable ICU 2.0 + */ + public final static int DECEMBER = 11; + + /** + * Value of the MONTH 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 AM_PM 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 AM_PM 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. + * + *

    Note: Calling setTime with + * Date(Long.MAX_VALUE) or Date(Long.MIN_VALUE) + * 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 true if and only if the argument is + * not null and is a Calendar object that + * represents the same calendar as this object. + * @param obj the object to compare with. + * @return true if the objects are the same; + * false 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. + * + *

    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. + *

    + * 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 getActualMinimum(WEEK_OF_MONTH) will return 1. However, + * if the first of the month is a Thursday, Friday, or Saturday, there are + * not four days in that week, so it is week number 0, and + * getActualMinimum(WEEK_OF_MONTH) will return 0. + *

    + * @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: + *

    + * roll({@link #DATE}, true) + *

    + * 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}). + *

    + * When rolling on certain fields, the values of other fields may conflict and + * need to be changed. For example, when rolling the MONTH field + * for the Gregorian date 1/31/96 upward, the DAY_OF_MONTH field + * must be adjusted so that the result is 2/29/96 rather than the invalid + * 2/31/96. + *

    + * Note: Calling roll(field, true) N times is not + * necessarily equivalent to calling roll(field, N). For example, + * imagine that you start with the date Gregorian date January 31, 1995. If you call + * roll(Calendar.MONTH, 2), the result will be March 31, 1995. + * But if you call roll(Calendar.MONTH, true), the result will be + * February 28, 1995. Calling it one more time will give March 28, 1995, which + * is usually not the desired result. + *

    + * Note: You should always use roll and add rather + * than attempting to perform arithmetic operations directly on the fields + * of a Calendar. It is quite possible for Calendar subclasses + * to have fields with non-linear behavior, for example missing months + * or days during non-leap years. The subclasses' add and roll + * methods will take this into account, while simple arithmetic manipulations + * may give invalid results. + *

    + * @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 true if rolling up, + * false 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 + * roll(Calendar.DATE, 3). If the + * field is rolled past its maximum allowable value, it will "wrap" back + * to its minimum and continue rolling. + * For example, calling roll(Calendar.DATE, 10) + * on a Gregorian calendar set to 4/25/96 will result in the date 4/5/96. + *

    + * 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. + *

    + * {@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 roll. + *

    + * Note: You should always use roll and add rather + * than attempting to perform arithmetic operations directly on the fields + * of a Calendar. It is quite possible for Calendar subclasses + * to have fields with non-linear behavior, for example missing months + * or days during non-leap years. The subclasses' add and roll + * methods will take this into account, while simple arithmetic manipulations + * may give invalid results. + *

    + * Subclassing:
    + * This implementation of roll 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. + *

    + * Subclasses that have fields for which the assumption of continuity breaks + * down must overide roll 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. + *

    + * @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 + * add(Calendar.DATE, 3). + *

    + * 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. + *

    + * {@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 add. + *

    + * Note: You should always use roll and add rather + * than attempting to perform arithmetic operations directly on the fields + * of a Calendar. It is quite possible for Calendar subclasses + * to have fields with non-linear behavior, for example missing months + * or days during non-leap years. The subclasses' add and roll + * methods will take this into account, while simple arithmetic manipulations + * may give invalid results. + *

    + * Subclassing:
    + * This implementation of add 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. + *

    + * Subclasses that have fields for which this assumption of continuity breaks + * down must overide add 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. + *

    + * @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 + * Calendar objects. + * + * @param that the Calendar to compare to this. + * @return 0 if the time represented by + * this Calendar is equal to the time represented + * by that Calendar, a value less than + * 0 if the time represented by this is before + * the time represented by that, and a value greater than + * 0 if the time represented by this + * is after the time represented by that. + * @throws NullPointerException if that + * Calendar is null. + * @throws IllegalArgumentException if the time of that + * Calendar 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 DateFormat 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 DateFormat 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 + * before the given time, the returned value will be + * positive. If this calendar is set after the given + * time, the returned value will be negative. The + * field parameter specifies the units of the return + * value. For example, if fieldDifference(when, + * Calendar.MONTH) returns 3, then this calendar is set to + * 3 months before when, and possibly some additional + * time less than one month. + * + *

    As a side effect of this call, this calendar is advanced + * toward when by the given amount. That is, calling + * this method has the side effect of calling add(field, + * n), where n is the return value. + * + *

    Usage: To use this method, call it first with the largest + * field of interest, then with progressively smaller fields. For + * example: + * + *

    +     * int y = cal.fieldDifference(when, Calendar.YEAR);
    +     * int m = cal.fieldDifference(when, Calendar.MONTH);
    +     * int d = cal.fieldDifference(when, Calendar.DATE);
    + * + * computes the difference between cal and + * when in years, months, and days. + * + *

    Note: fieldDifference() is + * asymmetrical. That is, in the following code: + * + *

    +     * 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);
    + * + * one might expect that m1 == -m2 && d1 == -d2. + * 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 when, in terms of + * field. + * @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 null. + * + * @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 set() and get() are + * 0..getFieldCount()-1. + * @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 en_US_CALIFORNIA, the actual data may be + * drawn from en (the actual locale), and + * en_US may be the most specific locale that exists (the + * valid locale). + * + *

    Note: This method will be implemented in ICU 3.0; ICU 2.8 + * contains a partial preview implementation. The * actual + * locale is returned correctly, but the valid 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 type, 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 new file mode 100644 index 00000000000..bac782055f6 --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/Currency.java @@ -0,0 +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 + * Currency object can be created given a Locale or + * given an ISO 4217 code. Once created, the Currency object + * can return various data necessary to its proper display: + * + *

    • A display symbol, for a specific locale + *
    • The number of fraction digits to display + *
    • A rounding increment + *
    + * + * The DecimalFormat class uses these data to display + * currencies. + * + *

    Note: This class deliberately resembles + * java.util.Currency 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 theISOCode is null. + * @throws IllegalArgumentException if theISOCode 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. + *

    + * The only supported key is "currency", other values return an empty array. + *

    + * 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. + *

    + * 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 + * Unicode TR#35 Sec. C1. + * 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. Note: + * 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 + * 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. Note: + * 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 en_US_CALIFORNIA, the actual data may be + * drawn from en (the actual locale), and + * en_US may be the most specific locale that exists (the + * valid locale). + * + *

    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 type, 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 new file mode 100644 index 00000000000..22b32391339 --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/CurrencyAmount.java @@ -0,0 +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() {} +} 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 new file mode 100644 index 00000000000..f775d29a276 --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/TimeZone.java @@ -0,0 +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_} + * + *

    TimeZone represents a time zone offset, and also computes daylight + * savings. + * + *

    Typically, you get a TimeZone using {@link #getDefault()} + * which creates a TimeZone based on the time zone where the program + * is running. For example, for a program running in Japan, getDefault + * creates a TimeZone object based on Japanese Standard Time. + * + *

    You can also get a TimeZone 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 TimeZone object with: + * + *

    + *
    + * TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
    + * 
    + *
    + * 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 TimeZone. + * 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: + * + *
    + *
    + * GMT[+|-]hh[[:]mm]
    + * 
    + *
    + * + * For example, you might specify GMT+14:00 as a custom + * time zone ID. The TimeZone that is returned + * when you specify a custom time zone ID does not include + * daylight savings time. + * + *

    For compatibility with JDK 1.1.x, some other three-letter time zone IDs + * (such as "PST", "CTT", "AST") are also supported. However, their + * use is deprecated 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. + * + *

    Note: Starting from ICU4J 4.0, you can optionally choose + * JDK TimeZone as the time zone implementation. The TimeZone factory + * method getTimeZone creates an instance of ICU's own TimeZone + * 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 + * setDefaultTimeZoneType. Alternatively, you can change the initial + * default implementation type by setting a property below. + * + *

    + *
    + * #
    + * # The default TimeZone implementation type used by the ICU TimeZone
    + * # factory method. [ ICU | JDK ]
    + * #
    + * com.ibm.icu.util.TimeZone.DefaultTimeZoneType = ICU
    + * 
    + *
    + * + *

    This property is included in ICUConfig.properties in com.ibm.icu package. When the + * TimeZone class is loaded, the initialization code checks if the property + * com.ibm.icu.util.TimeZone.DefaultTimeZoneType=xxx 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 + * setDefaultTimeZoneType 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 + * getTimeZone, setDefaultTimeZoneType + * and getDefaultTimeZoneType. + * @stable ICU 4.0 + */ + public static final int TIMEZONE_ICU = 0; + /** + * {@icu} A time zone implementation type indicating JDK TimeZone used by + * getTimeZone, setDefaultTimeZoneType + * and getDefaultTimeZoneType. + * @stable ICU 4.0 + */ + public static final int TIMEZONE_JDK = 1; + + /** + * A style specifier for getDisplayName() indicating + * a short name, such as "PST." + * @see #LONG + * @stable ICU 2.0 + */ + public static final int SHORT = 0; + + /** + * A style specifier for getDisplayName() 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 getDisplayName() 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 getDisplayName() 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 getDisplayName() 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 getDisplayName() 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 getDisplayName() 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 getDisplayName() 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 standard 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 + * GMT[+-]hh:mm. + * @param daylight if true, return the daylight savings name. + * @param style the output style of the display name. Valid styles are + * SHORT, LONG, SHORT_GENERIC, + * LONG_GENERIC, SHORT_GMT, LONG_GMT, + * SHORT_COMMONLY_USED or GENERIC_LOCATION. + * @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 + * GMT[+-]hh:mm. + * @param daylight if true, return the daylight savings name. + * @param style the output style of the display name. Valid styles are + * SHORT, LONG, SHORT_GENERIC, + * LONG_GENERIC, SHORT_GMT, LONG_GMT, + * SHORT_COMMONLY_USED or GENERIC_LOCATION. + * @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 + * GMT[+-]hh:mm. + * @param daylight if true, return the daylight savings name. + * @param style the output style of the display name. Valid styles are + * SHORT, LONG, SHORT_GENERIC, + * LONG_GENERIC, SHORT_GMT, LONG_GMT, + * SHORT_COMMONLY_USED or GENERIC_LOCATION. + * @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. + *

    + * The default implementation always returns 3600000 milliseconds + * (i.e., one hour) if this time zone observes Daylight Saving + * Time. Otherwise, 0 (zero) is returned. + *

    + * 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 TimeZone for the given ID. + * + * @param ID the ID for a TimeZone, 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 TimeZone, 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 TimeZone for the given ID and the timezone type. + * @param ID the ID for a TimeZone, 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 TIMEZONE_ICU or + * TIMEZONE_JDK. + * @return the specified TimeZone, 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 getTimeZone. + * @param type time zone type, either TIMEZONE_ICU or + * TIMEZONE_JDK. + * @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 TIMEZONE_ICU or + * TIMEZONE_JDK. + * @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 + * get() 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 + * get() to construct the corresponding TimeZone + * object. + * @param country a two-letter ISO 3166 country code, or null + * 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 + * get() 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. + * + *

    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. + * + *

    The given index must be in the range 0..n-1, where n is the + * value returned by countEquivalentIDs(id). 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 countEquivalentIDs(id) + * @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 TimeZone for this host. + * The source of the default TimeZone + * may vary with implementation. + * @return a default TimeZone. + * @stable ICU 2.0 + */ + public static TimeZone getDefault() { + return new TimeZone(java.util.TimeZone.getDefault()); + } + + /** + * Sets the TimeZone that is + * returned by the getDefault method. If zone + * 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 TimeZone 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 isSystemID[0] + * @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 new file mode 100644 index 00000000000..7ffd3222221 --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/ULocale.java @@ -0,0 +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. + * + *

    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 requested + * 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 valid locale). Furthermore, + * even when a populated locale is found (the valid locale), + * further fallback may be required to reach a locale containing the + * specific data required by the service (the actual locale). + * + *

    ULocale performs 'normalization' and 'canonicalization' of locale ids. + * Normalization 'cleans up' ICU locale ids as follows: + *

      + *
    • language, script, country, variant, and keywords are properly cased
      + * (lower, title, upper, upper, and lower case respectively)
    • + *
    • hyphens used as separators are converted to underscores
    • + *
    • three-letter language and country ids are converted to two-letter + * equivalents where available
    • + *
    • surrounding spaces are removed from keywords and values
    • + *
    • if there are multiple keywords, they are put in sorted order
    • + *
    + * Canonicalization additionally performs the following: + *
      + *
    • POSIX ids are converted to ICU format IDs
    • + *
    • 'grandfathered' 3066 ids are converted to ICU standard form
    • + *
    • '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). + *
    + * All ULocale constructors automatically normalize the locale id. To handle + * POSIX ids, canonicalize can be called to convert the id + * to canonical form, or the canonicalInstance factory method + * can be called.

    + * + *

    This class provides selectors {@link #VALID_LOCALE} and {@link + * #ACTUAL_LOCALE} intended for use in methods named + * getLocale(). 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}, + * Collator, + * {@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, + * getLocale() may be called on it to determine the valid and + * actual locale arrived at during the object's construction. + * + *

    Note: The actual locale is returned correctly, but the valid + * 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 CACHE = new SimpleCache(); + + /** + * 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 with + * /, the ICU locale is mapped to 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 = { + // { , , , , + { "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(';'). + * + *

    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 ULocale(String + * localeID). + * + *

    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 nameCache = new SimpleCache(); + /** + * 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 + * checkPermission method doesn't allow the operation. + * @throws NullPointerException if newLocale 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 ULocale, + * not Locale. 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 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 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 + * ftp://dkuug.dk/i18n/iso-639-2.txt + * @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 + * ftp://dkuug.dk/i18n/iso-639-2.txt + * @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 getLocale() 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 null. + * + * @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 getLocale() 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 null. + * + *

    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 getLocale(). + * @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 { + 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 map = + new TreeMap(); + 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:

    + * + * http://www.unicode.org/reports/tr35/#Likely_Subtags
    + * + * If the provided ULocale instance is already in the minimal form, or there + * is no data available for minimization, it will be returned. Since the + * minimization algorithm relies on proper maximization, see the comments + * for addLikelySubtags for reasons why there might not be any data. + * + * Examples:
    +     *
    +     * "en_Latn_US" minimizes to "en"
    +     *
    +     * "de_Latn_US" minimizes to "de"
    +     *
    +     * "sr_Cyrl_RS" minimizes to "sr"
    +     *
    +     * "zh_Hant_TW" minimizes to "zh_TW" (The region is preferred to the
    +     * script, and minimizing to "zh" would imply "zh_Hans_CN".) 
    + * + * @param loc The ULocale to minimize + * @return The minimized ULocale instance. + * @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 [0-9A-Za-z]. 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 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 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. + * + *

    + * If this ULocale 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: + *

    + * Language: If language is empty or ill-formed (for example "a" or "e2"), + * it will be emitted as "und" (Undetermined). + *

    + * Country: If country is ill-formed (for example "12" or "USA"), it + * will be omitted. + *

    + * Variant: 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: + *

      + *
    • 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. + *
    • 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".
    • + *
    + * + *

    Note: 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, + *

    +     *   new ULocale("xx_YY").toLanguageTag();
    +     * 
    + * will return "xx-YY", but the language subtag "xx" and the region subtag "YY" + * are invalid because they are not registered in the + * + * IANA Language Subtag Registry. + * + * @return a BCP47 language tag representing the locale + * @see #forLanguageTag(String) + * + * @draft ICU 4.2 + * @provisional This API might change or be removed in a future release. + */ + public String toLanguageTag() { + 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. + * + *

    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. + * + *

    For a list of grandfathered tags, see the + * + * IANA Language Subtag Registry. + * + *

    Notes: This method converts private use subtags prefixed + * by "variant" to variant field in the result locale. For example, + * the code below will return "POSIX". + *

    +     *   ULocale.forLanguageTag("en-US-x-variant-posix).getVariant();
    +     * 
    + * + * @param languageTag the language tag + * @return the locale that best represents the language tag + * @exception NullPointerException if languageTag is null + * @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"); + } + + + /** + * Builder is used to build instances of ULocale + * from values configured by the setter. Unlike the ULocale + * constructors, the Builder checks if a value configured by a + * setter satisfies the syntactical requirements defined by the ULocale + * class. A ULocale object created by a Builder is + * well-formed and can be transformed to a well-formed IETF BCP 47 language tag + * without losing information. + * + *

    + * Note: The ULocale 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 setVariant method throws IllformedLocaleException + * for a variant that does not satisfy the syntax above. If it is + * necessary to support such a variant, you could use the constructor + * Builder(boolean isLenientVariant) passing true to + * skip the syntax validation for variant. However, you should keep in + * mind that a Locale object created this way might lose + * the variant information when transformed to a BCP 47 language tag. + * + *

    + * The following example shows how to create a ULocale object + * with the Builder. + *

    + *
    +     *     ULocale aLocale = new Builder().setLanguage("sr").setScript("Latn").setRegion("RS").build();
    +     * 
    + *
    + * + *

    Builders can be reused; clear() 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 + * setVariant to accept a value that does not + * conform to the IETF BCP 47 variant subtag's syntax requirements. + * + * @param isLenientVariant When true, this Builder + * 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 Builder accepts a value that does + * not conform to the IETF BCP 47 variant subtag's syntax requirements + * in setVariant + * + * @return true if this Build 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 Builder to match the provided locale. + * The previous state of the builder is discarded. Fields that do + * not conform to the ULocale class specification, for example, + * a single letter language, are ill-formed. + * + * @param locale the locale + * @return this builder + * @throws IllformedLocaleException if locale 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 languageTag is ill-formed. + * @throws NullPointerException if languageTag 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 language is the empty string, + * the language in this Builder 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 ULocale + * created by the Builder is always normalized + * to lower case letters. + * + * @param language the language + * @return this builder + * @throws IllformedLocaleException if language 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 script is the empty string, + * the script in this Builder 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 ULocale created by the + * Builder 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 script 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 Builder 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 ULocale created by the Builder is always + * normalized to upper case. + * + * @param region the region + * @return this builder + * @throws IllformedLocaleException if region 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 Builder is removed. + *

    + * Note: By default, this method checks if variant + * satisfies the IETF BCP 47 variant subtag's syntax requirements. + * However, the ULocale class itself does not impose any syntactical + * restriction on variant. When a Builder is created by the + * constructor Builder(boolean isLenientVariant) + * with true, this method skips the syntax check. + * + * @param variant the variant + * @return this builder + * @throws IllformedLocaleException if variant 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 [0-9A-Za-z]. 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. + * + *

    Note: 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. + * + *

    Note: 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 key is illegal + * or value 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. + *

    + * Note: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 key or type + * 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 new file mode 100644 index 00000000000..0bac81d1453 --- /dev/null +++ b/eclipse-build/plugins.template/com.ibm.icu.base/src/com/ibm/icu/util/VersionInfo.java @@ -0,0 +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() {} +} -- 2.40.0