ICU-10993 ICU4J 54 maintenance branch copied from trunk r36530
X-SVN-Rev: 36535
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..e322584
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,533 @@
+* text=auto !eol
+
+*.c text !eol
+*.cc text !eol
+*.classpath text !eol
+*.cpp text !eol
+*.css text !eol
+*.dsp text !eol
+*.dsw text !eol
+*.filters text !eol
+*.h text !eol
+*.htm text !eol
+*.html text !eol
+*.in text !eol
+*.java text !eol
+*.launch text !eol
+*.mak text !eol
+*.md text !eol
+*.MF text !eol
+*.mk text !eol
+*.pl text !eol
+*.pm text !eol
+*.project text !eol
+*.properties text !eol
+*.py text !eol
+*.rc text !eol
+*.sh text eol=lf
+*.sln text !eol
+*.stub text !eol
+*.txt text !eol
+*.ucm text !eol
+*.vcproj text !eol
+*.vcxproj text !eol
+*.xml text !eol
+*.xsl text !eol
+*.xslt text !eol
+Makefile text !eol
+configure text !eol
+LICENSE text !eol
+README text !eol
+
+*.bin -text
+*.brk -text
+*.cnv -text
+*.icu -text
+*.res -text
+*.nrm -text
+*.spp -text
+*.tri2 -text
+
+/build.properties -text
+demos/.settings/org.eclipse.core.resources.prefs -text
+demos/manifest.stub -text
+eclipse-build/build-local.properties.template -text
+eclipse-build/features.template/com.ibm.icu.base/.project -text
+eclipse-build/features.template/com.ibm.icu.base/build.properties -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.core.resources.prefs -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/.classpath -text
+eclipse-build/plugins.template/com.ibm.icu.base/.project -text
+eclipse-build/plugins.template/com.ibm.icu.base/.settings/org.eclipse.core.resources.prefs -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.tests/.settings/org.eclipse.core.resources.prefs -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/.settings/org.eclipse.core.resources.prefs -text
+eclipse-build/plugins.template/com.ibm.icu/META-INF/MANIFEST.MF -text
+main/classes/charset/.classpath -text
+main/classes/charset/.project -text
+main/classes/charset/.settings/org.eclipse.core.resources.prefs -text
+main/classes/charset/.settings/org.eclipse.jdt.core.prefs -text
+main/classes/charset/manifest.stub -text
+main/classes/collate/.classpath -text
+main/classes/collate/.project -text
+main/classes/collate/.settings/edu.umd.cs.findbugs.core.prefs -text
+main/classes/collate/.settings/org.eclipse.core.resources.prefs -text
+main/classes/collate/.settings/org.eclipse.jdt.core.prefs -text
+main/classes/collate/.settings/org.eclipse.jdt.ui.prefs -text
+main/classes/collate/collate-build.launch -text
+main/classes/core/.classpath -text
+main/classes/core/.project -text
+main/classes/core/.settings/edu.umd.cs.findbugs.core.prefs -text
+main/classes/core/.settings/org.eclipse.core.resources.prefs -text
+main/classes/core/.settings/org.eclipse.jdt.core.prefs -text
+main/classes/core/manifest.stub -text
+main/classes/currdata/.externalToolBuilders/copy-data-currdata.launch -text
+main/classes/currdata/.settings/org.eclipse.core.resources.prefs -text
+main/classes/currdata/.settings/org.eclipse.jdt.core.prefs -text
+main/classes/currdata/.settings/org.eclipse.jdt.ui.prefs -text
+main/classes/currdata/currdata-build.launch -text
+main/classes/langdata/.externalToolBuilders/copy-data-langdata.launch -text
+main/classes/langdata/.settings/org.eclipse.core.resources.prefs -text
+main/classes/langdata/.settings/org.eclipse.jdt.core.prefs -text
+main/classes/langdata/.settings/org.eclipse.jdt.ui.prefs -text
+main/classes/langdata/langdata-build.launch -text
+main/classes/localespi/.classpath -text
+main/classes/localespi/.project -text
+main/classes/localespi/.settings/org.eclipse.core.resources.prefs -text
+main/classes/localespi/.settings/org.eclipse.jdt.core.prefs -text
+main/classes/localespi/manifest.stub -text
+main/classes/localespi/src/META-INF/services/java.text.spi.BreakIteratorProvider -text
+main/classes/localespi/src/META-INF/services/java.text.spi.CollatorProvider -text
+main/classes/localespi/src/META-INF/services/java.text.spi.DateFormatProvider -text
+main/classes/localespi/src/META-INF/services/java.text.spi.DateFormatSymbolsProvider -text
+main/classes/localespi/src/META-INF/services/java.text.spi.DecimalFormatSymbolsProvider -text
+main/classes/localespi/src/META-INF/services/java.text.spi.NumberFormatProvider -text
+main/classes/localespi/src/META-INF/services/java.util.spi.CurrencyNameProvider -text
+main/classes/localespi/src/META-INF/services/java.util.spi.LocaleNameProvider -text
+main/classes/localespi/src/META-INF/services/java.util.spi.TimeZoneNameProvider -text
+main/classes/localespi/src/com/ibm/icu/impl/javaspi/ICULocaleServiceProviderConfig.properties -text
+main/classes/regiondata/.externalToolBuilders/copy-data-regiondata.launch -text
+main/classes/regiondata/.settings/org.eclipse.core.resources.prefs -text
+main/classes/regiondata/.settings/org.eclipse.jdt.core.prefs -text
+main/classes/regiondata/.settings/org.eclipse.jdt.ui.prefs -text
+main/classes/regiondata/regiondata-build.launch -text
+main/classes/translit/.externalToolBuilders/copy-data-translit.launch -text
+main/classes/translit/.settings/edu.umd.cs.findbugs.core.prefs -text
+main/classes/translit/.settings/org.eclipse.core.resources.prefs -text
+main/classes/translit/.settings/org.eclipse.jdt.core.prefs -text
+main/classes/translit/.settings/org.eclipse.jdt.ui.prefs -text
+main/classes/translit/translit-build.launch -text
+main/shared/.project -text
+main/shared/.settings/org.eclipse.core.resources.prefs -text
+main/shared/data/icudata.jar -text
+main/shared/data/icutzdata.jar -text
+main/shared/data/testdata.jar -text
+main/tests/charset/.classpath -text
+main/tests/charset/.project -text
+main/tests/charset/.settings/org.eclipse.core.resources.prefs -text
+main/tests/charset/.settings/org.eclipse.jdt.core.prefs -text
+main/tests/charset/manifest.stub -text
+main/tests/collate/.classpath -text
+main/tests/collate/.project -text
+main/tests/collate/.settings/org.eclipse.core.resources.prefs -text
+main/tests/collate/.settings/org.eclipse.jdt.core.prefs -text
+main/tests/collate/.settings/org.eclipse.jdt.ui.prefs -text
+main/tests/collate/collate-tests-build.launch -text
+main/tests/core/.classpath -text
+main/tests/core/.project -text
+main/tests/core/.settings/org.eclipse.core.resources.prefs -text
+main/tests/core/.settings/org.eclipse.jdt.core.prefs -text
+main/tests/core/manifest.stub -text
+main/tests/core/src/com/ibm/icu/dev/data/rbbi/english.dict -text
+main/tests/core/src/com/ibm/icu/dev/data/resources/testmessages.properties -text
+main/tests/core/src/com/ibm/icu/dev/data/thai6.ucs -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_3.6/com.ibm.icu.impl.OlsonTimeZone.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_3.6/com.ibm.icu.impl.TimeZoneAdapter.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_3.6/com.ibm.icu.math.BigDecimal.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_3.6/com.ibm.icu.math.MathContext.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_3.6/com.ibm.icu.text.ArabicShapingException.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_3.6/com.ibm.icu.text.ChineseDateFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_3.6/com.ibm.icu.text.ChineseDateFormatSymbols.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_3.6/com.ibm.icu.text.DateFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_3.6/com.ibm.icu.text.DateFormatSymbols.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_3.6/com.ibm.icu.text.DecimalFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_3.6/com.ibm.icu.text.DecimalFormatSymbols.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_3.6/com.ibm.icu.text.MessageFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_3.6/com.ibm.icu.text.NumberFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_3.6/com.ibm.icu.text.RuleBasedNumberFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_3.6/com.ibm.icu.text.SimpleDateFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_3.6/com.ibm.icu.text.StringPrepParseException.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_3.6/com.ibm.icu.util.BuddhistCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_3.6/com.ibm.icu.util.Calendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_3.6/com.ibm.icu.util.ChineseCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_3.6/com.ibm.icu.util.CopticCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_3.6/com.ibm.icu.util.Currency.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_3.6/com.ibm.icu.util.EthiopicCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_3.6/com.ibm.icu.util.GregorianCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_3.6/com.ibm.icu.util.HebrewCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_3.6/com.ibm.icu.util.IslamicCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_3.6/com.ibm.icu.util.JapaneseCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_3.6/com.ibm.icu.util.SimpleTimeZone.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_3.6/com.ibm.icu.util.TimeZone.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_3.6/com.ibm.icu.util.ULocale.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_3.6/com.ibm.icu.util.UResourceTypeMismatchException.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.impl.DateNumberFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.impl.IllegalIcuArgumentException.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.impl.InvalidFormatException.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.impl.JavaTimeZone.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.impl.OlsonTimeZone.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.impl.RelativeDateFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.impl.TimeZoneAdapter.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.impl.TimeZoneGenericNames.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.impl.TimeZoneNamesImpl.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.impl.duration.BasicDurationFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.impl.locale.LocaleSyntaxException.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.math.BigDecimal.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.math.MathContext.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.text.ArabicShapingException.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.text.ChineseDateFormat$Field.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.text.ChineseDateFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.text.ChineseDateFormatSymbols.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.text.CompactDecimalFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.text.CurrencyPluralInfo.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.text.DateFormat$Field.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.text.DateFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.text.DateFormatSymbols.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.text.DateIntervalFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.text.DateIntervalInfo$PatternInfo.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.text.DateIntervalInfo.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.text.DecimalFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.text.DecimalFormatSymbols.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.text.MessageFormat$Field.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.text.MessageFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.text.NumberFormat$Field.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.text.NumberFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.text.PluralFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.text.PluralRules.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.text.RuleBasedNumberFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.text.SelectFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.text.SimpleDateFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.text.StringPrepParseException.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.text.TimeUnitFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.text.TimeZoneFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.util.AnnualTimeZoneRule.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.util.BuddhistCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.util.Calendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.util.ChineseCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.util.CopticCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.util.Currency.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.util.DangiCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.util.DateInterval.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.util.DateTimeRule.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.util.EthiopicCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.util.GregorianCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.util.HebrewCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.util.IllformedLocaleException.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.util.IndianCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.util.InitialTimeZoneRule.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.util.IslamicCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.util.JapaneseCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.util.PersianCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.util.RuleBasedTimeZone.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.util.SimpleTimeZone.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.util.TaiwanCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.util.TimeArrayTimeZoneRule.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.util.TimeZone.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.util.ULocale.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.util.UResourceTypeMismatchException.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_51.1/com.ibm.icu.util.VTimeZone.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.impl.DateNumberFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.impl.IllegalIcuArgumentException.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.impl.InvalidFormatException.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.impl.JavaTimeZone.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.impl.OlsonTimeZone.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.impl.RelativeDateFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.impl.TimeZoneAdapter.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.impl.TimeZoneGenericNames.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.impl.TimeZoneNamesImpl.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.impl.duration.BasicDurationFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.impl.locale.LocaleSyntaxException.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.math.BigDecimal.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.math.MathContext.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.text.ArabicShapingException.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.text.ChineseDateFormat$Field.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.text.ChineseDateFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.text.ChineseDateFormatSymbols.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.text.CompactDecimalFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.text.CurrencyPluralInfo.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.text.DateFormat$Field.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.text.DateFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.text.DateFormatSymbols.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.text.DateIntervalFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.text.DateIntervalInfo$PatternInfo.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.text.DateIntervalInfo.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.text.DecimalFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.text.DecimalFormatSymbols.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.text.GeneralMeasureFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.text.MessageFormat$Field.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.text.MessageFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.text.NumberFormat$Field.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.text.NumberFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.text.PluralFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.text.PluralRules.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.text.RuleBasedNumberFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.text.SelectFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.text.SimpleDateFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.text.StringPrepParseException.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.text.TimeUnitFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.text.TimeZoneFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.util.AnnualTimeZoneRule.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.util.BuddhistCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.util.Calendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.util.ChineseCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.util.CopticCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.util.Currency.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.util.DangiCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.util.DateInterval.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.util.DateTimeRule.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.util.EthiopicCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.util.GregorianCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.util.HebrewCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.util.IllformedLocaleException.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.util.IndianCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.util.InitialTimeZoneRule.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.util.IslamicCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.util.JapaneseCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.util.MeasureUnit.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.util.PersianCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.util.RuleBasedTimeZone.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.util.SimpleTimeZone.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.util.TaiwanCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.util.TimeArrayTimeZoneRule.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.util.TimeUnit.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.util.TimeZone.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.util.ULocale.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.util.UResourceTypeMismatchException.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_52.1/com.ibm.icu.util.VTimeZone.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.impl.DateNumberFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.impl.IllegalIcuArgumentException.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.impl.InvalidFormatException.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.impl.JavaTimeZone.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.impl.OlsonTimeZone.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.impl.RelativeDateFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.impl.TimeZoneAdapter.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.impl.TimeZoneGenericNames.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.impl.TimeZoneNamesImpl.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.impl.duration.BasicDurationFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.impl.locale.LocaleSyntaxException.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.math.BigDecimal.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.math.MathContext.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.text.ArabicShapingException.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.text.ChineseDateFormat$Field.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.text.ChineseDateFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.text.ChineseDateFormatSymbols.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.text.CompactDecimalFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.text.CurrencyPluralInfo.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.text.DateFormat$Field.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.text.DateFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.text.DateFormatSymbols.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.text.DateIntervalFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.text.DateIntervalInfo$PatternInfo.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.text.DateIntervalInfo.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.text.DecimalFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.text.DecimalFormatSymbols.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.text.MeasureFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.text.MessageFormat$Field.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.text.MessageFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.text.NumberFormat$Field.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.text.NumberFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.text.PluralFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.text.PluralRules.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.text.RuleBasedNumberFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.text.SelectFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.text.SimpleDateFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.text.StringPrepParseException.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.text.TimeUnitFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.text.TimeZoneFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.util.AnnualTimeZoneRule.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.util.BuddhistCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.util.Calendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.util.ChineseCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.util.CopticCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.util.Currency.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.util.DangiCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.util.DateInterval.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.util.DateTimeRule.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.util.EthiopicCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.util.GregorianCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.util.HebrewCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.util.ICUCloneNotSupportedException.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.util.ICUException.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.util.ICUUncheckedIOException.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.util.IllformedLocaleException.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.util.IndianCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.util.InitialTimeZoneRule.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.util.IslamicCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.util.JapaneseCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.util.MeasureUnit.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.util.PersianCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.util.RuleBasedTimeZone.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.util.SimpleTimeZone.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.util.TaiwanCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.util.TimeArrayTimeZoneRule.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.util.TimeUnit.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.util.TimeZone.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.util.ULocale.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.util.UResourceTypeMismatchException.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_53.1/com.ibm.icu.util.VTimeZone.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.impl.DateNumberFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.impl.IllegalIcuArgumentException.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.impl.InvalidFormatException.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.impl.JavaTimeZone.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.impl.OlsonTimeZone.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.impl.RelativeDateFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.impl.TZDBTimeZoneNames.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.impl.TimeZoneAdapter.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.impl.TimeZoneGenericNames.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.impl.TimeZoneNamesImpl.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.impl.duration.BasicDurationFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.impl.locale.LocaleSyntaxException.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.math.BigDecimal.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.math.MathContext.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.text.ArabicShapingException.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.text.ChineseDateFormat$Field.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.text.ChineseDateFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.text.ChineseDateFormatSymbols.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.text.CompactDecimalFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.text.CurrencyPluralInfo.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.text.DateFormat$Field.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.text.DateFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.text.DateFormatSymbols.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.text.DateIntervalFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.text.DateIntervalInfo$PatternInfo.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.text.DateIntervalInfo.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.text.DecimalFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.text.DecimalFormatSymbols.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.text.MeasureFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.text.MessageFormat$Field.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.text.MessageFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.text.NumberFormat$Field.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.text.NumberFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.text.PluralFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.text.PluralRules.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.text.RuleBasedNumberFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.text.SelectFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.text.SimpleDateFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.text.StringPrepParseException.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.text.TimeUnitFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.text.TimeZoneFormat.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.util.AnnualTimeZoneRule.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.util.BuddhistCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.util.Calendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.util.ChineseCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.util.CopticCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.util.Currency.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.util.DangiCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.util.DateInterval.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.util.DateTimeRule.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.util.EthiopicCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.util.GregorianCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.util.HebrewCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.util.ICUCloneNotSupportedException.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.util.ICUException.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.util.ICUUncheckedIOException.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.util.IllformedLocaleException.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.util.IndianCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.util.InitialTimeZoneRule.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.util.IslamicCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.util.JapaneseCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.util.MeasureUnit.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.util.PersianCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.util.RuleBasedTimeZone.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.util.SimpleTimeZone.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.util.TaiwanCalendar.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.util.TimeArrayTimeZoneRule.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.util.TimeUnit.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.util.TimeZone.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.util.ULocale.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.util.UResourceTypeMismatchException.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_54.1/com.ibm.icu.util.VTimeZone.dat -text
+main/tests/core/src/com/ibm/icu/dev/test/util/Trie2Test.setRanges1.16.tri2 -text
+main/tests/core/src/com/ibm/icu/dev/test/util/Trie2Test.setRanges1.32.tri2 -text
+main/tests/core/src/com/ibm/icu/dev/test/util/Trie2Test.setRanges2.16.tri2 -text
+main/tests/core/src/com/ibm/icu/dev/test/util/Trie2Test.setRanges2.32.tri2 -text
+main/tests/core/src/com/ibm/icu/dev/test/util/Trie2Test.setRanges3.16.tri2 -text
+main/tests/core/src/com/ibm/icu/dev/test/util/Trie2Test.setRanges3.32.tri2 -text
+main/tests/core/src/com/ibm/icu/dev/test/util/Trie2Test.setRangesEmpty.16.tri2 -text
+main/tests/core/src/com/ibm/icu/dev/test/util/Trie2Test.setRangesEmpty.32.tri2 -text
+main/tests/core/src/com/ibm/icu/dev/test/util/Trie2Test.setRangesSingleValue.16.tri2 -text
+main/tests/core/src/com/ibm/icu/dev/test/util/Trie2Test.setRangesSingleValue.32.tri2 -text
+main/tests/framework/.classpath -text
+main/tests/framework/.project -text
+main/tests/framework/.settings/org.eclipse.core.resources.prefs -text
+main/tests/framework/.settings/org.eclipse.jdt.core.prefs -text
+main/tests/framework/manifest.stub -text
+main/tests/localespi/.classpath -text
+main/tests/localespi/.project -text
+main/tests/localespi/.settings/org.eclipse.core.resources.prefs -text
+main/tests/localespi/manifest.stub -text
+main/tests/packaging/.settings/org.eclipse.core.resources.prefs -text
+main/tests/packaging/.settings/org.eclipse.jdt.core.prefs -text
+main/tests/packaging/.settings/org.eclipse.jdt.ui.prefs -text
+main/tests/packaging/packaging-tests-build.launch -text
+main/tests/testall/.classpath -text
+main/tests/testall/.project -text
+main/tests/testall/.settings/org.eclipse.core.resources.prefs -text
+main/tests/testall/.settings/org.eclipse.jdt.core.prefs -text
+main/tests/testall/.settings/org.eclipse.jdt.ui.prefs -text
+main/tests/testall/build.properties -text
+main/tests/testall/manifest.stub -text
+main/tests/translit/.externalToolBuilders/copy-translit-test-data.launch -text
+main/tests/translit/.settings/org.eclipse.core.resources.prefs -text
+main/tests/translit/.settings/org.eclipse.jdt.core.prefs -text
+main/tests/translit/.settings/org.eclipse.jdt.ui.prefs -text
+main/tests/translit/translit-tests-build.launch -text
+/manifest.stub -text
+perf-tests/.classpath -text
+perf-tests/.project -text
+perf-tests/.settings/org.eclipse.core.resources.prefs -text
+perf-tests/.settings/org.eclipse.jdt.core.prefs -text
+perf-tests/.settings/org.eclipse.jdt.ui.prefs -text
+perf-tests/data/icuperf2report.xsl -text
+samples/build.properties -text
+samples/manifest.stub -text
+samples/src/com/ibm/icu/samples/iuc/data/popmsg/en.res -text
+samples/src/com/ibm/icu/samples/iuc/data/popmsg/es.res -text
+samples/src/com/ibm/icu/samples/iuc/data/popmsg/res_index.res -text
+samples/src/com/ibm/icu/samples/iuc/data/popmsg/root.res -text
+samples/src/com/ibm/icu/samples/iuc/data/reshello/es.res -text
+samples/src/com/ibm/icu/samples/iuc/data/reshello/mt.res -text
+samples/src/com/ibm/icu/samples/iuc/data/reshello/res_index.res -text
+samples/src/com/ibm/icu/samples/iuc/data/reshello/root.res -text
+tools/build/.settings/org.eclipse.core.resources.prefs -text
+tools/build/icu4j48.api3.gz -text
+tools/build/icu4j49.api3.gz -text
+tools/build/icu4j50.api3.gz -text
+tools/build/icu4j51.api3.gz -text
+tools/build/icu4j52.api3.gz -text
+tools/build/icu4j53.api3.gz -text
+tools/build/icu4j54.api3.gz -text
+tools/build/manifest.stub -text
+tools/misc/.settings/org.eclipse.core.resources.prefs -text
+tools/misc/manifest.stub -text
+
+# The following file types are stored in Git-LFS.
+*.jar filter=lfs diff=lfs merge=lfs -text
+*.dat filter=lfs diff=lfs merge=lfs -text
+*.zip filter=lfs diff=lfs merge=lfs -text
+*.gz filter=lfs diff=lfs merge=lfs -text
+*.bz2 filter=lfs diff=lfs merge=lfs -text
+*.gif filter=lfs diff=lfs merge=lfs -text
+
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c800d44
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,27 @@
+/*.jar
+/.project
+demos/out
+/doc
+eclipse-build/out
+main/classes/charset/out
+main/classes/collate/out
+main/classes/core/out
+main/classes/currdata/out
+main/classes/langdata/out
+main/classes/localespi/out
+main/classes/regiondata/out
+main/classes/translit/out
+main/tests/charset/out
+main/tests/collate/out
+main/tests/core/out
+main/tests/framework/out
+main/tests/localespi/out
+main/tests/packaging/out
+main/tests/testall/out
+main/tests/translit/out
+/out
+perf-tests/out
+samples/build-local.properties
+samples/out
+tools/build/out
+tools/misc/out
diff --git a/APIChangeReport.html b/APIChangeReport.html
new file mode 100644
index 0000000..e856b67
--- /dev/null
+++ b/APIChangeReport.html
@@ -0,0 +1,537 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>ICU4J API Comparison: ICU4J 53.1.0 with ICU4J 54.1.0</title>
+<!-- Copyright 2014, IBM, All Rights Reserved. -->
+</head>
+<body>
+<h1>ICU4J API Comparison: ICU4J 53.1.0 with ICU4J 54.1.0</h1>
+
+<hr/>
+<h2>Removed from ICU4J 53.1.0</h2>
+
+<h3>Package com.ibm.icu.text</h3>
+<ul>
+Normalizer.Mode
+<ul>
+<li><span style='color:orange'>(draft)</span> public <i>Normalizer.Mode</i>()</li>
+</ul>
+PluralRules.Factory
+<ul>
+<li><span style='color:orange'>(draft)</span> public <i>PluralRules.Factory</i>()</li>
+</ul>
+TimeZoneNames.Factory
+<ul>
+<li><span style='color:orange'>(draft)</span> public <i>TimeZoneNames.Factory</i>()</li>
+</ul>
+UnicodeSet
+<ul>
+<li><span style='color:green'>(stable)</span> public UnicodeSet <i>add</i>(java.util.Collection<?>)</li>
+<li><span style='color:green'>(stable)</span> public UnicodeSet <i>addAll</i>(java.lang.String...)</li>
+<li><span style='color:green'>(stable)</span> public UnicodeSet <i>addAll</i>(java.util.Collection<?>)</li>
+<li><span style='color:green'>(stable)</span> public static int <i>compare</i>(int, java.lang.String)</li>
+<li><span style='color:green'>(stable)</span> public static int <i>compare</i>(java.lang.String, int)</li>
+<li><span style='color:green'>(stable)</span> public final UnicodeSet <i>complement</i>(java.lang.String)</li>
+<li><span style='color:green'>(stable)</span> public final UnicodeSet <i>complementAll</i>(java.lang.String)</li>
+<li><span style='color:green'>(stable)</span> public final boolean <i>contains</i>(java.lang.String)</li>
+<li><span style='color:green'>(stable)</span> public boolean <i>containsAll</i>(java.util.Collection<java.lang.String>)</li>
+<li><span style='color:green'>(stable)</span> public boolean <i>containsNone</i>(java.lang.String)</li>
+<li><span style='color:green'>(stable)</span> public boolean <i>containsNone</i>(java.util.Collection<java.lang.String>)</li>
+<li><span style='color:green'>(stable)</span> public final boolean <i>containsSome</i>(java.lang.String)</li>
+<li><span style='color:green'>(stable)</span> public final boolean <i>containsSome</i>(java.util.Collection<java.lang.String>)</li>
+<li><span style='color:green'>(stable)</span> public static UnicodeSet <i>from</i>(java.lang.String)</li>
+<li><span style='color:green'>(stable)</span> public static UnicodeSet <i>fromAll</i>(java.lang.String)</li>
+<li><span style='color:green'>(stable)</span> public final UnicodeSet <i>remove</i>(java.lang.String)</li>
+<li><span style='color:green'>(stable)</span> public final UnicodeSet <i>removeAll</i>(java.lang.String)</li>
+<li><span style='color:green'>(stable)</span> public UnicodeSet <i>removeAll</i>(java.util.Collection<java.lang.String>)</li>
+<li><span style='color:green'>(stable)</span> public final UnicodeSet <i>retain</i>(java.lang.String)</li>
+<li><span style='color:green'>(stable)</span> public final UnicodeSet <i>retainAll</i>(java.lang.String)</li>
+<li><span style='color:green'>(stable)</span> public UnicodeSet <i>retainAll</i>(java.util.Collection<java.lang.String>)</li>
+<li><span style='color:green'>(stable)</span> public java.lang.Iterable<java.lang.String> <i>strings</i>()</li>
+</ul>
+</ul>
+
+
+<hr/>
+<h2>Deprecated or Obsoleted in ICU4J 54.1.0</h2>
+
+<h3>Package com.ibm.icu.lang</h3>
+<ul>
+UScript
+<ul>
+<li><span style='color:gray'>(deprecated)</span> public static final int DUPLOYAN_SHORTAND</li>
+</ul>
+</ul>
+
+<h3>Package com.ibm.icu.text</h3>
+<ul>
+<li><span style='color:gray'>(deprecated)</span> public interface <i>RbnfLenientScanner</i></li>
+<li><span style='color:gray'>(deprecated)</span> public interface <i>RbnfLenientScannerProvider</i></li>
+</ul>
+
+<h3>Package com.ibm.icu.util</h3>
+<ul>
+Calendar
+<ul>
+<li><span style='color:gray'>(deprecated)</span> public static final int WEEKDAY</li>
+<li><span style='color:gray'>(deprecated)</span> public static final int WEEKEND</li>
+<li><span style='color:gray'>(deprecated)</span> public static final int WEEKEND_CEASE</li>
+<li><span style='color:gray'>(deprecated)</span> public static final int WEEKEND_ONSET</li>
+<li><span style='color:gray'>(deprecated)</span> public int <i>getDayOfWeekType</i>(int)</li>
+<li><span style='color:gray'>(deprecated)</span> public int <i>getWeekendTransition</i>(int)</li>
+</ul>
+VersionInfo
+<ul>
+<li><span style='color:gray'>(deprecated)</span> public static final VersionInfo UCOL_TAILORINGS_VERSION</li>
+</ul>
+</ul>
+
+
+<hr/>
+<h2>Changed in ICU4J 54.1.0 (old, new)</h2>
+<p>(no API changed)</p>
+
+<hr/>
+<h2>Promoted to stable in ICU4J 54.1.0</h2>
+
+<h3>Package com.ibm.icu.text</h3>
+<ul>
+BreakIterator
+<ul>
+<li><span style='color:green'>(stable)</span> public int <i>getRuleStatus</i>()</li>
+<li><span style='color:green'>(stable)</span> public int <i>getRuleStatusVec</i>(int[])</li>
+</ul>
+ListFormatter
+<ul>
+<li><span style='color:green'>(stable)</span> public java.lang.String <i>getPatternForNumItems</i>(int)</li>
+</ul>
+</ul>
+
+<h3>Package com.ibm.icu.util</h3>
+<ul>
+<li><span style='color:green'>(stable)</span> public static enum <i>IslamicCalendar.CalculationType</i></li>
+IslamicCalendar.CalculationType
+<ul>
+<li><span style='color:green'>(stable)</span> public static final IslamicCalendar.CalculationType ISLAMIC</li>
+<li><span style='color:green'>(stable)</span> public static final IslamicCalendar.CalculationType ISLAMIC_CIVIL</li>
+<li><span style='color:green'>(stable)</span> public static final IslamicCalendar.CalculationType ISLAMIC_TBLA</li>
+<li><span style='color:green'>(stable)</span> public static final IslamicCalendar.CalculationType ISLAMIC_UMALQURA</li>
+</ul>
+TimeZone
+<ul>
+<li><span style='color:green'>(stable)</span> public static java.lang.String <i>getIDForWindowsID</i>(java.lang.String, java.lang.String)</li>
+<li><span style='color:green'>(stable)</span> public static java.lang.String <i>getWindowsID</i>(java.lang.String)</li>
+</ul>
+</ul>
+
+
+<hr/>
+<h2>Added in ICU4J 54.1.0</h2>
+
+<h3>Package com.ibm.icu.lang</h3>
+<ul>
+UCharacter
+<ul>
+<li><span style='color:orange'>(draft)</span> public static java.lang.String <i>toTitleCase</i>(java.util.Locale, java.lang.String, BreakIterator, int)</li>
+</ul>
+UCharacter.JoiningGroup
+<ul>
+<li><span style='color:green'>(stable)</span> public static final int MANICHAEAN_ALEPH</li>
+<li><span style='color:green'>(stable)</span> public static final int MANICHAEAN_AYIN</li>
+<li><span style='color:green'>(stable)</span> public static final int MANICHAEAN_BETH</li>
+<li><span style='color:green'>(stable)</span> public static final int MANICHAEAN_DALETH</li>
+<li><span style='color:green'>(stable)</span> public static final int MANICHAEAN_DHAMEDH</li>
+<li><span style='color:green'>(stable)</span> public static final int MANICHAEAN_FIVE</li>
+<li><span style='color:green'>(stable)</span> public static final int MANICHAEAN_GIMEL</li>
+<li><span style='color:green'>(stable)</span> public static final int MANICHAEAN_HETH</li>
+<li><span style='color:green'>(stable)</span> public static final int MANICHAEAN_HUNDRED</li>
+<li><span style='color:green'>(stable)</span> public static final int MANICHAEAN_KAPH</li>
+<li><span style='color:green'>(stable)</span> public static final int MANICHAEAN_LAMEDH</li>
+<li><span style='color:green'>(stable)</span> public static final int MANICHAEAN_MEM</li>
+<li><span style='color:green'>(stable)</span> public static final int MANICHAEAN_NUN</li>
+<li><span style='color:green'>(stable)</span> public static final int MANICHAEAN_ONE</li>
+<li><span style='color:green'>(stable)</span> public static final int MANICHAEAN_PE</li>
+<li><span style='color:green'>(stable)</span> public static final int MANICHAEAN_QOPH</li>
+<li><span style='color:green'>(stable)</span> public static final int MANICHAEAN_RESH</li>
+<li><span style='color:green'>(stable)</span> public static final int MANICHAEAN_SADHE</li>
+<li><span style='color:green'>(stable)</span> public static final int MANICHAEAN_SAMEKH</li>
+<li><span style='color:green'>(stable)</span> public static final int MANICHAEAN_TAW</li>
+<li><span style='color:green'>(stable)</span> public static final int MANICHAEAN_TEN</li>
+<li><span style='color:green'>(stable)</span> public static final int MANICHAEAN_TETH</li>
+<li><span style='color:green'>(stable)</span> public static final int MANICHAEAN_THAMEDH</li>
+<li><span style='color:green'>(stable)</span> public static final int MANICHAEAN_TWENTY</li>
+<li><span style='color:green'>(stable)</span> public static final int MANICHAEAN_WAW</li>
+<li><span style='color:green'>(stable)</span> public static final int MANICHAEAN_YODH</li>
+<li><span style='color:green'>(stable)</span> public static final int MANICHAEAN_ZAYIN</li>
+<li><span style='color:green'>(stable)</span> public static final int STRAIGHT_WAW</li>
+</ul>
+UCharacter.UnicodeBlock
+<ul>
+<li><span style='color:green'>(stable)</span> public static final UCharacter.UnicodeBlock BASSA_VAH</li>
+<li><span style='color:green'>(stable)</span> public static final int BASSA_VAH_ID</li>
+<li><span style='color:green'>(stable)</span> public static final UCharacter.UnicodeBlock CAUCASIAN_ALBANIAN</li>
+<li><span style='color:green'>(stable)</span> public static final int CAUCASIAN_ALBANIAN_ID</li>
+<li><span style='color:green'>(stable)</span> public static final UCharacter.UnicodeBlock COMBINING_DIACRITICAL_MARKS_EXTENDED</li>
+<li><span style='color:green'>(stable)</span> public static final int COMBINING_DIACRITICAL_MARKS_EXTENDED_ID</li>
+<li><span style='color:green'>(stable)</span> public static final UCharacter.UnicodeBlock COPTIC_EPACT_NUMBERS</li>
+<li><span style='color:green'>(stable)</span> public static final int COPTIC_EPACT_NUMBERS_ID</li>
+<li><span style='color:green'>(stable)</span> public static final UCharacter.UnicodeBlock DUPLOYAN</li>
+<li><span style='color:green'>(stable)</span> public static final int DUPLOYAN_ID</li>
+<li><span style='color:green'>(stable)</span> public static final UCharacter.UnicodeBlock ELBASAN</li>
+<li><span style='color:green'>(stable)</span> public static final int ELBASAN_ID</li>
+<li><span style='color:green'>(stable)</span> public static final UCharacter.UnicodeBlock GEOMETRIC_SHAPES_EXTENDED</li>
+<li><span style='color:green'>(stable)</span> public static final int GEOMETRIC_SHAPES_EXTENDED_ID</li>
+<li><span style='color:green'>(stable)</span> public static final UCharacter.UnicodeBlock GRANTHA</li>
+<li><span style='color:green'>(stable)</span> public static final int GRANTHA_ID</li>
+<li><span style='color:green'>(stable)</span> public static final UCharacter.UnicodeBlock KHOJKI</li>
+<li><span style='color:green'>(stable)</span> public static final int KHOJKI_ID</li>
+<li><span style='color:green'>(stable)</span> public static final UCharacter.UnicodeBlock KHUDAWADI</li>
+<li><span style='color:green'>(stable)</span> public static final int KHUDAWADI_ID</li>
+<li><span style='color:green'>(stable)</span> public static final UCharacter.UnicodeBlock LATIN_EXTENDED_E</li>
+<li><span style='color:green'>(stable)</span> public static final int LATIN_EXTENDED_E_ID</li>
+<li><span style='color:green'>(stable)</span> public static final UCharacter.UnicodeBlock LINEAR_A</li>
+<li><span style='color:green'>(stable)</span> public static final int LINEAR_A_ID</li>
+<li><span style='color:green'>(stable)</span> public static final UCharacter.UnicodeBlock MAHAJANI</li>
+<li><span style='color:green'>(stable)</span> public static final int MAHAJANI_ID</li>
+<li><span style='color:green'>(stable)</span> public static final UCharacter.UnicodeBlock MANICHAEAN</li>
+<li><span style='color:green'>(stable)</span> public static final int MANICHAEAN_ID</li>
+<li><span style='color:green'>(stable)</span> public static final UCharacter.UnicodeBlock MENDE_KIKAKUI</li>
+<li><span style='color:green'>(stable)</span> public static final int MENDE_KIKAKUI_ID</li>
+<li><span style='color:green'>(stable)</span> public static final UCharacter.UnicodeBlock MODI</li>
+<li><span style='color:green'>(stable)</span> public static final int MODI_ID</li>
+<li><span style='color:green'>(stable)</span> public static final UCharacter.UnicodeBlock MRO</li>
+<li><span style='color:green'>(stable)</span> public static final int MRO_ID</li>
+<li><span style='color:green'>(stable)</span> public static final UCharacter.UnicodeBlock MYANMAR_EXTENDED_B</li>
+<li><span style='color:green'>(stable)</span> public static final int MYANMAR_EXTENDED_B_ID</li>
+<li><span style='color:green'>(stable)</span> public static final UCharacter.UnicodeBlock NABATAEAN</li>
+<li><span style='color:green'>(stable)</span> public static final int NABATAEAN_ID</li>
+<li><span style='color:green'>(stable)</span> public static final UCharacter.UnicodeBlock OLD_NORTH_ARABIAN</li>
+<li><span style='color:green'>(stable)</span> public static final int OLD_NORTH_ARABIAN_ID</li>
+<li><span style='color:green'>(stable)</span> public static final UCharacter.UnicodeBlock OLD_PERMIC</li>
+<li><span style='color:green'>(stable)</span> public static final int OLD_PERMIC_ID</li>
+<li><span style='color:green'>(stable)</span> public static final UCharacter.UnicodeBlock ORNAMENTAL_DINGBATS</li>
+<li><span style='color:green'>(stable)</span> public static final int ORNAMENTAL_DINGBATS_ID</li>
+<li><span style='color:green'>(stable)</span> public static final UCharacter.UnicodeBlock PAHAWH_HMONG</li>
+<li><span style='color:green'>(stable)</span> public static final int PAHAWH_HMONG_ID</li>
+<li><span style='color:green'>(stable)</span> public static final UCharacter.UnicodeBlock PALMYRENE</li>
+<li><span style='color:green'>(stable)</span> public static final int PALMYRENE_ID</li>
+<li><span style='color:green'>(stable)</span> public static final UCharacter.UnicodeBlock PAU_CIN_HAU</li>
+<li><span style='color:green'>(stable)</span> public static final int PAU_CIN_HAU_ID</li>
+<li><span style='color:green'>(stable)</span> public static final UCharacter.UnicodeBlock PSALTER_PAHLAVI</li>
+<li><span style='color:green'>(stable)</span> public static final int PSALTER_PAHLAVI_ID</li>
+<li><span style='color:green'>(stable)</span> public static final UCharacter.UnicodeBlock SHORTHAND_FORMAT_CONTROLS</li>
+<li><span style='color:green'>(stable)</span> public static final int SHORTHAND_FORMAT_CONTROLS_ID</li>
+<li><span style='color:green'>(stable)</span> public static final UCharacter.UnicodeBlock SIDDHAM</li>
+<li><span style='color:green'>(stable)</span> public static final int SIDDHAM_ID</li>
+<li><span style='color:green'>(stable)</span> public static final UCharacter.UnicodeBlock SINHALA_ARCHAIC_NUMBERS</li>
+<li><span style='color:green'>(stable)</span> public static final int SINHALA_ARCHAIC_NUMBERS_ID</li>
+<li><span style='color:green'>(stable)</span> public static final UCharacter.UnicodeBlock SUPPLEMENTAL_ARROWS_C</li>
+<li><span style='color:green'>(stable)</span> public static final int SUPPLEMENTAL_ARROWS_C_ID</li>
+<li><span style='color:green'>(stable)</span> public static final UCharacter.UnicodeBlock TIRHUTA</li>
+<li><span style='color:green'>(stable)</span> public static final int TIRHUTA_ID</li>
+<li><span style='color:green'>(stable)</span> public static final UCharacter.UnicodeBlock WARANG_CITI</li>
+<li><span style='color:green'>(stable)</span> public static final int WARANG_CITI_ID</li>
+</ul>
+UScript
+<ul>
+<li><span style='color:green'>(stable)</span> public static final int AHOM</li>
+<li><span style='color:green'>(stable)</span> public static final int DUPLOYAN</li>
+<li><span style='color:green'>(stable)</span> public static final int HATRAN</li>
+<li><span style='color:green'>(stable)</span> public static final int KHUDAWADI</li>
+<li><span style='color:green'>(stable)</span> public static final int MODI</li>
+<li><span style='color:green'>(stable)</span> public static final int MULTANI</li>
+<li><span style='color:green'>(stable)</span> public static final int PAU_CIN_HAU</li>
+<li><span style='color:green'>(stable)</span> public static final int SIDDHAM</li>
+<li><span style='color:orange'>(draft)</span> public static final int <i>getCodeFromName</i>(java.lang.String)</li>
+</ul>
+</ul>
+
+<h3>Package com.ibm.icu.text</h3>
+<ul>
+<li><span style='color:orange'>(draft)</span> public final class <i>ScientificFormatHelper</i></li>
+<li><span style='color:orange'>(draft)</span> public static class <i>UnicodeSet.EntryRange</i></li>
+<li><span style='color:orange'>(draft)</span> public class <i>UnicodeSetSpanner</i></li>
+<li><span style='color:orange'>(draft)</span> public static enum <i>RelativeDateTimeFormatter.Style</i></li>
+<li><span style='color:orange'>(draft)</span> public static enum <i>UnicodeSetSpanner.CountMethod</i></li>
+<li><span style='color:orange'>(draft)</span> public static enum <i>UnicodeSetSpanner.TrimOption</i></li>
+CurrencyDisplayNames
+<ul>
+<li><span style='color:orange'>(draft)</span> public static CurrencyDisplayNames <i>getInstance</i>(java.util.Locale)</li>
+<li><span style='color:orange'>(draft)</span> public static CurrencyDisplayNames <i>getInstance</i>(java.util.Locale, boolean)</li>
+</ul>
+CurrencyMetaInfo
+<ul>
+<li><span style='color:orange'>(draft)</span> public CurrencyMetaInfo.CurrencyDigits <i>currencyDigits</i>(java.lang.String, Currency.CurrencyUsage)</li>
+</ul>
+DateFormat
+<ul>
+<li><span style='color:orange'>(draft)</span> public static final DateFormat <i>getInstanceForSkeleton</i>(Calendar, java.lang.String, ULocale)</li>
+<li><span style='color:orange'>(draft)</span> public static final DateFormat <i>getInstanceForSkeleton</i>(Calendar, java.lang.String, java.util.Locale)</li>
+<li><span style='color:orange'>(draft)</span> public static final DateFormat <i>getInstanceForSkeleton</i>(java.lang.String)</li>
+<li><span style='color:orange'>(draft)</span> public static final DateFormat <i>getInstanceForSkeleton</i>(java.lang.String, ULocale)</li>
+<li><span style='color:orange'>(draft)</span> public static final DateFormat <i>getInstanceForSkeleton</i>(java.lang.String, java.util.Locale)</li>
+</ul>
+DateFormatSymbols
+<ul>
+<li><span style='color:orange'>(draft)</span> public java.lang.String[] <i>getYearNames</i>(int, int)</li>
+<li><span style='color:orange'>(draft)</span> public java.lang.String[] <i>getZodiacNames</i>(int, int)</li>
+<li><span style='color:orange'>(draft)</span> public void <i>setYearNames</i>(java.lang.String[], int, int)</li>
+<li><span style='color:orange'>(draft)</span> public void <i>setZodiacNames</i>(java.lang.String[], int, int)</li>
+</ul>
+DateIntervalInfo
+<ul>
+<li><span style='color:orange'>(draft)</span> public <i>DateIntervalInfo</i>(java.util.Locale)</li>
+</ul>
+DateTimePatternGenerator
+<ul>
+<li><span style='color:orange'>(draft)</span> public static DateTimePatternGenerator <i>getInstance</i>(java.util.Locale)</li>
+</ul>
+DecimalFormat
+<ul>
+<li><span style='color:orange'>(draft)</span> public Currency.CurrencyUsage <i>getCurrencyUsage</i>()</li>
+<li><span style='color:orange'>(draft)</span> public boolean <i>isDecimalPatternMatchRequired</i>()</li>
+<li><span style='color:orange'>(draft)</span> public void <i>setCurrencyUsage</i>(Currency.CurrencyUsage)</li>
+<li><span style='color:orange'>(draft)</span> public void <i>setDecimalPatternMatchRequired</i>(boolean)</li>
+</ul>
+DecimalFormatSymbols
+<ul>
+<li><span style='color:orange'>(draft)</span> public java.lang.String <i>getExponentMultiplicationSign</i>()</li>
+<li><span style='color:orange'>(draft)</span> public void <i>setExponentMultiplicationSign</i>(java.lang.String)</li>
+</ul>
+DisplayContext
+<ul>
+<li><span style='color:orange'>(draft)</span> public static final DisplayContext LENGTH_FULL</li>
+<li><span style='color:orange'>(draft)</span> public static final DisplayContext LENGTH_SHORT</li>
+</ul>
+DisplayContext.Type
+<ul>
+<li><span style='color:orange'>(draft)</span> public static final DisplayContext.Type DISPLAY_LENGTH</li>
+</ul>
+LocaleDisplayNames
+<ul>
+<li><span style='color:orange'>(draft)</span> public static LocaleDisplayNames <i>getInstance</i>(java.util.Locale)</li>
+<li><span style='color:orange'>(draft)</span> public static LocaleDisplayNames <i>getInstance</i>(java.util.Locale, DisplayContext...)</li>
+</ul>
+MeasureFormat
+<ul>
+<li><span style='color:orange'>(draft)</span> public static MeasureFormat <i>getCurrencyFormat</i>(java.util.Locale)</li>
+<li><span style='color:orange'>(draft)</span> public static MeasureFormat <i>getInstance</i>(java.util.Locale, MeasureFormat.FormatWidth)</li>
+<li><span style='color:orange'>(draft)</span> public static MeasureFormat <i>getInstance</i>(java.util.Locale, MeasureFormat.FormatWidth, NumberFormat)</li>
+</ul>
+NumberFormat
+<ul>
+<li><span style='color:orange'>(draft)</span> public static final int CASHCURRENCYSTYLE</li>
+</ul>
+PluralFormat
+<ul>
+<li><span style='color:orange'>(draft)</span> public <i>PluralFormat</i>(java.util.Locale)</li>
+<li><span style='color:orange'>(draft)</span> public <i>PluralFormat</i>(java.util.Locale, PluralRules)</li>
+<li><span style='color:orange'>(draft)</span> public <i>PluralFormat</i>(java.util.Locale, PluralRules.PluralType)</li>
+</ul>
+PluralRules
+<ul>
+<li><span style='color:orange'>(draft)</span> public static PluralRules <i>forLocale</i>(java.util.Locale)</li>
+<li><span style='color:orange'>(draft)</span> public static PluralRules <i>forLocale</i>(java.util.Locale, PluralRules.PluralType)</li>
+</ul>
+RelativeDateTimeFormatter
+<ul>
+<li><span style='color:orange'>(draft)</span> public DisplayContext <i>getCapitalizationContext</i>()</li>
+<li><span style='color:orange'>(draft)</span> public RelativeDateTimeFormatter.Style <i>getFormatStyle</i>()</li>
+<li><span style='color:orange'>(draft)</span> public static RelativeDateTimeFormatter <i>getInstance</i>(ULocale, NumberFormat, RelativeDateTimeFormatter.Style, DisplayContext)</li>
+<li><span style='color:orange'>(draft)</span> public static RelativeDateTimeFormatter <i>getInstance</i>(java.util.Locale)</li>
+<li><span style='color:orange'>(draft)</span> public static RelativeDateTimeFormatter <i>getInstance</i>(java.util.Locale, NumberFormat)</li>
+</ul>
+RelativeDateTimeFormatter.Style
+<ul>
+<li><span style='color:orange'>(draft)</span> public static final RelativeDateTimeFormatter.Style LONG</li>
+<li><span style='color:orange'>(draft)</span> public static final RelativeDateTimeFormatter.Style NARROW</li>
+<li><span style='color:orange'>(draft)</span> public static final RelativeDateTimeFormatter.Style SHORT</li>
+</ul>
+SimpleDateFormat
+<ul>
+<li><span style='color:orange'>(draft)</span> public NumberFormat <i>getNumberFormat</i>(char)</li>
+<li><span style='color:orange'>(draft)</span> public void <i>setNumberFormat</i>(java.lang.String, NumberFormat)</li>
+</ul>
+SpoofChecker
+<ul>
+<li><span style='color:orange'>(draft)</span> public java.util.Set<java.util.Locale> <i>getAllowedJavaLocales</i>()</li>
+</ul>
+SpoofChecker.Builder
+<ul>
+<li><span style='color:orange'>(draft)</span> public SpoofChecker.Builder <i>setAllowedJavaLocales</i>(java.util.Set<java.util.Locale>)</li>
+</ul>
+TimeZoneFormat
+<ul>
+<li><span style='color:orange'>(draft)</span> public static TimeZoneFormat <i>getInstance</i>(java.util.Locale)</li>
+</ul>
+TimeZoneFormat.ParseOption
+<ul>
+<li><span style='color:orange'>(draft)</span> public static final TimeZoneFormat.ParseOption TZ_DATABASE_ABBREVIATIONS</li>
+</ul>
+TimeZoneNames
+<ul>
+<li><span style='color:orange'>(draft)</span> public static TimeZoneNames <i>getInstance</i>(java.util.Locale)</li>
+<li><span style='color:orange'>(draft)</span> public static TimeZoneNames <i>getTZDBInstance</i>(ULocale)</li>
+</ul>
+UTF16
+<ul>
+<li><span style='color:orange'>(draft)</span> public static int <i>compareCodePoint</i>(int, java.lang.CharSequence)</li>
+<li><span style='color:orange'>(draft)</span> public static int <i>getSingleCodePoint</i>(java.lang.CharSequence)</li>
+</ul>
+UnicodeSet
+<ul>
+<li><span style='color:green'>(stable)</span> public UnicodeSet <i>add</i>(java.lang.Iterable<?>)</li>
+<li><span style='color:green'>(stable)</span> public UnicodeSet <i>addAll</i>(T...)</li>
+<li><span style='color:green'>(stable)</span> public UnicodeSet <i>addAll</i>(java.lang.Iterable<?>)</li>
+<li><span style='color:green'>(stable)</span> public static int <i>compare</i>(int, java.lang.CharSequence)</li>
+<li><span style='color:green'>(stable)</span> public static int <i>compare</i>(java.lang.CharSequence, int)</li>
+<li><span style='color:green'>(stable)</span> public final UnicodeSet <i>complement</i>(java.lang.CharSequence)</li>
+<li><span style='color:green'>(stable)</span> public final UnicodeSet <i>complementAll</i>(java.lang.CharSequence)</li>
+<li><span style='color:green'>(stable)</span> public final boolean <i>contains</i>(java.lang.CharSequence)</li>
+<li><span style='color:green'>(stable)</span> public boolean <i>containsAll</i>(java.lang.Iterable<T>)</li>
+<li><span style='color:green'>(stable)</span> public boolean <i>containsNone</i>(java.lang.CharSequence)</li>
+<li><span style='color:green'>(stable)</span> public boolean <i>containsNone</i>(java.lang.Iterable<T>)</li>
+<li><span style='color:green'>(stable)</span> public final boolean <i>containsSome</i>(java.lang.CharSequence)</li>
+<li><span style='color:green'>(stable)</span> public final boolean <i>containsSome</i>(java.lang.Iterable<T>)</li>
+<li><span style='color:green'>(stable)</span> public static UnicodeSet <i>from</i>(java.lang.CharSequence)</li>
+<li><span style='color:green'>(stable)</span> public static UnicodeSet <i>fromAll</i>(java.lang.CharSequence)</li>
+<li><span style='color:orange'>(draft)</span> public java.lang.Iterable<UnicodeSet.EntryRange> <i>ranges</i>()</li>
+<li><span style='color:green'>(stable)</span> public final UnicodeSet <i>remove</i>(java.lang.CharSequence)</li>
+<li><span style='color:green'>(stable)</span> public final UnicodeSet <i>removeAll</i>(java.lang.CharSequence)</li>
+<li><span style='color:green'>(stable)</span> public UnicodeSet <i>removeAll</i>(java.lang.Iterable<T>)</li>
+<li><span style='color:green'>(stable)</span> public final UnicodeSet <i>retain</i>(java.lang.CharSequence)</li>
+<li><span style='color:green'>(stable)</span> public final UnicodeSet <i>retainAll</i>(java.lang.CharSequence)</li>
+<li><span style='color:green'>(stable)</span> public UnicodeSet <i>retainAll</i>(java.lang.Iterable<T>)</li>
+<li><span style='color:green'>(stable)</span> public java.util.Collection<java.lang.String> <i>strings</i>()</li>
+</ul>
+UnicodeSetSpanner.CountMethod
+<ul>
+<li><span style='color:orange'>(draft)</span> public static final UnicodeSetSpanner.CountMethod MIN_ELEMENTS</li>
+<li><span style='color:orange'>(draft)</span> public static final UnicodeSetSpanner.CountMethod WHOLE_SPAN</li>
+</ul>
+UnicodeSetSpanner.TrimOption
+<ul>
+<li><span style='color:orange'>(draft)</span> public static final UnicodeSetSpanner.TrimOption BOTH</li>
+<li><span style='color:orange'>(draft)</span> public static final UnicodeSetSpanner.TrimOption LEADING</li>
+<li><span style='color:orange'>(draft)</span> public static final UnicodeSetSpanner.TrimOption TRAILING</li>
+</ul>
+</ul>
+
+<h3>Package com.ibm.icu.util</h3>
+<ul>
+<li><span style='color:orange'>(draft)</span> public static final class <i>Calendar.WeekData</i></li>
+<li><span style='color:orange'>(draft)</span> public static enum <i>Currency.CurrencyUsage</i></li>
+Calendar
+<ul>
+<li><span style='color:orange'>(draft)</span> public Calendar.WeekData <i>getWeekData</i>()</li>
+<li><span style='color:orange'>(draft)</span> public static Calendar.WeekData <i>getWeekDataForRegion</i>(java.lang.String)</li>
+<li><span style='color:orange'>(draft)</span> public Calendar <i>setWeekData</i>(Calendar.WeekData)</li>
+</ul>
+Currency
+<ul>
+<li><span style='color:orange'>(draft)</span> public static java.lang.String[] <i>getAvailableCurrencyCodes</i>(java.util.Locale, java.util.Date)</li>
+<li><span style='color:orange'>(draft)</span> public int <i>getDefaultFractionDigits</i>(Currency.CurrencyUsage)</li>
+<li><span style='color:orange'>(draft)</span> public double <i>getRoundingIncrement</i>(Currency.CurrencyUsage)</li>
+</ul>
+Currency.CurrencyUsage
+<ul>
+<li><span style='color:orange'>(draft)</span> public static final Currency.CurrencyUsage CASH</li>
+<li><span style='color:orange'>(draft)</span> public static final Currency.CurrencyUsage STANDARD</li>
+</ul>
+MeasureUnit
+<ul>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit ACRE_FOOT</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit AMPERE</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit ASTRONOMICAL_UNIT</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit BIT</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit BUSHEL</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit BYTE</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit CALORIE</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit CARAT</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit CENTILITER</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit CUBIC_CENTIMETER</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit CUBIC_FOOT</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit CUBIC_INCH</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit CUBIC_METER</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit CUBIC_YARD</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit CUP</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit DECILITER</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit DECIMETER</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit FATHOM</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit FLUID_OUNCE</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit FOODCALORIE</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit FURLONG</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit GALLON</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit GIGABIT</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit GIGABYTE</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit GIGAHERTZ</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit GIGAWATT</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit HECTOLITER</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit HERTZ</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit JOULE</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit KARAT</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit KELVIN</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit KILOBIT</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit KILOBYTE</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit KILOCALORIE</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit KILOHERTZ</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit KILOJOULE</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit KILOWATT_HOUR</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit LITER_PER_KILOMETER</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit LUX</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit MEGABIT</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit MEGABYTE</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit MEGAHERTZ</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit MEGALITER</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit MEGAWATT</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit METER_PER_SECOND_SQUARED</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit METRIC_TON</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit MICROGRAM</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit MICROMETER</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit MICROSECOND</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit MILE_PER_GALLON</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit MILLIAMPERE</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit MILLIGRAM</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit MILLILITER</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit MILLIMETER_OF_MERCURY</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit MILLIWATT</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit NANOMETER</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit NANOSECOND</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit NAUTICAL_MILE</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit OHM</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit OUNCE_TROY</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit PARSEC</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit PINT</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit POUND_PER_SQUARE_INCH</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit QUART</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit RADIAN</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit SQUARE_CENTIMETER</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit SQUARE_INCH</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit SQUARE_YARD</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit STONE</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit TABLESPOON</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit TEASPOON</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit TERABIT</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit TERABYTE</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit TON</li>
+<li><span style='color:orange'>(draft)</span> public static final MeasureUnit VOLT</li>
+</ul>
+ULocale
+<ul>
+<li><span style='color:orange'>(draft)</span> public boolean <i>isRightToLeft</i>()</li>
+<li><span style='color:orange'>(draft)</span> public static java.lang.String <i>toLegacyKey</i>(java.lang.String)</li>
+<li><span style='color:orange'>(draft)</span> public static java.lang.String <i>toLegacyType</i>(java.lang.String, java.lang.String)</li>
+<li><span style='color:orange'>(draft)</span> public static java.lang.String <i>toUnicodeLocaleKey</i>(java.lang.String)</li>
+<li><span style='color:orange'>(draft)</span> public static java.lang.String <i>toUnicodeLocaleType</i>(java.lang.String, java.lang.String)</li>
+</ul>
+VersionInfo
+<ul>
+<li><span style='color:green'>(stable)</span> public static final VersionInfo UNICODE_7_0</li>
+</ul>
+</ul>
+
+<hr/>
+<p><i><font size="-1">Contents generated by ReportAPI tool on Tue Sep 16 15:13:43 EDT 2014<br/>Copyright (C) 2014, International Business Machines Corporation, All Rights Reserved.</font></i></p>
+</body>
+</html>
diff --git a/build.properties b/build.properties
new file mode 100644
index 0000000..a9956d0
--- /dev/null
+++ b/build.properties
@@ -0,0 +1,9 @@
+#*******************************************************************************
+#* Copyright (C) 2009-2014, International Business Machines Corporation and *
+#* others. All Rights Reserved. *
+#*******************************************************************************
+api.report.version = 54
+api.report.prev.version = 53
+release.file.ver = 54rc
+api.doc.version = 54 Release Candidate
+
diff --git a/build.xml b/build.xml
new file mode 100644
index 0000000..694827d
--- /dev/null
+++ b/build.xml
@@ -0,0 +1,2005 @@
+<!--
+*******************************************************************************
+* Copyright (C) 1997-2014, International Business Machines Corporation and *
+* others. All Rights Reserved. *
+*******************************************************************************
+-->
+<project name="icu4j" default="jar" basedir="."
+ xmlns:jacoco="antlib:org.jacoco.ant">
+
+ <property file="build-local.properties"/>
+ <property file="build.properties"/>
+
+ <property name="shared.dir" value="main/shared"/>
+ <import file="${shared.dir}/build/common-targets.xml"/>
+
+ <property environment="env"/>
+
+ <!-- icu4j binaries -->
+ <property name="icu4j.jar.file" value="icu4j.jar"/>
+ <property name="icu4jtests.jar.file" value="icu4jtests.jar"/>
+ <property name="icu4j-charset.jar.file" value="icu4j-charset.jar"/>
+ <property name="icu4j-localespi.jar.file" value="icu4j-localespi.jar"/>
+
+ <property name="icu4jdemos.jar.file" value="icu4jdemos.jar"/>
+
+ <!-- icu4j API doc jar file -->
+ <property name="icu4jdocs.jar.file" value="icu4j-docs.jar"/>
+
+ <!-- icu4j src jar files -->
+ <property name="icu4j-src.jar.file" value="icu4j-src.jar"/>
+ <property name="icu4j-charset-src.jar.file" value="icu4j-charset-src.jar"/>
+ <property name="icu4j-localespi-src.jar.file" value="icu4j-localespi-src.jar"/>
+
+ <!-- icu4j source package archive files -->
+ <property name="icu4jsrc.zip.file" value="icu4j.zip"/>
+ <property name="icu4jsrc.tgz.file" value="icu4j.tgz"/>
+
+ <!-- icu4j versioned release files -->
+ <property name="icu4j.jar.versioned.file" value="icu4j-${release.file.ver}.jar"/>
+ <property name="icu4j-charset.jar.versioned.file" value="icu4j-charset-${release.file.ver}.jar"/>
+ <property name="icu4j-localespi.jar.versioned.file" value="icu4j-localespi-${release.file.ver}.jar"/>
+
+ <property name="icu4j-src.jar.versioned.file" value="icu4j-${release.file.ver}-src.jar"/>
+ <property name="icu4j-charset-src.jar.versioned.file" value="icu4j-charset-${release.file.ver}-src.jar"/>
+ <property name="icu4j-localespi-src.jar.versioned.file" value="icu4j-localespi-${release.file.ver}-src.jar"/>
+
+ <property name="icu4jdocs.jar.versioned.file" value="icu4j-${release.file.ver}-docs.jar"/>
+
+ <!-- <property name="icu4jsrc.zip.versioned.file" value="icu4j-${release.file.ver}.zip"/> -->
+ <property name="icu4jsrc.tgz.versioned.file" value="icu4j-${release.file.ver}.tgz"/>
+
+ <!-- API doc -->
+ <property name="icu4j.api.doc.title" value="ICU4J ${api.doc.version} API Specification"/>
+ <property name="icu4j.api.doc.window.title" value="ICU4J ${api.doc.version}"/>
+ <property name="icu4j.api.doc.header" value="ICU4J ${api.doc.version}"/>
+ <property name="icu4j.api.doc.jdk.link" value="http://docs.oracle.com/javase/7/docs/api/"/>
+
+ <!-- directories -->
+ <property name="release.dir" value="release"/>
+ <property name="doc.dir" value="doc"/>
+ <property name="cldr.util.out.dir" value="${out.dir}/cldr_util"/>
+ <property name="cldr.release.dir" value="release_cldr"/>
+
+ <!-- Java version check -->
+ <condition property="is.java6.plus">
+ <or>
+ <contains string="${java.version}" substring="1.6."/>
+ <contains string="${java.version}" substring="1.7."/>
+ <contains string="${java.version}" substring="1.8."/>
+ </or>
+ </condition>
+ <condition property="is.java5">
+ <contains string="${java.version}" substring="1.5."/>
+ </condition>
+ <fail message="The JDK version is too old or unknown.">
+ <condition>
+ <not>
+ <or>
+ <isset property="is.java6.plus"/>
+ <isset property="is.java5"/>
+ </or>
+ </not>
+ </condition>
+ </fail>
+
+ <condition property="is.java7.plus">
+ <or>
+ <contains string="${java.version}" substring="1.7."/>
+ <contains string="${java.version}" substring="1.8."/>
+ </or>
+ </condition>
+
+ <!-- Build environment info -->
+ <property name="env.COMPUTERNAME" value="${env.HOSTNAME}"/>
+ <target name="info" description="Display the build environment information">
+ <echo message="----- Build Environment Information -------------------"/>
+ <echo message="Java Home: ${java.home}"/>
+ <echo message="Java Version: ${java.version}"/>
+ <echo message="Ant Home: ${ant.home}"/>
+ <echo message="Ant Version: ${ant.version}"/>
+ <echo message="OS: ${os.name}"/>
+ <echo message="OS Version: ${os.version}"/>
+ <echo message="OS Arch: ${os.arch}"/>
+ <echo message="Host: ${env.COMPUTERNAME}"/>
+ <echo message="-------------------------------------------------------"/>
+ </target>
+
+ <target name="clean" description="Clean up build outputs">
+ <ant dir="${icu4j.core.dir}" target="clean" inheritAll="false"/>
+ <ant dir="${icu4j.collate.dir}" target="clean" inheritAll="false"/>
+ <ant dir="${icu4j.charset.dir}" target="clean" inheritAll="false"/>
+ <ant dir="${icu4j.currdata.dir}" target="clean" inheritAll="false"/>
+ <ant dir="${icu4j.langdata.dir}" target="clean" inheritAll="false"/>
+ <ant dir="${icu4j.localespi.dir}" target="clean" inheritAll="false"/>
+ <ant dir="${icu4j.regiondata.dir}" target="clean" inheritAll="false"/>
+ <ant dir="${icu4j.translit.dir}" target="clean" inheritAll="false"/>
+ <ant dir="${icu4j.test-framework.dir}" target="clean" inheritAll="false"/>
+ <ant dir="${icu4j.core-tests.dir}" target="clean" inheritAll="false"/>
+ <ant dir="${icu4j.collate-tests.dir}" target="clean" inheritAll="false"/>
+ <ant dir="${icu4j.charset-tests.dir}" target="clean" inheritAll="false"/>
+ <ant dir="${icu4j.localespi-tests.dir}" target="clean" inheritAll="false"/>
+ <ant dir="${icu4j.packaging-tests.dir}" target="clean" inheritAll="false"/>
+ <ant dir="${icu4j.translit-tests.dir}" target="clean" inheritAll="false"/>
+ <ant dir="${icu4j.testall.dir}" target="clean" inheritAll="false"/>
+ <ant dir="${icu4j.build-tools.dir}" target="clean" inheritAll="false"/>
+ <ant dir="${icu4j.tools.dir}" target="clean" inheritAll="false"/>
+ <ant dir="${icu4j.demos.dir}" target="clean" inheritAll="false"/>
+ <ant dir="${icu4j.samples.dir}" target="clean" inheritAll="false"/>
+ <ant dir="${icu4j.perf-tests.dir}" target="clean" inheritAll="false"/>
+
+ <!-- delete all .jar files root directory -->
+ <delete>
+ <fileset dir="." includes="icu4j*.jar"/>
+ </delete>
+
+ <delete dir="${release.dir}"/>
+ <delete dir="${doc.dir}"/>
+ <delete dir="${out.dir}"/>
+ <delete dir="${module.dir}"/>
+ <delete dir="${cldr.release.dir}"/>
+
+ <available file="eclipse-build" type="dir" property="eclipse-build.dir.present"/>
+ <antcall target="_clean.eclipse-build"/>
+ </target>
+
+ <target name="_clean.eclipse-build" if="eclipse-build.dir.present">
+ <ant dir="eclipse-build" target="clean" inheritAll="false"/>
+ </target>
+
+ <!-- meta build targets -->
+ <target name="all" depends="info, main, tests, build-tools, tools, demos, samples, perf-tests, jar, docs" description="Build all primary targets"/>
+ <target name="main" depends="info, core, collate, charset, currdata, langdata, regiondata, translit, localespi" description="Build ICU4J runtime library classes"/>
+ <target name="tests" depends="info, core-tests, charset-tests, collate-tests, packaging-tests, translit-tests, testall, localespi-tests" description="Build ICU4J test classes"/>
+
+ <target name="secure" depends="icu4jJar" description="(Deprecated)Build ICU4J API and test classes for running the ICU4J test suite with Java security manager enabled"/>
+
+ <!-- Check to see if JVM_OPTIONS enviroment variable is set. This can be use to set the heap size. -->
+ <property name="env.JVM_OPTIONS" value=""/>
+ <property name="jvm_options" value="${env.JVM_OPTIONS}"/>
+ <target name="check" description="Run the standard ICU4J test suite">
+ <antcall target="_runCheck">
+ <param name="runcheck.arg" value="-n"/>
+ <param name="runcheck.jvmarg" value="${jvm_options} -ea"/>
+ </antcall>
+ </target>
+
+ <target name="exhaustiveCheck" description="Run the standard ICU4J test suite in exhaustive mode">
+ <antcall target="_runCheck">
+ <param name="runcheck.arg" value="-n -e10"/>
+ <param name="runcheck.jvmarg" value="${jvm_options} -ea"/>
+ </antcall>
+ </target>
+
+ <target name="timeZoneCheck" description="Run the complete test for TimeZoneRoundTripAll">
+ <antcall target="_runCheck">
+ <param name="runcheck.arg" value="-n -prop:TimeZoneRoundTripAll=true Core/Format/DateFormat/TimeZoneFormatTest -v"/>
+ <param name="runcheck.jvmarg" value="${jvm_options}"/>
+ </antcall>
+ </target>
+
+ <target name="jdktzCheck" description="Run the standard ICU4J test suite with JDK TimeZone">
+ <antcall target="_runCheck">
+ <param name="runcheck.arg" value="-n"/>
+ <param name="runcheck.jvmarg" value="${jvm_options} -Dcom.ibm.icu.util.TimeZone.DefaultTimeZoneType=JDK"/>
+ </antcall>
+ </target>
+
+ <target name="_runCheck" depends="main, tests">
+ <echo message="JVM argument: ${runcheck.jvmarg} -Djava.awt.headless=true"/>
+ <echo message="Test argument: ${runcheck.arg}"/>
+
+ <java classname="com.ibm.icu.dev.test.TestAll" fork="yes" failonerror="true">
+ <arg line="${runcheck.arg}"/>
+ <jvmarg line="${runcheck.jvmarg} -Djava.awt.headless=true"/>
+ <classpath>
+ <pathelement location="${icu4j.core.jar}"/>
+ <pathelement location="${icu4j.collate.jar}"/>
+ <pathelement location="${icu4j.charset.jar}"/>
+ <pathelement location="${icu4j.currdata.jar}"/>
+ <pathelement location="${icu4j.langdata.jar}"/>
+ <pathelement location="${icu4j.regiondata.jar}"/>
+ <pathelement location="${icu4j.translit.jar}"/>
+ <pathelement location="${icu4j.test-framework.jar}"/>
+ <pathelement location="${icu4j.core-tests.jar}"/>
+ <pathelement location="${icu4j.collate-tests.jar}"/>
+ <pathelement location="${icu4j.charset-tests.jar}"/>
+ <pathelement location="${icu4j.translit-tests.jar}"/>
+ <pathelement location="${icu4j.testall.jar}"/>
+ </classpath>
+ </java>
+ </target>
+
+ <target name="_runTestArgCheck" unless="testarg">
+ <echo message="No test arguments are supplied. Using the default argument '-n'."/>
+ <echo message="For specifying test arguments, use '-Dtestarg=[test args]' as"/>
+ <echo message="ant command line argument. For example:"/>
+ <echo message=" >ant runTest -Dtestarg="Core/Format -e10""/>
+ <echo message="for running ICU4J core format test suite in exhaustive mode."/>
+ <property name="testarg" value="-n"/>
+ </target>
+
+ <target name="runTest" depends="_runTestArgCheck" description="Run a ICU4J test case, without calling any other build targets">
+ <echo message="JVM argument: ${jvm_options} -Djava.awt.headless=true"/>
+ <echo message="Test argument: ${testarg}"/>
+
+ <java classname="com.ibm.icu.dev.test.TestAll" fork="yes" failonerror="true">
+ <arg line="${testarg}"/>
+ <jvmarg line="${jvm_options} -Djava.awt.headless=true"/>
+ <classpath>
+ <pathelement location="${icu4j.core.jar}"/>
+ <pathelement location="${icu4j.collate.jar}"/>
+ <pathelement location="${icu4j.charset.jar}"/>
+ <pathelement location="${icu4j.currdata.jar}"/>
+ <pathelement location="${icu4j.langdata.jar}"/>
+ <pathelement location="${icu4j.regiondata.jar}"/>
+ <pathelement location="${icu4j.translit.jar}"/>
+ <pathelement location="${icu4j.test-framework.jar}"/>
+ <pathelement location="${icu4j.core-tests.jar}"/>
+ <pathelement location="${icu4j.collate-tests.jar}"/>
+ <pathelement location="${icu4j.charset-tests.jar}"/>
+ <pathelement location="${icu4j.translit-tests.jar}"/>
+ <pathelement location="${icu4j.testall.jar}"/>
+ </classpath>
+ </java>
+ </target>
+
+ <target name="packagingCheck" depends="info, core, packaging-tests" description="Run packaging tests">
+ <!-- region data but no language data -->
+ <java classname="com.ibm.icu.dev.test.TestPackaging" fork="yes" failonerror="true">
+ <arg line="-n -w"/>
+ <classpath>
+ <pathelement location="${icu4j.core.jar}"/>
+ <pathelement location="${icu4j.charset.jar}"/>
+ <pathelement location="${icu4j.test-framework.jar}"/>
+ <pathelement location="${icu4j.packaging-tests.jar}"/>
+ <pathelement location="${icu4j.regiondata.jar}"/>
+ </classpath>
+ </java>
+ <!-- language data but no region data -->
+ <java classname="com.ibm.icu.dev.test.TestPackaging" fork="yes" failonerror="true">
+ <arg line="-n -w"/>
+ <classpath>
+ <pathelement location="${icu4j.core.jar}"/>
+ <pathelement location="${icu4j.charset.jar}"/>
+ <pathelement location="${icu4j.test-framework.jar}"/>
+ <pathelement location="${icu4j.packaging-tests.jar}"/>
+ <pathelement location="${icu4j.langdata.jar}"/>
+ </classpath>
+ </java>
+ <!-- neither region nor language data -->
+ <java classname="com.ibm.icu.dev.test.TestPackaging" fork="yes" failonerror="true">
+ <arg line="-n -w"/>
+ <classpath>
+ <pathelement location="${icu4j.core.jar}"/>
+ <pathelement location="${icu4j.charset.jar}"/>
+ <pathelement location="${icu4j.test-framework.jar}"/>
+ <pathelement location="${icu4j.packaging-tests.jar}"/>
+ </classpath>
+ </java>
+ </target>
+
+ <target name="coreCheck" depends="info, core, currdata, langdata, regiondata, core-tests" description="Run only the core tests">
+ <java classname="com.ibm.icu.dev.test.TestAllCore" fork="yes" failonerror="true">
+ <arg line="-n"/>
+ <classpath>
+ <pathelement location="${icu4j.core.jar}"/>
+ <pathelement location="${icu4j.currdata.jar}"/>
+ <pathelement location="${icu4j.langdata.jar}"/>
+ <pathelement location="${icu4j.regiondata.jar}"/>
+ <pathelement location="${icu4j.test-framework.jar}"/>
+ <pathelement location="${icu4j.core-tests.jar}"/>
+ </classpath>
+ </java>
+ </target>
+
+ <target name="collateCheck" depends="info, core, collate, currdata, langdata, regiondata, core-tests, collate-tests" description="Run only the collation tests">
+ <java classname="com.ibm.icu.dev.test.TestAllCollate" fork="yes" failonerror="true">
+ <arg line="-n"/>
+ <classpath>
+ <pathelement location="${icu4j.core.jar}"/>
+ <pathelement location="${icu4j.collate.jar}"/>
+ <pathelement location="${icu4j.test-framework.jar}"/>
+ <pathelement location="${icu4j.collate-tests.jar}"/>
+
+ <!-- for now, collateCheck needs currdata, langdata and regiondata, because of GlobalizationPreferencesTest" -->
+ <pathelement location="${icu4j.currdata.jar}"/>
+ <pathelement location="${icu4j.langdata.jar}"/>
+ <pathelement location="${icu4j.regiondata.jar}"/>
+ <pathelement location="${icu4j.core-tests.jar}"/>
+ </classpath>
+ </java>
+ </target>
+
+ <target name="translitCheck" depends="info, core, translit, translit-tests" description="Run the ICU4J Translit test suite">
+ <java classname="com.ibm.icu.dev.test.TestAllTranslit" fork="yes" failonerror="true">
+ <arg line="-n"/>
+ <classpath>
+ <pathelement location="${icu4j.core.jar}"/>
+ <pathelement location="${icu4j.translit.jar}"/>
+ <pathelement location="${icu4j.test-framework.jar}"/>
+ <pathelement location="${icu4j.translit-tests.jar}"/>
+ </classpath>
+ </java>
+ </target>
+
+ <target name="localespiCheck" if="is.java6.plus" depends="info" description="Run the ICU4J Locale SPI test suite">
+ <antcall target="_runLocalespiCheck"/>
+ </target>
+
+ <target name="_runLocalespiCheck" depends="localespi, localespi-tests">
+ <java classname="com.ibm.icu.dev.test.localespi.TestAll" fork="yes" failonerror="true">
+ <jvmarg line="-Djava.ext.dirs=${icu4j.core.dir}/${jar.dir}${path.separator}${icu4j.localespi.dir}/${jar.dir}${path.separator}${icu4j.collate.dir}/${jar.dir}${path.separator}${icu4j.currdata.dir}/${jar.dir}${path.separator}${icu4j.langdata.dir}/${jar.dir}${path.separator}${icu4j.regiondata.dir}/${jar.dir}${path.separator}${java.ext.dirs}"/>
+ <arg value="-n"/>
+ <classpath>
+ <pathelement location="${icu4j.localespi-tests.jar}"/>
+ <pathelement location="${icu4j.test-framework.jar}"/>
+ </classpath>
+ </java>
+ </target>
+
+ <target name="secureCheck" depends="main, jar, icu4jtestsJar" description="Run the secure (applet-like) ICU4J test suite">
+ <property name="securecheck.arg" value="-n -w"/>
+ <property name="securecheck.jvmarg"
+ value="${jvm_options} -Djava.security.manager -Djava.security.policy=${shared.dir}/data/security.policy -Djava.awt.headless=true"/>
+
+ <echo message="JVM argument: ${securecheck.jvmarg}"/>
+ <echo message="Test argument: ${securecheck.arg}"/>
+
+ <java classname="com.ibm.icu.dev.test.TestAll" fork="yes" failonerror="true">
+ <arg line="${securecheck.arg}"/>
+ <jvmarg line="${securecheck.jvmarg}"/>
+ <classpath>
+ <pathelement location="${icu4j.jar.file}"/>
+ <pathelement location="${icu4j-charset.jar.file}"/>
+ <pathelement location="${icu4jtests.jar.file}"/>
+ </classpath>
+ </java>
+ </target>
+
+ <!-- jar targets -->
+ <target name="jar" depends="icu4jJar, charset, localespi" description="Build ICU4J runtime library jar files">
+ <copy file="${icu4j.charset.jar}" tofile="${icu4j-charset.jar.file}"/>
+ <copy file="${icu4j.localespi.jar}" tofile="${icu4j-localespi.jar.file}" failonerror="false"/>
+ </target>
+
+ <target name="icu4jJar" depends="info, core, collate, currdata, langdata, regiondata, translit" description="Build ICU4J all-in-one core jar">
+ <mkdir dir="${out.dir}"/>
+
+ <!-- manifest -->
+ <copy file="manifest.stub" todir="${out.dir}">
+ <filterset>
+ <filter token="SPECVERSION" value="${jar.spec.version}"/>
+ <filter token="IMPLVERSION" value="${jar.impl.version}"/>
+ <filter token="COPYRIGHT" value="${jar.copyright.info}"/>
+ <filter token="EXECENV" value="${jar.exec.env}"/>
+ </filterset>
+ </copy>
+
+ <!-- jar -->
+ <jar jarfile="${icu4j.jar.file}"
+ compress="true"
+ manifest="${out.dir}/manifest.stub">
+ <fileset dir="${icu4j.core.dir}/${bin.dir}" includes="**/*"/>
+ <fileset dir="${icu4j.collate.dir}/${bin.dir}" includes="**/*"/>
+ <fileset dir="${icu4j.currdata.dir}/${bin.dir}" includes="**/*"/>
+ <fileset dir="${icu4j.langdata.dir}/${bin.dir}" includes="**/*"/>
+ <fileset dir="${icu4j.regiondata.dir}/${bin.dir}" includes="**/*"/>
+ <fileset dir="${icu4j.translit.dir}/${bin.dir}" includes="**/*"/>
+ <fileset dir="${shared.dir}/licenses">
+ <include name="license.html"/>
+ </fileset>
+ </jar>
+ </target>
+
+ <target name="icu4jSrcJar" description="Build icu4j-src.jar">
+ <jar jarfile="${icu4j-src.jar.file}"
+ compress="true">
+ <fileset dir="${icu4j.core.dir}/${src.dir}" includes="**/*.java"/>
+ <fileset dir="${icu4j.collate.dir}/${src.dir}" includes="**/*.java"/>
+ <fileset dir="${icu4j.currdata.dir}/${src.dir}" includes="**/*.java"/>
+ <fileset dir="${icu4j.langdata.dir}/${src.dir}" includes="**/*.java"/>
+ <fileset dir="${icu4j.regiondata.dir}/${src.dir}" includes="**/*.java"/>
+ <fileset dir="${icu4j.translit.dir}/${src.dir}" includes="**/*.java"/>
+ <fileset dir="${shared.dir}/licenses">
+ <include name="license.html"/>
+ </fileset>
+ </jar>
+ </target>
+
+ <target name="icu4jtestsJar" depends="info, tests" description="Build ICU4J all-in-one test jar">
+ <jar jarfile="${icu4jtests.jar.file}"
+ compress="true">
+ <fileset dir="${icu4j.test-framework.dir}/${bin.dir}" includes="**/*"/>
+ <fileset dir="${icu4j.core-tests.dir}/${bin.dir}" includes="**/*"/>
+ <fileset dir="${icu4j.collate-tests.dir}/${bin.dir}" includes="**/*"/>
+ <fileset dir="${icu4j.translit-tests.dir}/${bin.dir}" includes="**/*"/>
+ <fileset dir="${icu4j.charset-tests.dir}/${bin.dir}" includes="**/*"/>
+ <fileset dir="${icu4j.testall.dir}/${bin.dir}" includes="**/*"/>
+ </jar>
+ </target>
+
+ <target name="jarDemos" depends="icu4jJar, demos" description="Build ICU4J demo jar file">
+ <copy file="${icu4j.demos.jar}" tofile="${icu4jdemos.jar.file}"/>
+ </target>
+
+
+ <!-- release targets -->
+ <target name="releaseVer" depends="info, releaseBinaries, releaseSrcJars, releaseDocs, releaseSourceArchiveTgz"
+ description="Build all ICU4J release files for distribution with versioned file names">
+ <!-- binaries -->
+ <move file="${release.dir}/${icu4j.jar.file}" tofile="${release.dir}/${icu4j.jar.versioned.file}"/>
+ <move file="${release.dir}/${icu4j-charset.jar.file}" tofile="${release.dir}/${icu4j-charset.jar.versioned.file}"/>
+ <move file="${release.dir}/${icu4j-localespi.jar.file}" tofile="${release.dir}/${icu4j-localespi.jar.versioned.file}"/>
+
+ <!-- source jars -->
+ <move file="${release.dir}/${icu4j-src.jar.file}" tofile="${release.dir}/${icu4j-src.jar.versioned.file}"/>
+ <move file="${release.dir}/${icu4j-charset-src.jar.file}" tofile="${release.dir}/${icu4j-charset-src.jar.versioned.file}"/>
+ <move file="${release.dir}/${icu4j-localespi-src.jar.file}" tofile="${release.dir}/${icu4j-localespi-src.jar.versioned.file}"/>
+
+ <!-- docs -->
+ <move file="${release.dir}/${icu4jdocs.jar.file}" tofile="${release.dir}/${icu4jdocs.jar.versioned.file}"/>
+
+ <!-- package archive -->
+ <move file="${release.dir}/${icu4jsrc.tgz.file}" tofile="${release.dir}/${icu4jsrc.tgz.versioned.file}"/>
+
+ <!-- md5 checksum file -->
+ <mkdir dir="${out.dir}/checksum"/>
+ <delete dir="${out.dir}/checksum" includes="**/*"/>
+
+ <checksum todir="${out.dir}/checksum" format="MD5SUM">
+ <fileset dir="${release.dir}">
+ <include name="*.jar"/>
+ <include name="*.tgz"/>
+ </fileset>
+ </checksum>
+
+ <concat destfile="${release.dir}/icu4j-${release.file.ver}.md5">
+ <fileset dir="${out.dir}/checksum" includes="*"/>
+ <filterchain>
+ <fixcrlf eol="lf"/>
+ </filterchain>
+ </concat>
+ </target>
+
+ <target name="release" depends="info, releaseBinaries, releaseSrcJars, releaseDocs, releaseSourceArchiveTgz" description="Build all ICU4J release files for distribution">
+ <mkdir dir="${out.dir}/checksum"/>
+ <delete dir="${out.dir}/checksum" includes="**/*"/>
+
+ <checksum todir="${out.dir}/checksum" format="MD5SUM">
+ <fileset dir="${release.dir}">
+ <include name="*.jar"/>
+ <include name="*.tgz"/>
+ </fileset>
+ </checksum>
+
+ <concat destfile="${release.dir}/icu4j.md5">
+ <fileset dir="${out.dir}/checksum" includes="*"/>
+ <filterchain>
+ <fixcrlf eol="lf"/>
+ </filterchain>
+ </concat>
+ </target>
+
+ <target name="releaseBinaries" depends="icu4jJar, charset, localespi" description="Build ICU4J binary files for distribution">
+ <mkdir dir="${release.dir}"/>
+ <copy file="${icu4j.jar.file}" tofile="${release.dir}/${icu4j.jar.file}"/>
+ <copy file="${icu4j.charset.jar}" tofile="${release.dir}/${icu4j-charset.jar.file}"/>
+ <copy file="${icu4j.localespi.jar}" tofile="${release.dir}/${icu4j-localespi.jar.file}"/>
+ </target>
+
+ <target name="releaseSrcJars" depends="icu4jSrcJar" description="Build ICU4J src jar files for distribution">
+ <mkdir dir="${release.dir}"/>
+
+ <!-- icu4j src-jar -->
+ <copy file="${icu4j-src.jar.file}" tofile="${release.dir}/${icu4j-src.jar.file}"/>
+
+ <!-- charset/localespi src-jar -->
+ <ant dir="${icu4j.charset.dir}" target="src-jar" inheritAll="false"/>
+ <ant dir="${icu4j.localespi.dir}" target="src-jar" inheritAll="false"/>
+
+ <copy file="${icu4j.charset.dir}/${out.dir}/lib/${icu4j-charset-src.jar.file}" tofile="${release.dir}/${icu4j-charset-src.jar.file}"/>
+ <copy file="${icu4j.localespi.dir}/${out.dir}/lib/${icu4j-localespi-src.jar.file}" tofile="${release.dir}/${icu4j-localespi-src.jar.file}"/>
+ </target>
+
+
+ <target name="releaseDocs" depends="docs" description="Build ICU4J API reference doc jar file for distribution">
+ <mkdir dir="${release.dir}"/>
+ <jar jarfile="${release.dir}/${icu4jdocs.jar.file}" compress="true" basedir="${doc.dir}"/>
+ </target>
+
+ <property name="src.release.wrk.dir" value="${out.dir}/tmpsrc"/>
+
+ <target name="releaseSourceArchiveZip" description="Build ICU4J source release archive (.zip)">
+ <delete dir="${src.release.wrk.dir}"/>
+ <delete file="${icu4jsrc.zip.file}"/>
+
+ <mkdir dir="${src.release.wrk.dir}"/>
+
+ <fixcrlf srcdir="."
+ destdir="${src.release.wrk.dir}"
+ encoding="UTF-8"
+ eol="crlf">
+ <include name="demos/**/*"/>
+ <include name="main/**/*"/>
+ <include name="perf-tests/**/*"/>
+ <include name="samples/**/*"/>
+ <include name="tools/**/*"/>
+ <include name="*.html"/>
+ <include name="*.xml"/>
+ <include name="*.properties"/>
+ <include name="*.css"/>
+ <include name="*.stub"/>
+ <exclude name="**/out/**/*"/>
+ <exclude name="**/*.jar"/>
+ <exclude name="**/build-local.properties"/>
+ <exclude name="main/tests/core/src/com/ibm/icu/dev/data/rbbi/english.dict"/>
+ <exclude name="main/tests/core/src/com/ibm/icu/dev/test/serializable/data/**/*.dat"/>
+ <exclude name="main/tests/core/src/com/ibm/icu/dev/test/util/Trie2Test.*.tri2"/>
+ <exclude name="tools/build/icu4j*.api*.gz"/>
+ </fixcrlf>
+
+ <mkdir dir="${release.dir}"/>
+ <zip destfile="${release.dir}/${icu4jsrc.zip.file}">
+ <fileset dir="${src.release.wrk.dir}" includes="**/*"/>
+ <fileset dir="${basedir}">
+ <include name="main/shared/data/*.jar"/>
+ <include name="main/tests/core/src/com/ibm/icu/dev/data/rbbi/english.dict"/>
+ <include name="main/tests/core/src/com/ibm/icu/dev/test/serializable/data/**/*.dat"/>
+ <include name="main/tests/core/src/com/ibm/icu/dev/test/util/Trie2Test.*.tri2"/>
+ <include name="tools/build/icu4j*.api*.gz"/>
+ </fileset>
+ </zip>
+
+ <delete dir="${src.release.wrk.dir}"/>
+ </target>
+
+ <target name="releaseSourceArchiveTgz" description="Build ICU4J source release archive (.tgz)">
+ <delete dir="${src.release.wrk.dir}"/>
+ <delete file="${icu4jsrc.tgz.file}"/>
+
+ <mkdir dir="${src.release.wrk.dir}"/>
+
+ <fixcrlf srcdir="."
+ destdir="${src.release.wrk.dir}"
+ encoding="UTF-8"
+ eol="lf">
+ <include name="demos/**/*"/>
+ <include name="main/**/*"/>
+ <include name="perf-tests/**/*"/>
+ <include name="samples/**/*"/>
+ <include name="tools/**/*"/>
+ <include name="*.html"/>
+ <include name="*.xml"/>
+ <include name="*.properties"/>
+ <include name="*.css"/>
+ <include name="*.stub"/>
+ <exclude name="**/out/**/*"/>
+ <exclude name="**/*.jar"/>
+ <exclude name="**/build-local.properties"/>
+ <exclude name="main/tests/core/src/com/ibm/icu/dev/data/rbbi/english.dict"/>
+ <exclude name="main/tests/core/src/com/ibm/icu/dev/test/serializable/data/**/*.dat"/>
+ <exclude name="main/tests/core/src/com/ibm/icu/dev/test/util/Trie2Test.*.tri2"/>
+ <exclude name="tools/build/icu4j*.api*.gz"/>
+ </fixcrlf>
+
+ <property name="icu4jsrc.tar" value="${out.dir}/icu4jsrc.tar"/>
+
+ <tar destfile="${icu4jsrc.tar}" longfile="gnu">
+ <fileset dir="${src.release.wrk.dir}" includes="**/*"/>
+ <fileset dir="${basedir}">
+ <include name="main/shared/data/*.jar"/>
+ <include name="main/tests/core/src/com/ibm/icu/dev/data/rbbi/english.dict"/>
+ <include name="main/tests/core/src/com/ibm/icu/dev/test/serializable/data/**/*.dat"/>
+ <include name="main/tests/core/src/com/ibm/icu/dev/test/util/Trie2Test.*.tri2"/>
+ <include name="tools/build/icu4j*.api*.gz"/>
+ </fileset>
+ </tar>
+
+ <mkdir dir="${release.dir}"/>
+ <gzip destfile="${release.dir}/${icu4jsrc.tgz.file}" src="${icu4jsrc.tar}"/>
+
+ <delete dir="${src.release.wrk.dir}"/>
+ <delete file="${icu4jsrc.tar}"/>
+ </target>
+
+ <!-- findbugs targets -->
+
+ <target name="findbugs" description="Run FindBugs on all library sub projects.">
+ <property name="findbugs.out.dir" value="${out.dir}/findbugs"/>
+ <mkdir dir="${findbugs.out.dir}"/>
+
+ <ant dir="${icu4j.core.dir}" inheritAll="false" target="findbugs"/>
+ <copy file="${icu4j.core.dir}/${out.dir}/fb-core.html" todir="${findbugs.out.dir}"/>
+
+ <ant dir="${icu4j.collate.dir}" inheritAll="false" target="findbugs"/>
+ <copy file="${icu4j.collate.dir}/${out.dir}/fb-collate.html" todir="${findbugs.out.dir}"/>
+
+ <ant dir="${icu4j.currdata.dir}" inheritAll="false" target="findbugs"/>
+ <copy file="${icu4j.currdata.dir}/${out.dir}/fb-currdata.html" todir="${findbugs.out.dir}"/>
+
+ <ant dir="${icu4j.langdata.dir}" inheritAll="false" target="findbugs"/>
+ <copy file="${icu4j.langdata.dir}/${out.dir}/fb-langdata.html" todir="${findbugs.out.dir}"/>
+
+ <ant dir="${icu4j.regiondata.dir}" inheritAll="false" target="findbugs"/>
+ <copy file="${icu4j.regiondata.dir}/${out.dir}/fb-regiondata.html" todir="${findbugs.out.dir}"/>
+
+ <ant dir="${icu4j.translit.dir}" inheritAll="false" target="findbugs"/>
+ <copy file="${icu4j.translit.dir}/${out.dir}/fb-translit.html" todir="${findbugs.out.dir}"/>
+
+
+ <ant dir="${icu4j.charset.dir}" inheritAll="false" target="findbugs"/>
+ <copy file="${icu4j.charset.dir}/${out.dir}/fb-charset.html" todir="${findbugs.out.dir}"/>
+
+ <ant dir="${icu4j.localespi.dir}" inheritAll="false" target="findbugs"/>
+ <copy file="${icu4j.localespi.dir}/${out.dir}/fb-localespi.html" todir="${findbugs.out.dir}"/>
+ </target>
+
+ <!-- compile targets -->
+ <target name="core" description="Build core classes">
+ <ant dir="${icu4j.core.dir}" inheritAll="false"/>
+ </target>
+
+ <target name="collate" depends="core" description="Build collation classes">
+ <ant dir="${icu4j.collate.dir}" inheritAll="false"/>
+ </target>
+
+ <target name="charset" depends="core" description="Build charset classes">
+ <ant dir="${icu4j.charset.dir}" inheritAll="false"/>
+ </target>
+
+ <target name="currdata" depends="core" description="Build currency data classes">
+ <ant dir="${icu4j.currdata.dir}" inheritAll="false"/>
+ </target>
+
+ <target name="langdata" depends="core" description="Build language data classes">
+ <ant dir="${icu4j.langdata.dir}" inheritAll="false"/>
+ </target>
+
+ <target name="localespi" if="is.java6.plus" description="Build Locale SPI classes">
+ <antcall target="_build-localespi"/>
+ </target>
+
+ <target name="_build-localespi" depends="core, collate, currdata, langdata, regiondata">
+ <ant dir="${icu4j.localespi.dir}" inheritAll="false"/>
+ </target>
+
+ <target name="regiondata" depends="core" description="Build region data classes">
+ <ant dir="${icu4j.regiondata.dir}" inheritAll="false"/>
+ </target>
+
+ <target name="translit" depends="core" description="Build translit classes">
+ <ant dir="${icu4j.translit.dir}" inheritAll="false"/>
+ </target>
+
+ <target name="test-framework" depends="core" description="Build test framework classes">
+ <ant dir="${icu4j.test-framework.dir}" inheritAll="false"/>
+ </target>
+
+ <target name="core-tests" depends="core, test-framework" description="Build core tests">
+ <ant dir="${icu4j.core-tests.dir}" inheritAll="false"/>
+ </target>
+
+ <target name="collate-tests" depends="collate, test-framework" description="Build core tests">
+ <ant dir="${icu4j.collate-tests.dir}" inheritAll="false"/>
+ </target>
+
+ <target name="charset-tests" depends="charset, test-framework" description="Build charset tests">
+ <ant dir="${icu4j.charset-tests.dir}" inheritAll="false"/>
+ </target>
+
+ <target name="localespi-tests" if="is.java6.plus" description="Build Locale SPI tests">
+ <antcall target="_build-localespi-tests"/>
+ </target>
+
+ <target name="_build-localespi-tests" depends="localespi, test-framework">
+ <ant dir="${icu4j.localespi-tests.dir}" inheritAll="false"/>
+ </target>
+
+ <target name="packaging-tests" depends="test-framework" description="Build packaging tests">
+ <ant dir="${icu4j.packaging-tests.dir}" inheritAll="false"/>
+ </target>
+
+ <target name="translit-tests" depends="translit, test-framework" description="Build translit tests">
+ <ant dir="${icu4j.translit-tests.dir}" inheritAll="false"/>
+ </target>
+
+ <target name="testall" depends="test-framework" description="Build top level TestAll">
+ <ant dir="${icu4j.testall.dir}" inheritAll="false"/>
+ </target>
+
+ <target name="demos" depends="core, charset, translit" description="Build demo classes">
+ <ant dir="${icu4j.demos.dir}" inheritAll="false"/>
+ </target>
+
+ <target name="samples" depends="core, charset, collate, translit" description="Build sample classes">
+ <ant dir="${icu4j.samples.dir}" inheritAll="false"/>
+ </target>
+
+ <target name="build-tools" description="Build build-tool classes">
+ <ant dir="${icu4j.build-tools.dir}" inheritAll="false"/>
+ </target>
+
+ <target name="tools" depends="core, core-tests, collate, translit, translit-tests" description="Build tool classes">
+ <ant dir="${icu4j.tools.dir}" inheritAll="false"/>
+ </target>
+
+ <target name="perf-tests" if="is.java6.plus" depends="core, charset, collate, tools" description="Build performance test classes">
+ <ant dir="${icu4j.perf-tests.dir}" inheritAll="false"/>
+ </target>
+
+ <!-- doc targets -->
+ <target name="docs" depends="info, build-tools, _checkJCite, _docsWithJCite, _docsWithoutJCite" description="Build API documents"/>
+
+ <target name="_checkJCite" if="env.JCITE_DIR">
+ <fileset dir="${env.JCITE_DIR}" id="jcite.files">
+ <include name="build/*.jar"/>
+ <include name="lib/*.jar"/>
+ </fileset>
+ <pathconvert property="jcite.libs" refid="jcite.files"/>
+
+ <dirset dir="${basedir}" id="jcite.src.dirs">
+ <include name="samples/src"/>
+ <include name="demos/src"/>
+ <include name="main/tests/*/src"/>
+ </dirset>
+ <pathconvert property="jcite.addl.src" refid="jcite.src.dirs"/>
+ </target>
+
+ <target name="_docsStyleSheet">
+ <condition property="docs.style.sheet" value="stylesheet7.css" else="stylesheet.css">
+ <isset property="is.java7.plus"/>
+ </condition>
+ </target>
+
+ <target name="_docsWithJCite" depends="_docsStyleSheet" if="jcite.libs">
+ <echo message="JCite library path: ${jcite.libs}"/>
+ <echo message="JCite additional source path: ${jcite.addl.src}"/>
+ <echo message="Custom stylesheet: ${docs.style.sheet}"/>
+ <javadoc
+ destdir="${doc.dir}"
+ nodeprecatedlist="true"
+ windowtitle="${icu4j.api.doc.window.title}"
+ doctitle="${icu4j.api.doc.title}"
+ header="${icu4j.api.doc.header}"
+ encoding="${java.src.encoding}"
+ docencoding="UTF-8"
+ charset="UTF-8"
+ bottom="<font size=-1>Copyright (c) ${current.year} IBM Corporation and others.</font>"
+ additionalparam="-breakiterator -use -tagletpath ${icu4j.build-tools.jar}${path.separator}${jcite.libs} -taglet com.ibm.icu.dev.tool.docs.ICUTaglet -taglet ch.arrenbrecht.jcite.JCiteTaglet -J-Djcitesourcepath=${jcite.addl.src} -J-Dfile.encoding=UTF-8"
+ link="${icu4j.api.doc.jdk.link}"
+ source="1.5"
+ stylesheetfile="${docs.style.sheet}">
+ <packageset dir="${icu4j.core.dir}/src">
+ <include name="com/ibm/icu/lang/**"/>
+ <include name="com/ibm/icu/math/**"/>
+ <include name="com/ibm/icu/text/**"/>
+ <include name="com/ibm/icu/util/**"/>
+ </packageset>
+ <packageset dir="${icu4j.collate.dir}/src">
+ <include name="com/ibm/icu/text/**"/>
+ </packageset>
+ <packageset dir="${icu4j.translit.dir}/src">
+ <include name="com/ibm/icu/text/**"/>
+ </packageset>
+ <packageset dir="${icu4j.charset.dir}/src">
+ <include name="com/ibm/icu/charset/**"/>
+ </packageset>
+ </javadoc>
+ </target>
+
+ <target name="_docsWithoutJCite" unless="jcite.libs">
+ <javadoc
+ destdir="${doc.dir}"
+ nodeprecatedlist="true"
+ windowtitle="${icu4j.api.doc.window.title}"
+ doctitle="${icu4j.api.doc.title}"
+ header="${icu4j.api.doc.header}"
+ encoding="${java.src.encoding}"
+ docencoding="UTF-8"
+ charset="UTF-8"
+ bottom="<font size=-1>Copyright (c) ${current.year} IBM Corporation and others.</font>"
+ additionalparam="-breakiterator -use -tagletpath ${icu4j.build-tools.jar} -taglet com.ibm.icu.dev.tool.docs.ICUTaglet"
+ link="${icu4j.api.doc.jdk.link}"
+ source="1.5">
+ <packageset dir="${icu4j.core.dir}/src">
+ <include name="com/ibm/icu/lang/**"/>
+ <include name="com/ibm/icu/math/**"/>
+ <include name="com/ibm/icu/text/**"/>
+ <include name="com/ibm/icu/util/**"/>
+ </packageset>
+ <packageset dir="${icu4j.collate.dir}/src">
+ <include name="com/ibm/icu/text/**"/>
+ </packageset>
+ <packageset dir="${icu4j.translit.dir}/src">
+ <include name="com/ibm/icu/text/**"/>
+ </packageset>
+ <packageset dir="${icu4j.charset.dir}/src">
+ <include name="com/ibm/icu/charset/**"/>
+ </packageset>
+ </javadoc>
+ </target>
+
+ <!-- JaCoCo code coverage target -->
+ <taskdef uri="antlib:org.jacoco.ant" resource="org/jacoco/ant/antlib.xml" onerror="ignore">
+ <classpath path="${env.JACOCO_DIR}/lib/jacocoant.jar"/>
+ </taskdef>
+
+ <target name="coverageJaCoCo" depends="jar, tests" description="Run the ICU4J unit tests and generate code coverage report">
+ <property name="jacoco.out.dir" value="${out.dir}/jacoco"/>
+ <property name="jacoco.exec.data.file" value="${jacoco.out.dir}/jacoco.exec"/>
+ <property name="jacoco.report.html.zip" value="${jacoco.out.dir}/report_html.zip"/>
+ <property name="jacoco.report.xml" value="${jacoco.out.dir}/report.xml"/>
+ <property name="jacoco.report.csv" value="${jacoco.out.dir}/report.csv"/>
+
+ <delete dir="${jacoco.out.dir}"/>
+ <mkdir dir="${jacoco.out.dir}"/>
+
+ <jacoco:coverage destfile="${jacoco.exec.data.file}">
+ <java classname="com.ibm.icu.dev.test.TestAll" fork="yes" failonerror="true">
+ <arg value="-n"/>
+ <jvmarg line="${jvm_options} -ea -Djava.awt.headless=true"/>
+ <classpath>
+ <pathelement location="${icu4j.jar.file}"/>
+ <pathelement location="${icu4j-charset.jar.file}"/>
+ <pathelement location="${icu4j.test-framework.jar}"/>
+ <pathelement location="${icu4j.core-tests.jar}"/>
+ <pathelement location="${icu4j.collate-tests.jar}"/>
+ <pathelement location="${icu4j.charset-tests.jar}"/>
+ <pathelement location="${icu4j.translit-tests.jar}"/>
+ <pathelement location="${icu4j.testall.jar}"/>
+ </classpath>
+ </java>
+ </jacoco:coverage>
+
+ <jacoco:report>
+ <executiondata>
+ <file file="${jacoco.exec.data.file}"/>
+ </executiondata>
+
+ <structure name="ICU4J Project">
+ <classfiles>
+ <fileset dir=".">
+ <include name="${icu4j.jar.file}"/>
+ <include name="${icu4j-charset.jar.file}"/>
+ </fileset>
+ </classfiles>
+ <sourcefiles encoding="UTF-8">
+ <fileset dir="${icu4j.core.dir}/src"/>
+ <fileset dir="${icu4j.collate.dir}/src"/>
+ <fileset dir="${icu4j.currdata.dir}/src"/>
+ <fileset dir="${icu4j.langdata.dir}/src"/>
+ <fileset dir="${icu4j.regiondata.dir}/src"/>
+ <fileset dir="${icu4j.translit.dir}/src"/>
+
+ <fileset dir="${icu4j.charset.dir}/src"/>
+ </sourcefiles>
+ </structure>
+
+ <html destfile="${jacoco.report.html.zip}"/>
+ <xml destfile="${jacoco.report.xml}"/>
+ <csv destfile="${jacoco.report.csv}"/>
+ </jacoco:report>
+ </target>
+
+ <!-- Clover code coverage target -->
+ <property name="clover.out.dir" value="${out.dir}/clover"/>
+ <property name="clover.jar" location="${env.CLOVER_DIR}/clover.jar"/>
+ <taskdef resource="cloverlib.xml" classpath="${clover.jar}" onerror="ignore"/>
+
+ <target name="codeCoverage" depends="clean" description="Generate code coverage report with clover">
+ <!-- Set up clover -->
+ <mkdir dir="${clover.out.dir}"/>
+ <clover-setup initstring="${clover.out.dir}/clover.db">
+ <files>
+ <exclude name="**/dev/**/*.java"/>
+ </files>
+ <methodContext name="API" regexp="(.* )?public .*"/>
+ </clover-setup>
+
+ <!-- Build components with clover instrumentation -->
+ <ant dir="${icu4j.core.dir}" inheritAll="false" inheritRefs="true">
+ <property name="build.compiler" value="${build.compiler}"/>
+ </ant>
+ <ant dir="${icu4j.collate.dir}" inheritAll="false" inheritRefs="true">
+ <property name="build.compiler" value="${build.compiler}"/>
+ </ant>
+ <ant dir="${icu4j.charset.dir}" inheritAll="false" inheritRefs="true">
+ <property name="build.compiler" value="${build.compiler}"/>
+ </ant>
+ <ant dir="${icu4j.currdata.dir}" inheritAll="false" inheritRefs="true">
+ <property name="build.compiler" value="${build.compiler}"/>
+ </ant>
+ <ant dir="${icu4j.langdata.dir}" inheritAll="false" inheritRefs="true">
+ <property name="build.compiler" value="${build.compiler}"/>
+ </ant>
+ <ant dir="${icu4j.regiondata.dir}" inheritAll="false" inheritRefs="true">
+ <property name="build.compiler" value="${build.compiler}"/>
+ </ant>
+ <ant dir="${icu4j.translit.dir}" inheritAll="false" inheritRefs="true">
+ <property name="build.compiler" value="${build.compiler}"/>
+ </ant>
+ <ant dir="${icu4j.test-framework.dir}" inheritAll="false" inheritRefs="true">
+ <property name="build.compiler" value="${build.compiler}"/>
+ </ant>
+ <ant dir="${icu4j.core-tests.dir}" inheritAll="false" inheritRefs="true">
+ <property name="build.compiler" value="${build.compiler}"/>
+ </ant>
+ <ant dir="${icu4j.collate-tests.dir}" inheritAll="false" inheritRefs="true">
+ <property name="build.compiler" value="${build.compiler}"/>
+ </ant>
+ <ant dir="${icu4j.charset-tests.dir}" inheritAll="false" inheritRefs="true">
+ <property name="build.compiler" value="${build.compiler}"/>
+ </ant>
+ <ant dir="${icu4j.translit-tests.dir}" inheritAll="false" inheritRefs="true">
+ <property name="build.compiler" value="${build.compiler}"/>
+ </ant>
+ <ant dir="${icu4j.testall.dir}" inheritAll="false" inheritRefs="true">
+ <property name="build.compiler" value="${build.compiler}"/>
+ </ant>
+
+ <!-- Run the test suites -->
+ <java classname="com.ibm.icu.dev.test.TestAll" fork="yes" failonerror="true">
+ <arg value="-n"/>
+ <classpath>
+ <pathelement location="${icu4j.core.jar}"/>
+ <pathelement location="${icu4j.collate.jar}"/>
+ <pathelement location="${icu4j.charset.jar}"/>
+ <pathelement location="${icu4j.currdata.jar}"/>
+ <pathelement location="${icu4j.langdata.jar}"/>
+ <pathelement location="${icu4j.regiondata.jar}"/>
+ <pathelement location="${icu4j.translit.jar}"/>
+ <pathelement location="${icu4j.test-framework.jar}"/>
+ <pathelement location="${icu4j.core-tests.jar}"/>
+ <pathelement location="${icu4j.collate-tests.jar}"/>
+ <pathelement location="${icu4j.charset-tests.jar}"/>
+ <pathelement location="${icu4j.translit-tests.jar}"/>
+ <pathelement location="${icu4j.testall.jar}"/>
+ <pathelement location="${clover.jar}"/>
+ </classpath>
+ </java>
+
+ <!-- Generate HTML coverage report -->
+ <!-- <clover-html-report outdir="${clover.out.dir}/html" title="ICU4J Code Coverage"/> -->
+ <clover-report>
+ <current outfile="${clover.out.dir}/html" title="ICU4J Code Coverage">
+ <format type="html" filter="assert" />
+ </current>
+ </clover-report>
+ </target>
+
+ <!-- Release management targets -->
+ <target name="checktags" depends="info, build-tools" description="Check API tags before release">
+ <javadoc source="1.5"
+ encoding="${java.src.encoding}">
+ <packageset dir="${icu4j.core.dir}/src">
+ <include name="com/ibm/icu/lang/**"/>
+ <include name="com/ibm/icu/math/**"/>
+ <include name="com/ibm/icu/text/**"/>
+ <include name="com/ibm/icu/util/**"/>
+ </packageset>
+ <packageset dir="${icu4j.collate.dir}/src">
+ <include name="com/ibm/icu/**"/>
+ </packageset>
+ <packageset dir="${icu4j.charset.dir}/src">
+ <include name="com/ibm/icu/charset/**"/>
+ </packageset>
+ <doclet name="com.ibm.icu.dev.tool.docs.CheckTags" path="${icu4j.build-tools.jar}"/>
+ </javadoc>
+ </target>
+
+ <target name="gatherapi" depends="info, build-tools" description="Run API database generator tool">
+ <mkdir dir="${out.dir}"/>
+ <javadoc source="1.5"
+ encoding="${java.src.encoding}">
+ <packageset dir="${icu4j.core.dir}/src">
+ <include name="com/ibm/icu/lang/**"/>
+ <include name="com/ibm/icu/math/**"/>
+ <include name="com/ibm/icu/text/**"/>
+ <include name="com/ibm/icu/util/**"/>
+ </packageset>
+ <packageset dir="${icu4j.collate.dir}/src">
+ <include name="com/ibm/icu/text/**"/>
+ <include name="com/ibm/icu/util/**"/>
+ </packageset>
+ <packageset dir="${icu4j.charset.dir}/src">
+ <include name="com/ibm/icu/charset/**"/>
+ </packageset>
+ <packageset dir="${icu4j.translit.dir}/src">
+ <include name="com/ibm/icu/text/**"/>
+ </packageset>
+ <doclet name="com.ibm.icu.dev.tool.docs.GatherAPIData" path="${icu4j.build-tools.jar}">
+ <param name="-name" value="ICU4J ${icu4j.impl.version}"/>
+ <param name="-output" value="${out.dir}/icu4j${api.report.version}.api3"/>
+ <param name="-internal"/>
+ <param name="-version"/>
+ <param name="-gzip"/>
+ </doclet>
+ </javadoc>
+ </target>
+
+ <target name="apireport" depends="info, gatherapi" description="Run API report generator tool">
+ <java classname="com.ibm.icu.dev.tool.docs.ReportAPI"
+ classpath="${icu4j.build-tools.jar}"
+ failonerror="true">
+ <arg value="-old:" />
+ <arg value="${icu4j.build-tools.dir}/icu4j${api.report.prev.version}.api3.gz" />
+ <arg value="-new:" />
+ <arg value="${out.dir}/icu4j${api.report.version}.api3.gz" />
+ <arg value="-html" />
+ <arg value="-out:" />
+ <arg value="${out.dir}/icu4j_compare_${api.report.prev.version}_${api.report.version}.html" />
+ </java>
+ </target>
+
+ <target name="gatherapiOld" depends="info, build-tools" description="Run API database generator tool (Pre Java 5 style)">
+ <mkdir dir="${out.dir}"/>
+ <javadoc source="1.5"
+ encoding="${java.src.encoding}">
+ <packageset dir="${icu4j.core.dir}/src">
+ <include name="com/ibm/icu/lang/**"/>
+ <include name="com/ibm/icu/math/**"/>
+ <include name="com/ibm/icu/text/**"/>
+ <include name="com/ibm/icu/util/**"/>
+ </packageset>
+ <packageset dir="${icu4j.collate.dir}/src">
+ <include name="com/ibm/icu/text/**"/>
+ <include name="com/ibm/icu/util/**"/>
+ </packageset>
+ <packageset dir="${icu4j.charset.dir}/src">
+ <include name="com/ibm/icu/charset/**"/>
+ </packageset>
+ <packageset dir="${icu4j.translit.dir}/src">
+ <include name="com/ibm/icu/text/**"/>
+ </packageset>
+ <doclet name="com.ibm.icu.dev.tool.docs.GatherAPIDataOld" path="${icu4j.build-tools.jar}">
+ <param name="-name" value="ICU4J ${icu4j.impl.version}"/>
+ <param name="-output" value="${out.dir}/icu4j${api.report.version}.api"/>
+ <param name="-internal"/>
+ <param name="-gzip"/>
+ </doclet>
+ </javadoc>
+ </target>
+
+ <target name="apireportOld" depends="info, gatherapiOld" description="Run API report generator tool (Pre Java 5 Style)">
+ <java classname="com.ibm.icu.dev.tool.docs.ReportAPI"
+ classpath="${icu4j.build-tools.jar}"
+ failonerror="true">
+ <arg value="-old:" />
+ <arg value="${icu4j.build-tools.dir}/icu4j${api.report.prev.version}.api.gz" />
+ <arg value="-new:" />
+ <arg value="${out.dir}/icu4j${api.report.version}.api.gz" />
+ <arg value="-html" />
+ <arg value="-internal" />
+ <arg value="-out:" />
+ <arg value="${out.dir}/icu4j_compare_${api.report.prev.version}_${api.report.version}.html" />
+ </java>
+ </target>
+
+ <target name="checkDeprecated" depends="info, build-tools, gatherapi, main"
+ description="Check consistency between javadoc @deprecated and @Deprecated annotation">
+ <java classname="com.ibm.icu.dev.tool.docs.DeprecatedAPIChecker"
+ failonerror="true">
+ <arg value="${out.dir}/icu4j${api.report.version}.api3.gz" />
+ <classpath>
+ <pathelement location="${icu4j.build-tools.jar}"/>
+ <pathelement location="${icu4j.core.jar}"/>
+ <pathelement location="${icu4j.collate.jar}"/>
+ <pathelement location="${icu4j.charset.jar}"/>
+ <pathelement location="${icu4j.currdata.jar}"/>
+ <pathelement location="${icu4j.langdata.jar}"/>
+ <pathelement location="${icu4j.regiondata.jar}"/>
+ <pathelement location="${icu4j.translit.jar}"/>
+ </classpath>
+ </java>
+ </target>
+
+ <target name="draftAPIs" depends="info, gatherapi" description="Run API collector tool and generate draft API report">
+ <java classname="com.ibm.icu.dev.tool.docs.CollectAPI"
+ classpath="${icu4j.build-tools.jar}"
+ failonerror="true">
+ <arg value="-f"/>
+ <arg value="Draft"/>
+ <arg value="-o"/>
+ <arg value="${out.dir}/draftAPIs.html"/>
+ <arg value="${out.dir}/icu4j${api.report.version}.api3.gz" />
+ </java>
+ </target>
+
+ <target name="swatDeprecated" depends="build-tools" description="Convert @deprecated @draft tags to @provisional">
+ <antcall target="_runSwatDeprecated">
+ <param name="swat.deprecated.opt" value="-dep"/>
+ </antcall>
+ </target>
+
+ <target name="swatProvisional" depends="build-tools" description="Convert @provisional tags to @deprecated @draft">
+ <antcall target="_runSwatDeprecated">
+ <param name="swat.deprecated.opt" value="-prov"/>
+ </antcall>
+ </target>
+
+ <target name="_runSwatDeprecated">
+ <java classname="com.ibm.icu.dev.tool.docs.SwatDeprecated"
+ classpath="${icu4j.build-tools.jar}"
+ failonerror="true">
+ <arg value="${swat.deprecated.opt}"/>
+ <arg value="-src"/>
+ <arg value="${icu4j.core.dir}/src"/>
+ <arg value="-dst"/>
+ <arg value="${icu4j.core.dir}/src"/>
+ <arg value="-overwrite"/>
+ <arg value="-verbose"/>
+ </java>
+ <java classname="com.ibm.icu.dev.tool.docs.SwatDeprecated"
+ classpath="${icu4j.build-tools.jar}"
+ failonerror="true">
+ <arg value="${swat.deprecated.opt}"/>
+ <arg value="-src"/>
+ <arg value="${icu4j.charset.dir}/src"/>
+ <arg value="-dst"/>
+ <arg value="${icu4j.charset.dir}/src"/>
+ <arg value="-overwrite"/>
+ <arg value="-verbose"/>
+ </java>
+ </target>
+
+ <target name="serialTestData" depends="main, tests">
+ <property name="serial.test.data.dir" value="${out.dir}/serialTestData"/>
+ <delete dir="${serial.test.data.dir}"/>
+ <mkdir dir="${serial.test.data.dir}"/>
+ <java classname="com.ibm.icu.dev.test.serializable.SerializableWriter" fork="yes" failonerror="true">
+ <arg line="${serial.test.data.dir}"/>
+ <classpath>
+ <pathelement location="${icu4j.core.jar}"/>
+ <pathelement location="${icu4j.collate.jar}"/>
+ <pathelement location="${icu4j.charset.jar}"/>
+ <pathelement location="${icu4j.currdata.jar}"/>
+ <pathelement location="${icu4j.langdata.jar}"/>
+ <pathelement location="${icu4j.regiondata.jar}"/>
+ <pathelement location="${icu4j.translit.jar}"/>
+ <pathelement location="${icu4j.test-framework.jar}"/>
+ <pathelement location="${icu4j.core-tests.jar}"/>
+ </classpath>
+ </java>
+ <echo message="Note: The serialization compatibility test data files were"/>
+ <echo message="created in ${serial.test.data.dir}. Once you confirm"/>
+ <echo message="the test runs clean, you should copy the data file directory to"/>
+ <echo message="main/tests/core/src/com/ibm/icu/dev/test/serializable/data."/>
+ </target>
+
+ <!-- Special packaging targets -->
+ <target name="translitIMEJar" depends="info" description="Build transliterator IME 'icutransime.jar' jar file">
+ <property name="translit.ime.out.dir" value="${out.dir}/translit_ime"/>
+
+ <mkdir dir="${translit.ime.out.dir}/bin"/>
+ <javac destdir="${translit.ime.out.dir}/bin"
+ source="${javac.source}"
+ target="${javac.target}"
+ encoding="${java.src.encoding}"
+ debug="on" deprecation="off">
+ <src path="${icu4j.core.dir}/src"/>
+ <src path="${icu4j.translit.dir}/src"/>
+ <src path="${icu4j.tools.dir}/src"/>
+ <include name="com/ibm/icu/dev/tool/ime/translit/*.java"/>
+ </javac>
+
+ <copy file="${icu4j.tools.dir}/src/com/ibm/icu/dev/tool/ime/translit/Transliterator.properties"
+ todir="${translit.ime.out.dir}/bin/com/ibm/icu/dev/tool/ime/translit"/>
+
+ <mkdir dir="${translit.ime.out.dir}/lib"/>
+ <jar jarfile="${translit.ime.out.dir}/lib/icutransime.jar"
+ compress="true"
+ basedir="${translit.ime.out.dir}/bin"
+ includes="com/ibm/icu/dev/tool/ime/translit/**/*"
+ manifest="${icu4j.tools.dir}/src/com/ibm/icu/dev/tool/ime/translit/manifest.stub">
+ <metainf dir="${icu4j.tools.dir}/src/com/ibm/icu/dev/tool/ime/translit" includes="services/*" />
+ </jar>
+ </target>
+
+ <target name="indicIMEJar" depends="info" description="Build indic IME 'icuindicime.jar' jar file">
+ <property name="indic.ime.out.dir" value="${out.dir}/indic_ime"/>
+
+ <mkdir dir="${indic.ime.out.dir}/bin"/>
+ <javac destdir="${indic.ime.out.dir}/bin"
+ source="${javac.source}"
+ target="${javac.target}"
+ encoding="${java.src.encoding}"
+ debug="on" deprecation="off">
+ <src path="${icu4j.core.dir}/src"/>
+ <src path="${icu4j.tools.dir}/src"/>
+ <include name="com/ibm/icu/dev/tool/ime/indic/*.java"/>
+ </javac>
+
+ <copy file="${icu4j.tools.dir}/src/com/ibm/icu/dev/tool/ime/indic/DisplayNames.properties"
+ todir="${indic.ime.out.dir}/bin/com/ibm/icu/dev/tool/ime/indic"/>
+
+ <mkdir dir="${indic.ime.out.dir}/lib"/>
+ <jar jarfile="${indic.ime.out.dir}/lib/icuindicime.jar"
+ compress="true"
+ basedir="${indic.ime.out.dir}/bin"
+ includes="com/ibm/icu/dev/tool/ime/indic/**/*"
+ manifest="${icu4j.tools.dir}/src/com/ibm/icu/dev/tool/ime/indic/manifest.stub">
+ <metainf dir="${icu4j.tools.dir}/src/com/ibm/icu/dev/tool/ime/indic" includes="services/*" />
+ </jar>
+ </target>
+
+ <target name="cldrUtil" depends="icu4jJar" description="Build Utilities for CLDR tooling">
+ <mkdir dir="${cldr.util.out.dir}/bin"/>
+ <javac destdir="${cldr.util.out.dir}/bin"
+ source="${javac.source}"
+ target="${javac.target}"
+ encoding="${java.src.encoding}"
+ debug="on" deprecation="off"
+ classpath="${icu4j.jar.file}">
+
+ <src path="${icu4j.tools.dir}/src"/>
+ <src path="${icu4j.translit-tests.dir}/src"/>
+ <src path="${icu4j.test-framework.dir}/src"/>
+
+ <include name="com/ibm/icu/dev/test/TestFmwk.java" />
+ <include name="com/ibm/icu/dev/util/*.java" />
+ <include name="com/ibm/icu/dev/tool/UOption.java" />
+ </javac>
+
+ <mkdir dir="${cldr.util.out.dir}/lib"/>
+ <jar jarfile="${cldr.util.out.dir}/lib/utilities.jar"
+ compress="true"
+ basedir="${cldr.util.out.dir}/bin">
+ <include name="com/ibm/icu/dev/test/*.class"/>
+ <include name="com/ibm/icu/dev/util/*.class"/>
+ <include name="com/ibm/icu/dev/tool/UOption*.class"/>
+ </jar>
+ </target>
+
+ <target name="releaseCLDR" depends="icu4jJar,icu4jSrcJar,cldrUtil" description="Build release files for CLDR tooling">
+ <mkdir dir="${cldr.release.dir}"/>
+ <!-- icu4j.jar -->
+ <copy file="${icu4j.jar.file}" todir="${cldr.release.dir}"/>
+ <!-- icu4j-src.jar -->
+ <copy file="${icu4j-src.jar.file}" todir="${cldr.release.dir}"/>
+ <!-- utilities.jar -->
+ <copy file="${cldr.util.out.dir}/lib/utilities.jar" todir="${cldr.release.dir}"/>
+ <!-- utilities-src.jar -->
+ <jar jarfile="${cldr.release.dir}/utilities-src.jar" compress="true">
+ <fileset dir="${icu4j.test-framework.dir}/${src.dir}">
+ <include name="com/ibm/icu/dev/test/TestFmwk.java"/>
+ <include name="com/ibm/icu/dev/test/*Log*.java"/>
+ <include name="com/ibm/icu/dev/test/TestUtil.java"/>
+ <include name="com/ibm/icu/dev/test/UTF16Util.java"/>
+ </fileset>
+ <fileset dir="${icu4j.test-framework.dir}/${src.dir}" includes="com/ibm/icu/dev/util/*.java"/>
+ <fileset dir="${icu4j.translit-tests.dir}/${src.dir}" includes="com/ibm/icu/dev/util/*.java"/>
+ <fileset dir="${icu4j.tools.dir}/${src.dir}" includes="com/ibm/icu/dev/tool/UOption.java"/>
+ </jar>
+ </target>
+
+ <target name="xliff" description="Build xliff converter tool">
+ <property name="xliff.out.dir" value="${out.dir}/xliff"/>
+
+ <mkdir dir="${xliff.out.dir}/bin"/>
+ <javac destdir="${xliff.out.dir}/bin"
+ source="1.3"
+ target="1.3"
+ encoding="${java.src.encoding}"
+ debug="on" deprecation="off">
+ <src path="${icu4j.tools.dir}/src"/>
+ <include name="com/ibm/icu/dev/tool/localeconverter/CalculateCRC32.java"/>
+ <include name="com/ibm/icu/dev/tool/localeconverter/XLIFF2ICUConverter.java"/>
+ <include name="com/ibm/icu/dev/tool/UOption.java"/>
+ </javac>
+
+ <mkdir dir="${xliff.out.dir}/lib"/>
+
+ <jar jarfile="${xliff.out.dir}/lib/xliff-src.jar"
+ compress="true"
+ basedir="${icu4j.tools.dir}/src">
+ <include name="com/ibm/icu/dev/tool/localeconverter/CalculateCRC32.java"/>
+ <include name="com/ibm/icu/dev/tool/localeconverter/XLIFF2ICUConverter.java"/>
+ <include name="com/ibm/icu/dev/tool/UOption.java"/>
+ </jar>
+
+ <jar jarfile="${xliff.out.dir}/lib/xliff.jar"
+ compress="true"
+ basedir="${xliff.out.dir}/bin"
+ manifest="${icu4j.tools.dir}/src/com/ibm/icu/dev/tool/localeconverter/manifest.stub"/>
+ </target>
+
+
+ <!-- ICU4J modularization targets -->
+ <property name="module.dir" value="${out.dir}/module"/>
+ <property name="module.bin.dir" value="${module.dir}/bin"/>
+ <property name="module.tests.dir" value="${module.dir}/tests"/>
+ <property name="module.jar.dir" value="${module.dir}/lib"/>
+ <property name="module.jar" value="${module.jar.dir}/icu4j-module.jar"/>
+
+ <target name="moduleJar" description="Create a ICU4J module jar file">
+ <mkdir dir="${module.jar.dir}"/>
+ <jar jarfile="${module.jar}"
+ compress="true"
+ basedir="${module.bin.dir}">
+ <manifest>
+ <attribute name="Built-By" value="${corp}" />
+ <section name="com/ibm/icu">
+ <attribute name="Specification-Title" value="ICU4J Modularized Build" />
+ <attribute name="Specification-Version" value="${jar.spec.version}" />
+ <attribute name="Specification-Vendor" value="ICU" />
+ <attribute name="Implementation-Title" value=" ICU for Java Module" />
+ <attribute name="Implementation-Version" value="${jar.impl.version}" />
+ <attribute name="Implementation-Vendor" value="${corp}" />
+ <attribute name="Implementation-Vendor-Id" value="com.ibm" />
+ <attribute name="Copyright-Info" value="${jar.copyright.info}" />
+ <attribute name="Sealed" value="false" />
+ </section>
+ </manifest>
+ </jar>
+ <copy file="${module.jar}" tofile="icu4j.jar"/>
+ </target>
+
+ <target name="moduleCheck" description="Run tests for a ICU4J module jar">
+ <java classname="com.ibm.icu.dev.test.TestAll" fork="yes" failonerror="true">
+ <arg value="-nothrow"/>
+ <arg value="-nodata"/>
+ <classpath>
+ <pathelement location="${module.jar}"/>
+ <pathelement location="${module.tests.dir}"/>
+ </classpath>
+ </java>
+ </target>
+
+ <patternset id="common.test.sources">
+ <include name="com/ibm/icu/dev/test/TestFmwk.java"/>
+ <include name="com/ibm/icu/dev/test/TestLog.java"/>
+ <include name="com/ibm/icu/dev/test/TestUtil.java"/>
+ <include name="com/ibm/icu/dev/test/UTF16Util.java"/>
+ <include name="com/ibm/icu/dev/test/TestAll.java"/>
+ <include name="com/ibm/icu/dev/test/TestAllCore.java"/>
+ </patternset>
+
+ <!-- Break Iterator -->
+ <target name="breakIterator" depends="_copyFullPropsData" description="Modular build of break iterator services">
+ <mkdir dir="${module.bin.dir}"/>
+ <javac srcdir="${icu4j.core.dir}/src"
+ destdir="${module.bin.dir}"
+ source="${javac.source}"
+ target="${javac.target}"
+ encoding="${java.src.encoding}"
+ debug="on" deprecation="off">
+ <include name="com/ibm/icu/impl/UCharacterName.java"/>
+ <include name="com/ibm/icu/impl/data/*Break*.java"/>
+ <include name="com/ibm/icu/lang/**/*.java"/>
+ <include name="com/ibm/icu/text/*BreakIterator*.java"/>
+ <include name="com/ibm/icu/text/UnicodeSetIterator.java"/>
+ </javac>
+ </target>
+
+ <target name="breakIteratorTests" depends="breakIterator" description="Modular build of break iterator test suite">
+ <mkdir dir="${module.tests.dir}"/>
+ <javac destdir="${module.tests.dir}"
+ source="${javac.source}"
+ target="${javac.target}"
+ encoding="${java.src.encoding}"
+ classpath="${module.bin.dir}"
+ debug="on" deprecation="off">
+ <src path="${icu4j.core.dir}/src"/>
+ <src path="${icu4j.test-framework.dir}/src"/>
+ <src path="${icu4j.core-tests.dir}/src"/>
+ <src path="${icu4j.testall.dir}/src"/>
+
+ <patternset refid="common.test.sources"/>
+ <include name="com/ibm/icu/dev/test/rbbi/**/*.java"/>
+ </javac>
+
+ <copy file="${icu4j.core-tests.dir}/src/com/ibm/icu/dev/test/rbbi/rbbitst.txt"
+ todir="${module.tests.dir}/com/ibm/icu/dev/test/rbbi"/>
+ </target>
+
+ <!-- Calendar -->
+ <target name="calendar" description="Modular build of calendar services">
+ <mkdir dir="${module.bin.dir}"/>
+ <javac srcdir="${icu4j.core.dir}/src"
+ destdir="${module.bin.dir}"
+ source="${javac.source}"
+ target="${javac.target}"
+ encoding="${java.src.encoding}"
+ debug="on" deprecation="off">
+ <include name="com/ibm/icu/impl/data/*Holiday*.java"/>
+ <include name="com/ibm/icu/impl/TimeZoneNames*.java"/>
+ <include name="com/ibm/icu/lang/UCharacter.java"/>
+ <include name="com/ibm/icu/text/UnicodeSetIterator.java"/>
+ <include name="com/ibm/icu/text/NumberFormatServiceShim.java"/>
+ <include name="com/ibm/icu/util/*Calendar*.java"/>
+ </javac>
+
+ <!-- Calendar does not require Collation data, BreakIterator data -->
+ <unjar src="${icu4j.data.jar}" dest="${module.bin.dir}">
+ <patternset>
+ <include name="**/pnames.icu" />
+ <include name="**/ucase.icu" />
+ <include name="**/unorm.icu" />
+ <include name="**/uprops.icu" />
+ <include name="**/unames.icu" />
+ <include name="**/*.res" />
+ <exclude name="**/coll/*.res" />
+ <exclude name="**/translit/*.res" />
+ </patternset>
+ </unjar>
+ <unjar src="${icu4j.tzdata.jar}" dest="${module.bin.dir}">
+ <patternset>
+ <include name="**/*.res" />
+ </patternset>
+ </unjar>
+ </target>
+
+ <target name="calendarTests" depends="calendar" description="Modular build of calendar test suite">
+ <mkdir dir="${module.tests.dir}"/>
+ <javac destdir="${module.tests.dir}"
+ source="${javac.source}"
+ target="${javac.target}"
+ encoding="${java.src.encoding}"
+ classpath="${module.bin.dir}"
+ debug="on" deprecation="off">
+ <src path="${icu4j.core.dir}/src"/>
+ <src path="${icu4j.test-framework.dir}/src"/>
+ <src path="${icu4j.core-tests.dir}/src"/>
+ <src path="${icu4j.testall.dir}/src"/>
+
+ <patternset refid="common.test.sources"/>
+ <include name="com/ibm/icu/dev/test/calendar/**/*.java" />
+ </javac>
+
+ <unjar src="${icu4j.testdata.jar}" dest="${module.tests.dir}">
+ <patternset>
+ <include name="**/calendar.res"/>
+ </patternset>
+ </unjar>
+ </target>
+
+ <!-- Collator -->
+ <!-- this module will soon be obsolete, use the collate jar -->
+ <target name="collator" description="Modular build of collator services">
+ <mkdir dir="${module.bin.dir}"/>
+ <javac destdir="${module.bin.dir}"
+ source="${javac.source}"
+ target="${javac.target}"
+ encoding="${java.src.encoding}"
+ debug="on" deprecation="off">
+ <src path="${icu4j.core.dir}/src"/>
+ <src path="${icu4j.collate.dir}/src"/>
+
+ <include name="com/ibm/icu/impl/coll/*.java"/>
+ <include name="com/ibm/icu/impl/data/*Break*.java"/>
+ <include name="com/ibm/icu/text/*BreakIterator*.java"/>
+ <include name="com/ibm/icu/text/*Collation*.java"/>
+ <include name="com/ibm/icu/text/*Collator*.java"/>
+ <include name="com/ibm/icu/text/Normalizer.java"/>
+ <include name="com/ibm/icu/text/Replaceable.java"/>
+ <include name="com/ibm/icu/text/ReplaceableString.java"/>
+ <include name="com/ibm/icu/text/UnicodeFilter.java"/>
+ <include name="com/ibm/icu/text/UnicodeSetIterator.java"/>
+ <include name="com/ibm/icu/text/UTF16.java"/>
+ </javac>
+
+ <unjar src="${icu4j.data.jar}" dest="${module.bin.dir}">
+ <patternset>
+ <include name="**/*.icu"/>
+ <include name="**/coll/*.res"/>
+ <include name="**/*.brk"/>
+ <include name="**/*.nrm"/>
+ <include name="**/icudt${icu4j.data.version}b/res_index.res"/>
+ <include name="**/keyTypeData.res"/>
+ </patternset>
+ </unjar>
+ </target>
+
+ <target name="collatorTests" depends="collator" description="Modular build of collator test suite">
+ <mkdir dir="${module.tests.dir}"/>
+ <javac destdir="${module.tests.dir}"
+ source="${javac.source}"
+ target="${javac.target}"
+ encoding="${java.src.encoding}"
+ classpath="${module.bin.dir}"
+ debug="on" deprecation="off">
+ <src path="${icu4j.core.dir}/src"/>
+ <src path="${icu4j.test-framework.dir}/src"/>
+ <src path="${icu4j.collate-tests.dir}/src"/>
+ <src path="${icu4j.testall.dir}/src"/>
+
+ <patternset refid="common.test.sources"/>
+ <include name="com/ibm/icu/dev/test/TestAllCollate.java"/>
+ <include name="com/ibm/icu/dev/test/collator/**/*.java"/>
+ <include name="java,com/ibm/icu/dev/test/search/**/*.java"/>
+ <exclude name="com/ibm/icu/dev/test/collator/AlphabeticIndexTest.java"/>
+ <exclude name="com/ibm/icu/dev/test/collator/RandomCollator.java"/>
+ <exclude name="com/ibm/icu/dev/test/collator/IndexCharactersTest.java"/>
+ </javac>
+
+ <copy todir="${module.tests.dir}">
+ <fileset dir="${icu4j.collate-tests.dir}/src">
+ <include name="com/ibm/icu/dev/data/*.txt"/>
+ </fileset>
+ </copy>
+ </target>
+
+ <!-- Compression -->
+ <target name="compression" description="Modular build of compression services">
+ <mkdir dir="${module.bin.dir}"/>
+ <javac srcdir="${icu4j.core.dir}/src"
+ destdir="${module.bin.dir}"
+ source="${javac.source}"
+ target="${javac.target}"
+ encoding="${java.src.encoding}"
+ debug="on" deprecation="off">
+ <include name="com/ibm/icu/text/SCSU.java"/>
+ <include name="com/ibm/icu/text/UnicodeCompressor.java"/>
+ <include name="com/ibm/icu/text/UnicodeDecompressor.java"/>
+ </javac>
+ </target>
+
+ <target name="compressionTests" depends="compression" description="Modular build of compression test suite">
+ <mkdir dir="${module.tests.dir}"/>
+ <javac destdir="${module.tests.dir}"
+ source="${javac.source}"
+ target="${javac.target}"
+ encoding="${java.src.encoding}"
+ classpath="${module.bin.dir}"
+ debug="on" deprecation="off">
+ <src path="${icu4j.core.dir}/src"/>
+ <src path="${icu4j.test-framework.dir}/src"/>
+ <src path="${icu4j.core-tests.dir}/src"/>
+ <src path="${icu4j.testall.dir}/src"/>
+
+ <patternset refid="common.test.sources"/>
+ <include name="com/ibm/icu/dev/test/compression/**/*.java"/>
+ </javac>
+ </target>
+
+ <!-- Format -->
+ <target name="format" description="Modular build of format services">
+ <mkdir dir="${module.bin.dir}"/>
+ <javac srcdir="${icu4j.core.dir}/src"
+ destdir="${module.bin.dir}"
+ source="${javac.source}"
+ target="${javac.target}"
+ encoding="${java.src.encoding}"
+ debug="on" deprecation="off">
+ <include name="com/ibm/icu/impl/LocaleDisplayNamesImpl.java"/>
+ <include name="com/ibm/icu/impl/TimeZoneNames*.java"/>
+ <include name="com/ibm/icu/lang/UCharacter.java"/>
+ <include name="com/ibm/icu/text/BreakIteratorFactory.java"/>
+ <include name="com/ibm/icu/text/*Collator*.java"/>
+ <include name="com/ibm/icu/text/*Format*.java"/>
+ <include name="com/ibm/icu/text/UnicodeSetIterator.java"/>
+ <include name="com/ibm/icu/util/CalendarServiceShim.java"/>
+ </javac>
+
+ <javac srcdir="${icu4j.regiondata.dir}/src"
+ destdir="${module.bin.dir}"
+ source="${javac.source}"
+ target="${javac.target}"
+ encoding="${java.src.encoding}"
+ debug="on" deprecation="off"/>
+
+ <javac srcdir="${icu4j.currdata.dir}/src"
+ destdir="${module.bin.dir}"
+ source="${javac.source}"
+ target="${javac.target}"
+ encoding="${java.src.encoding}"
+ debug="on" deprecation="off"/>
+
+ <unjar src="${icu4j.data.jar}" dest="${module.bin.dir}">
+ <patternset>
+ <include name="**/*.icu"/>
+ <include name="**/*.brk"/>
+ <include name="**/*.res"/>
+ <exclude name="**/translit/*.res"/>
+ </patternset>
+ </unjar>
+ <unjar src="${icu4j.tzdata.jar}" dest="${module.bin.dir}">
+ <patternset>
+ <include name="**/*.res" />
+ </patternset>
+ </unjar>
+ </target>
+
+ <target name="formatTests" depends="format" description="Modular build of format test suite">
+ <mkdir dir="${module.tests.dir}"/>
+ <javac destdir="${module.tests.dir}"
+ source="${javac.source}"
+ target="${javac.target}"
+ encoding="${java.src.encoding}"
+ classpath="${module.bin.dir}"
+ debug="on" deprecation="off">
+ <src path="${icu4j.core.dir}/src"/>
+ <src path="${icu4j.test-framework.dir}/src"/>
+ <src path="${icu4j.core-tests.dir}/src"/>
+ <src path="${icu4j.testall.dir}/src"/>
+
+ <patternset refid="common.test.sources"/>
+ <include name="com/ibm/icu/dev/test/format/**/*.java"/>
+ <exclude name="com/ibm/icu/dev/test/format/GlobalizationPreferencesTest.java"/>
+ </javac>
+
+ <unjar src="${icu4j.testdata.jar}" dest="${module.tests.dir}">
+ <patternset>
+ <include name="**/format.res"/>
+ </patternset>
+ </unjar>
+
+ <copy file="${icu4j.core-tests.dir}/src/com/ibm/icu/dev/test/format/NumberFormatTestCases.txt"
+ todir="${module.tests.dir}/com/ibm/icu/dev/test/format"/>
+
+ </target>
+
+ <!-- Normalizer -->
+ <target name="normalizer" description="Modular build of normalizer services">
+ <mkdir dir="${module.bin.dir}"/>
+ <javac srcdir="${icu4j.core.dir}/src"
+ destdir="${module.bin.dir}"
+ source="${javac.source}"
+ target="${javac.target}"
+ encoding="${java.src.encoding}"
+ debug="on" deprecation="off">
+ <include name="com/ibm/icu/lang/**/*"/>
+ <include name="com/ibm/icu/text/CanonicalIterator.java"/>
+ <include name="com/ibm/icu/text/Normalizer.java"/>
+ <include name="com/ibm/icu/text/Replaceable.java"/>
+ <include name="com/ibm/icu/text/ReplaceableString.java"/>
+ <include name="com/ibm/icu/text/UCharacterIterator.java"/>
+ <include name="com/ibm/icu/text/UForwardCharacterIterator.java"/>
+ <include name="com/ibm/icu/text/UnicodeFilter.java"/>
+ <include name="com/ibm/icu/text/UnicodeSetIterator.java"/>
+ <include name="com/ibm/icu/text/UTF16.java"/>
+ </javac>
+
+ <unjar src="${icu4j.data.jar}" dest="${module.bin.dir}">
+ <patternset>
+ <include name="**/ubidi.icu"/>
+ <include name="**/ucase.icu"/>
+ <include name="**/unorm.icu"/>
+ <include name="**/uprops.icu"/>
+ <include name="**/pnames.icu"/>
+ <include name="**/unames.icu"/>
+ <include name="**/*.nrm"/>
+ </patternset>
+ </unjar>
+ </target>
+
+ <target name="normalizerTests" depends="normalizer" description="Modular build of normalizer test suite">
+ <mkdir dir="${module.tests.dir}"/>
+ <javac destdir="${module.tests.dir}"
+ source="${javac.source}"
+ target="${javac.target}"
+ encoding="${java.src.encoding}"
+ classpath="${module.bin.dir}"
+ debug="on" deprecation="off">
+ <src path="${icu4j.core.dir}/src"/>
+ <src path="${icu4j.test-framework.dir}/src"/>
+ <src path="${icu4j.core-tests.dir}/src"/>
+ <src path="${icu4j.testall.dir}/src"/>
+
+ <patternset refid="common.test.sources"/>
+ <include name="com/ibm/icu/dev/test/normalizer/**/*.java"/>
+ <exclude name="com/ibm/icu/dev/test/normalizer/TestDeprecatedNormalizerAPI.java"/>
+ </javac>
+
+ <copy todir="${module.tests.dir}">
+ <fileset dir="${icu4j.core-tests.dir}/src">
+ <include name="com/ibm/icu/dev/data/unicode/*.txt"/>
+ </fileset>
+ </copy>
+
+ <unjar src="${icu4j.testdata.jar}" dest="${module.tests.dir}">
+ <patternset>
+ <include name="**/testnorm.nrm"/>
+ </patternset>
+ </unjar>
+
+ </target>
+
+ <!-- Character Properties -->
+ <target name="_copyBasicPropsData">
+ <mkdir dir="${module.bin.dir}"/>
+ <unjar src="${icu4j.data.jar}" dest="${module.bin.dir}">
+ <patternset>
+ <include name="**/unorm.icu"/>
+ <include name="**/uprops.icu"/>
+ <include name="**/ubidi.icu"/>
+ <include name="**/ucase.icu"/>
+ <include name="**/pnames.icu"/>
+ <include name="**/unames.icu"/>
+ <include name="**/*.nrm"/>
+ </patternset>
+ </unjar>
+ </target>
+
+ <target name="_copyFullPropsData">
+ <mkdir dir="${module.bin.dir}"/>
+ <unjar src="${icu4j.data.jar}" dest="${module.bin.dir}">
+ <patternset>
+ <include name="**/unorm.icu"/>
+ <include name="**/uprops.icu"/>
+ <include name="**/ubidi.icu"/>
+ <include name="**/ucase.icu"/>
+ <include name="**/unames.icu"/>
+ <include name="**/pnames.icu"/>
+ <include name="**/*.res"/>
+ <include name="**/*.brk"/>
+ <include name="**/*.dict"/>
+ <include name="**/*.nrm"/>
+ <exclude name="**/coll/*.res"/>
+ <exclude name="**/translit/*.res"/>
+ <exclude name="**/rbnf/*.res"/>
+ </patternset>
+ </unjar>
+ <unjar src="${icu4j.tzdata.jar}" dest="${module.bin.dir}">
+ <patternset>
+ <include name="**/*.res" />
+ </patternset>
+ </unjar>
+ </target>
+
+ <target name="_propertiesClasses">
+ <mkdir dir="${module.bin.dir}"/>
+ <javac srcdir="${icu4j.core.dir}/src"
+ destdir="${module.bin.dir}"
+ source="${javac.source}"
+ target="${javac.target}"
+ encoding="${java.src.encoding}"
+ debug="on" deprecation="off">
+ <include name="com/ibm/icu/impl/data/*Break*.java"/>
+ <include name="com/ibm/icu/lang/**/*"/>
+ <include name="com/ibm/icu/text/*BreakDictionary*.java"/>
+ <include name="com/ibm/icu/text/*BreakIterator*.java"/>
+ <include name="com/ibm/icu/text/UnicodeSetIterator.java"/>
+ </javac>
+ </target>
+
+ <target name="_propertiesTests">
+ <mkdir dir="${module.tests.dir}"/>
+ <javac destdir="${module.tests.dir}"
+ source="${javac.source}"
+ target="${javac.target}"
+ encoding="${java.src.encoding}"
+ classpath="${module.bin.dir}"
+ debug="on" deprecation="off">
+ <src path="${icu4j.core.dir}/src"/>
+ <src path="${icu4j.test-framework.dir}/src"/>
+ <src path="${icu4j.core-tests.dir}/src"/>
+ <src path="${icu4j.testall.dir}/src"/>
+
+ <patternset refid="common.test.sources"/>
+ <include name="com/ibm/icu/dev/test/lang/**/*.java"/>
+ <exclude name="com/ibm/icu/dev/test/lang/TestUScriptRun.java"/>
+ </javac>
+
+ <copy todir="${module.tests.dir}">
+ <fileset dir="${icu4j.core-tests.dir}/src">
+ <include name="com/ibm/icu/dev/data/unicode/SpecialCasing.txt"/>
+ <include name="com/ibm/icu/dev/data/unicode/UnicodeData.txt"/>
+ </fileset>
+ </copy>
+ </target>
+
+ <target name="propertiesBasic" depends="_propertiesClasses, _copyBasicPropsData" description="Modular build of basic character properties"/>
+
+ <target name="propertiesBasicTests" depends="propertiesBasic, _propertiesTests" description="Modular build of basic character properties test suite"/>
+
+ <target name="propertiesFull" depends="_propertiesClasses, _copyFullPropsData" description="Modular build of full character properties"/>
+
+ <target name="propertiesFullTests" depends="propertiesFull, _propertiesTests" description="Modular build of full character properties test suite"/>
+
+ <!-- Transliterator -->
+ <!-- this module will soon be obsolete, use the translit jar -->
+ <target name="transliterator" depends="_propertiesClasses" description="Modular build of transliterator services">
+ <mkdir dir="${module.bin.dir}"/>
+ <javac destdir="${module.bin.dir}"
+ source="${javac.source}"
+ target="${javac.target}"
+ encoding="${java.src.encoding}"
+ debug="on" deprecation="off">
+ <src path="${icu4j.core.dir}/src"/>
+ <src path="${icu4j.translit.dir}/src"/>
+
+ <include name="com/ibm/icu/impl/*Iterator*.java"/>
+ <include name="com/ibm/icu/impl/*Property*.java"/>
+ <include name="com/ibm/icu/impl/data/ResourceReader.java"/>
+ <include name="com/ibm/icu/impl/UtilityExtensions.java"/>
+ <include name="com/ibm/icu/text/*Transliterator*.java"/>
+ <include name="com/ibm/icu/text/UnicodeSetIterator.java"/>
+ <include name="com/ibm/icu/text/BreakIteratorFactory.java"/>
+ </javac>
+
+ <unjar src="${icu4j.data.jar}" dest="${module.bin.dir}">
+ <patternset>
+ <include name="**/unorm.icu"/>
+ <include name="**/uprops.icu"/>
+ <include name="**/ubidi.icu"/>
+ <include name="**/ucase.icu"/>
+ <include name="**/unames.icu"/>
+ <include name="**/pnames.icu"/>
+ <include name="**/*.brk"/>
+ <include name="**/*.dict"/>
+ <include name="**/*.nrm"/>
+ <include name="**/brkitr/*.res"/>
+ <include name="**/translit/*.res"/>
+ <include name="**/likelySubtags.res"/>
+ </patternset>
+ </unjar>
+ </target>
+
+ <target name="transliteratorTests" depends="transliterator" description="Modular build of transliterator test suite">
+ <mkdir dir="${module.tests.dir}"/>
+ <javac destdir="${module.tests.dir}"
+ source="${javac.source}"
+ target="${javac.target}"
+ encoding="${java.src.encoding}"
+ classpath="${module.bin.dir}"
+ debug="on" deprecation="off">
+ <src path="${icu4j.core.dir}/src"/>
+ <src path="${icu4j.test-framework.dir}/src"/>
+ <src path="${icu4j.translit-tests.dir}/src"/>
+ <src path="${icu4j.testall.dir}/src"/>
+
+ <patternset refid="common.test.sources"/>
+ <include name="com/ibm/icu/dev/test/TestAllTranslit.java"/>
+ <include name="com/ibm/icu/dev/test/translit/**/*.java"/>
+ <exclude name="com/ibm/icu/dev/test/translit/UnicodeFilterLogic*.java"/>
+ </javac>
+
+ <copy file="${icu4j.translit-tests.dir}/src/com/ibm/icu/dev/test/translit/langtagRegex.txt"
+ todir="${module.tests.dir}/com/ibm/icu/dev/test/translit"/>
+ </target>
+
+ <!-- StringPrep -->
+ <target name="stringPrep" depends="normalizer" description="Modular build of stringprep services">
+ <mkdir dir="${module.bin.dir}"/>
+ <javac srcdir="${icu4j.core.dir}/src"
+ destdir="${module.bin.dir}"
+ source="${javac.source}"
+ target="${javac.target}"
+ encoding="${java.src.encoding}"
+ debug="on" deprecation="off">
+ <include name="com/ibm/icu/impl/*StringPrep*.java"/>
+ <include name="com/ibm/icu/text/*IDNA*.java"/>
+ <include name="com/ibm/icu/text/*StringPrep*.java"/>
+ </javac>
+
+ <unjar src="${icu4j.data.jar}" dest="${module.bin.dir}">
+ <patternset>
+ <include name="**/*.spp"/>
+ <include name="**/ubidi.icu"/>
+ <include name="**/ucase.icu"/>
+ <include name="**/unorm.icu"/>
+ <include name="**/uprops.icu"/>
+ <include name="**/pnames.icu"/>
+ <include name="**/unames.icu"/>
+ </patternset>
+ </unjar>
+ </target>
+
+ <target name="stringPrepTests" depends="stringPrep" description="Modular build of stringprep test suite">
+ <mkdir dir="${module.tests.dir}"/>
+ <javac destdir="${module.tests.dir}"
+ source="${javac.source}"
+ target="${javac.target}"
+ encoding="${java.src.encoding}"
+ classpath="${module.bin.dir}"
+ debug="on" deprecation="off">
+ <src path="${icu4j.core.dir}/src"/>
+ <src path="${icu4j.test-framework.dir}/src"/>
+ <src path="${icu4j.core-tests.dir}/src"/>
+ <src path="${icu4j.testall.dir}/src"/>
+
+ <patternset refid="common.test.sources"/>
+ <include name="com/ibm/icu/dev/test/stringprep/**/*.java"/>
+ </javac>
+
+ <unjar src="${icu4j.testdata.jar}" dest="${module.tests.dir}">
+ <patternset>
+ <include name="**/*.spp"/>
+ <include name="**/idna_rules.res"/>
+ </patternset>
+ </unjar>
+
+ <copy file="${icu4j.core-tests.dir}/src/com/ibm/icu/dev/data/IDNATestInput.txt"
+ todir="${module.tests.dir}/com/ibm/icu/dev/data"/>
+ </target>
+
+ <target name="publishToMavenRepo" depends="releaseVer">
+ <!--
+ Publish libraries to Maven repositories, snapshot or release depending on current
+ version in pom.xml.
+
+ Prerequisites
+
+ 1) Apache Maven Ant tasks - http://maven.apache.org/ant-tasks
+ 2) GnuPG
+ 3) Put build-local.properties to specify followings
+
+ maven-ant-tasks.jar = [location of maven ant tasks jar file]
+ gpg.user = ICU Project
+ gpg.passphrase = [passprase for ICU Project's PGP key]
+
+ 4) Maven configuration file ~/.m2/settings.xml
+ <settings>
+ <servers>
+ <server>
+ <id>icu4j-releases</id>
+ <username>[your JIRA/Nexus ID]</username>
+ <password>[your JIRA/Nexus password]</password>
+ </server>
+ <server>
+ <id>icu4j-snapshots</id>
+ <username>[your JIRA/Nexus ID]</username>
+ <password>[your JIRA/Nexus password]</password>
+ </server>
+ </servers>
+ </settings>
+
+ Note: For now, charset.jar and localespi.jar are excluded.
+ -->
+ <fail message="Maven Ant Tasks are required to publish libraries. Set maven-ant-tasks.jar property. Maven Ant Tasks URL: http://maven.apache.org/ant-tasks/" unless="maven-ant-tasks.jar"/>
+ <condition property="no_maven-ant-tasks">
+ <available file="${maven-ant-tasks.jar}"/>
+ </condition>
+ <fail message="Maven Ant Tasks not found at ${maven-ant-tasks.jar}" unless="no_maven-ant-tasks"/>
+
+ <path id="maven-ant-tasks.classpath" path="${maven-ant-tasks.jar}"/>
+ <typedef resource="org/apache/maven/artifact/ant/antlib.xml" uri="urn:maven-artifact-ant"
+ classpathref="maven-ant-tasks.classpath"/>
+
+ <xmlproperty file="pom.xml" prefix="pom.xml"/>
+
+ <!-- copy release files -->
+ <property name="maven.release.dir" value="${release.dir}/maven"/>
+
+ <property name="maven.icu4j.jar.versioned.file" value="icu4j-${pom.xml.project.version}.jar"/>
+ <property name="maven.icu4j-src.jar.versioned.file" value="icu4j-${pom.xml.project.version}-src.jar"/>
+ <property name="maven.icu4jdocs.jar.file" value="icu4j-${pom.xml.project.version}-javadoc.jar"/>
+
+ <mkdir dir="${maven.release.dir}"/>
+
+ <copy file="${release.dir}/${icu4j.jar.versioned.file}" tofile="${maven.release.dir}/${maven.icu4j.jar.versioned.file}"/>
+ <copy file="${release.dir}/${icu4j-src.jar.versioned.file}" tofile="${maven.release.dir}/${maven.icu4j-src.jar.versioned.file}"/>
+ <copy file="${release.dir}/${icu4jdocs.jar.versioned.file}" tofile="${maven.release.dir}/${maven.icu4jdocs.jar.file}"/>
+
+ <copy file="pom.xml" todir="${maven.release.dir}"/>
+
+ <!-- sign release files-->
+ <macrodef name="gpg">
+ <attribute name="file"/>
+ <sequential>
+ <delete file="@{file}.asc" failonerror="false"/>
+ <exec executable="gpg">
+ <arg value="-u"/>
+ <arg value="${gpg.user}"/>
+ <arg value="-ab"/>
+ <arg value="--passphrase"/>
+ <arg value="${gpg.passphrase}"/>
+ <arg value="-o"/>
+ <arg value="@{file}.asc"/>
+ <arg value="@{file}"/>
+ </exec>
+ </sequential>
+ </macrodef>
+
+ <gpg file="${maven.release.dir}/${maven.icu4j.jar.versioned.file}"/>
+ <gpg file="${maven.release.dir}/${maven.icu4j-src.jar.versioned.file}"/>
+ <gpg file="${maven.release.dir}/${maven.icu4jdocs.jar.file}"/>
+
+ <gpg file="${maven.release.dir}/pom.xml"/>
+
+ <!-- deploy files to the repository -->
+ <deploy xmlns="urn:maven-artifact-ant" file="${maven.release.dir}/${maven.icu4j.jar.versioned.file}">
+ <pom file="${maven.release.dir}/pom.xml"/>
+ <attach file="${maven.release.dir}/pom.xml.asc" type="pom.asc"/>
+
+ <attach file="${maven.release.dir}/${maven.icu4j.jar.versioned.file}.asc" type="jar.asc"/>
+ <attach file="${maven.release.dir}/${maven.icu4j-src.jar.versioned.file}" classifier="sources"/>
+ <attach file="${maven.release.dir}/${maven.icu4j-src.jar.versioned.file}.asc" classifier="sources" type="jar.asc"/>
+ <attach file="${maven.release.dir}/${maven.icu4jdocs.jar.file}" classifier="javadoc"/>
+ <attach file="${maven.release.dir}/${maven.icu4jdocs.jar.file}.asc" classifier="javadoc" type="jar.asc"/>
+ </deploy>
+ </target>
+
+</project>
diff --git a/demos/.classpath b/demos/.classpath
new file mode 100644
index 0000000..c13960c
--- /dev/null
+++ b/demos/.classpath
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/icu4j-charset"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/icu4j-core"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/icu4j-translit"/>
+ <classpathentry kind="output" path="out/bin"/>
+</classpath>
diff --git a/demos/.project b/demos/.project
new file mode 100644
index 0000000..69e0c1b
--- /dev/null
+++ b/demos/.project
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>icu4j-demos</name>
+ <comment></comment>
+ <projects>
+ <project>icu4j-charset</project>
+ <project>icu4j-core</project>
+ <project>icu4j-shared</project>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/demos/.settings/org.eclipse.core.resources.prefs b/demos/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..c62da78
--- /dev/null
+++ b/demos/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Fri Nov 05 14:18:21 EDT 2010
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/demos/.settings/org.eclipse.jdt.core.prefs b/demos/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..1c6961a
--- /dev/null
+++ b/demos/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,330 @@
+#Fri Aug 28 16:05:27 EDT 2009
+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=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=ignore
+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=error
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=ignore
+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.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=ignore
+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.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=ignore
+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.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=ignore
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.5
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=120
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=120
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=space
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
diff --git a/demos/.settings/org.eclipse.jdt.ui.prefs b/demos/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..abf9d87
--- /dev/null
+++ b/demos/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,6 @@
+#Tue Jun 09 16:57:19 EDT 2009
+eclipse.preferences.version=1
+formatter_profile=_ICU4J Standard
+formatter_settings_version=11
+org.eclipse.jdt.ui.javadoc=false
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates><template autoinsert\="true" context\="gettercomment_context" deleted\="false" description\="Comment for getter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name\="gettercomment">/**\r\n * @return the ${bare_field_name}\r\n */</template><template autoinsert\="true" context\="settercomment_context" deleted\="false" description\="Comment for setter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.settercomment" name\="settercomment">/**\r\n * @param ${param} the ${bare_field_name} to set\r\n */</template><template autoinsert\="true" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment">/**\r\n * ${tags}\r\n */</template><template autoinsert\="false" context\="filecomment_context" deleted\="false" description\="Comment for created Java files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.filecomment" name\="filecomment">/*\r\n *******************************************************************************\r\n * Copyright (C) ${year}, International Business Machines Corporation and *\r\n * others. All Rights Reserved. *\r\n *******************************************************************************\r\n */</template><template autoinsert\="true" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\r\n * @author ${user}\r\n *\r\n * ${tags}\r\n */</template><template autoinsert\="true" context\="fieldcomment_context" deleted\="false" description\="Comment for fields" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment">/**\r\n * \r\n */</template><template autoinsert\="true" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodcomment" name\="methodcomment">/**\r\n * ${tags}\r\n */</template><template autoinsert\="true" context\="overridecomment_context" deleted\="false" description\="Comment for overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.overridecomment" name\="overridecomment">/* (non-Javadoc)\r\n * ${see_to_overridden}\r\n */</template><template autoinsert\="true" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.delegatecomment" name\="delegatecomment">/**\r\n * ${tags}\r\n * ${see_to_target}\r\n */</template><template autoinsert\="true" context\="newtype_context" deleted\="false" description\="Newly created files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.newtype" name\="newtype">${filecomment}\r\n${package_declaration}\r\n\r\n${typecomment}\r\n${type_declaration}</template><template autoinsert\="true" context\="classbody_context" deleted\="false" description\="Code in new class type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.classbody" name\="classbody">\r\n</template><template autoinsert\="true" context\="interfacebody_context" deleted\="false" description\="Code in new interface type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.interfacebody" name\="interfacebody">\r\n</template><template autoinsert\="true" context\="enumbody_context" deleted\="false" description\="Code in new enum type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.enumbody" name\="enumbody">\r\n</template><template autoinsert\="true" context\="annotationbody_context" deleted\="false" description\="Code in new annotation type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.annotationbody" name\="annotationbody">\r\n</template><template autoinsert\="true" context\="catchblock_context" deleted\="false" description\="Code in new catch blocks" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.catchblock" name\="catchblock">// ${todo} Auto-generated catch block\r\n${exception_var}.printStackTrace();</template><template autoinsert\="true" context\="methodbody_context" deleted\="false" description\="Code in created method stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodbody" name\="methodbody">// ${todo} Auto-generated method stub\r\n${body_statement}</template><template autoinsert\="true" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}\r\n// ${todo} Auto-generated constructor stub</template><template autoinsert\="true" context\="getterbody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.getterbody" name\="getterbody">return ${field};</template><template autoinsert\="true" context\="setterbody_context" deleted\="false" description\="Code in created setters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.setterbody" name\="setterbody">${field} \= ${param};</template></templates>
diff --git a/demos/build.properties b/demos/build.properties
new file mode 100644
index 0000000..f374881
--- /dev/null
+++ b/demos/build.properties
@@ -0,0 +1,5 @@
+#*******************************************************************************
+#* Copyright (C) 2009, International Business Machines Corporation and *
+#* others. All Rights Reserved. *
+#*******************************************************************************
+shared.dir = ../main/shared
diff --git a/demos/build.xml b/demos/build.xml
new file mode 100644
index 0000000..73e8bc9
--- /dev/null
+++ b/demos/build.xml
@@ -0,0 +1,31 @@
+<!--
+*******************************************************************************
+* Copyright (C) 2009-2011, International Business Machines Corporation and *
+* others. All Rights Reserved. *
+*******************************************************************************
+-->
+<project name="demos" default="build" basedir=".">
+ <property file="build-local.properties"/>
+ <property file="build.properties"/>
+ <import file="${shared.dir}/build/common-targets.xml"/>
+
+ <path id="javac.classpathref">
+ <path refid="javac.classpathref.${ant.project.name}"/>
+ </path>
+ <property name="jar.name" value="icu4j-${ant.project.name}.jar"/>
+ <property name="src.jar.name" value="icu4j-${ant.project.name}-src.jar"/>
+
+ <target name="build" depends="compile, copy, jar, src-jar" description="Build the project"/>
+
+ <target name="build-all" depends="@build-all" description="Build the project including all dependencies"/>
+
+ <target name="clean" depends="@clean" description="Clean up the build outputs"/>
+
+ <target name="compile" depends="@compile" description="Compile java source files"/>
+
+ <target name="copy" depends="@copy" description="Copy non-java runtime files to the project's binary directory"/>
+
+ <target name="jar" depends="compile, copy, @jar" description="Create the project's jar file"/>
+
+ <target name="src-jar" depends="@src-jar" description="Create the project's source jar file"/>
+</project>
\ No newline at end of file
diff --git a/demos/demos-build.launch b/demos/demos-build.launch
new file mode 100644
index 0000000..cead29e
--- /dev/null
+++ b/demos/demos-build.launch
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.ant.AntLaunchConfigurationType">
+<booleanAttribute key="org.eclipse.ant.ui.DEFAULT_VM_INSTALL" value="false"/>
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
+<listEntry value="/icu4j-demos/build.xml"/>
+</listAttribute>
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
+<listEntry value="1"/>
+</listAttribute>
+<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.ant.ui.AntClasspathProvider"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="icu4j-demos"/>
+<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.ant.ui.AntClasspathProvider"/>
+<mapAttribute key="org.eclipse.ui.externaltools.ATTR_ANT_PROPERTIES">
+<mapEntry key="eclipse.pdebuild.templates" value="/D:/eclipse-SDK-3.4.2-win32/eclipse/plugins/org.eclipse.pde.build_3.4.1.R34x_v20081217/templates/"/>
+<mapEntry key="eclipse.pdebuild.home" value="/D:/eclipse-SDK-3.4.2-win32/eclipse/plugins/org.eclipse.pde.build_3.4.1.R34x_v20081217/./"/>
+<mapEntry key="eclipse.pdebuild.scripts" value="/D:/eclipse-SDK-3.4.2-win32/eclipse/plugins/org.eclipse.pde.build_3.4.1.R34x_v20081217/scripts/"/>
+</mapAttribute>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_ANT_PROPERTY_FILES" value="${workspace_loc:/icu4j-shared/build/locations-eclipse.properties},"/>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/icu4j-demos/build.xml}"/>
+<stringAttribute key="process_factory_id" value="org.eclipse.ant.ui.remoteAntProcessFactory"/>
+</launchConfiguration>
diff --git a/demos/manifest.stub b/demos/manifest.stub
new file mode 100644
index 0000000..5180077
--- /dev/null
+++ b/demos/manifest.stub
@@ -0,0 +1,13 @@
+Manifest-Version: 1.0
+Main-Class: com.ibm.icu.dev.demo.Launcher
+Class-Path: icu4j.jar
+
+Name: com/ibm/icu/dev/demo
+Specification-Title: ICU for Java Demo
+Specification-Version: @SPECVERSION@
+Specification-Vendor: ICU
+Implementation-Title: ICU for Java Demo
+Implementation-Version: @IMPLVERSION@
+Implementation-Vendor: IBM Corporation
+Implementation-Vendor-Id: com.ibm
+Copyright-Info: @COPYRIGHT@
diff --git a/demos/src/com/ibm/icu/dev/demo/Launcher.java b/demos/src/com/ibm/icu/dev/demo/Launcher.java
new file mode 100644
index 0000000..bd5512a
--- /dev/null
+++ b/demos/src/com/ibm/icu/dev/demo/Launcher.java
@@ -0,0 +1,187 @@
+/*
+ *******************************************************************************
+ * Copyright (C) 2007-2011, International Business Machines Corporation and *
+ * others. All Rights Reserved. *
+ *******************************************************************************
+ */
+package com.ibm.icu.dev.demo;
+
+import java.awt.BorderLayout;
+import java.awt.Button;
+import java.awt.Color;
+import java.awt.Frame;
+import java.awt.GridLayout;
+import java.awt.Label;
+import java.awt.Panel;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import com.ibm.icu.dev.demo.impl.DemoApplet;
+import com.ibm.icu.dev.demo.impl.DemoUtility;
+import com.ibm.icu.util.VersionInfo;
+
+
+/**
+ * @author srl
+ * Application to provide a panel of demos to launch
+ */
+public class Launcher extends DemoApplet {
+ private static final long serialVersionUID = -8054963875776183877L;
+
+ /**
+ * base package of all demos
+ */
+ public static final String demoBase = "com.ibm.icu.dev.demo";
+ /**
+ * list of classes, relative to the demoBase. all must have a static void main(String[])
+ */
+ public static final String demoList[] = {
+ "calendar.CalendarApp",
+ "charsetdet.DetectingViewer",
+ "holiday.HolidayCalendarDemo",
+ "rbnf.RbnfDemo",
+ "translit.Demo",
+ };
+
+ public class LauncherFrame extends Frame implements ActionListener {
+ private static final long serialVersionUID = -8054963875776183878L;
+
+ public Button buttonList[] = new Button[demoList.length]; // one button for each demo
+ public Label statusLabel;
+ private DemoApplet applet;
+
+ LauncherFrame(DemoApplet applet) {
+ init();
+ this.applet = applet;
+ }
+
+ public void init() {
+ // close down when close is clicked.
+ // TODO: this should be factored..
+ addWindowListener(
+ new WindowAdapter() {
+ public void windowClosing(WindowEvent e) {
+ setVisible(false);
+ dispose();
+
+ if (applet != null) {
+ applet.demoClosed();
+ } else System.exit(0);
+ }
+ } );
+
+ setBackground(DemoUtility.bgColor);
+ setLayout(new BorderLayout());
+
+ Panel topPanel = new Panel();
+ topPanel.setLayout(new GridLayout(5,3));
+
+ for(int i=0;i<buttonList.length;i++) {
+ String demo = demoList[i];
+ Button b = new Button(demo);
+ b.addActionListener(this);
+ buttonList[i]=b;
+ topPanel.add(b);
+ }
+ add(BorderLayout.CENTER,topPanel);
+ statusLabel = new Label("");
+ statusLabel.setAlignment(Label.LEFT);
+ String javaVersion = "";
+ try {
+ javaVersion = "* Java: "+System.getProperty("java.version");
+ } catch (Throwable t) {
+ javaVersion = "";
+ }
+ add(BorderLayout.NORTH, new Label(
+ "ICU Demos * ICU version "+VersionInfo.ICU_VERSION +
+ " * http://icu-project.org "+javaVersion));
+ add(BorderLayout.SOUTH,statusLabel);
+ // set up an initial status.
+ showStatus(buttonList.length+" demos ready. ");
+ }
+
+ /**
+ * Change the 'status' field, and set it to black
+ * @param status
+ */
+ void showStatus(String status) {
+ statusLabel.setText(status);
+ statusLabel.setForeground(Color.BLACK);
+ statusLabel.setBackground(Color.WHITE);
+// statusLabel.setFont(Font.PLAIN);
+ doLayout();
+ }
+ void showStatus(String demo, String status) {
+ showStatus(demo+": "+status);
+ }
+ void showFailure(String status) {
+ statusLabel.setText(status);
+ statusLabel.setBackground(Color.GRAY);
+ statusLabel.setForeground(Color.RED);
+// statusLabel.setFont(Font.BOLD);
+ doLayout();
+ }
+ void showFailure(String demo, String status) {
+ showFailure(demo+": "+status);
+ }
+
+
+ public void actionPerformed(ActionEvent e) {
+ // find button
+ for(int i=0;i<buttonList.length;i++) {
+ if(e.getSource() == buttonList[i]) {
+ String demoShort = demoList[i];
+ String demo = demoBase+'.'+demoShort;
+ showStatus(demoShort, "launching");
+ try {
+ Class c = Class.forName(demo);
+ String args[] = new String[0];
+ Class params[] = new Class[1];
+ params[0] = args.getClass();
+ Method m = c.getMethod("main", params );
+ Object[] argList = { args };
+ m.invoke(null, argList);
+ showStatus(demoShort, "launched.");
+ } catch (ClassNotFoundException e1) {
+ showFailure(demoShort,e1.toString());
+ e1.printStackTrace();
+ } catch (SecurityException se) {
+ showFailure(demoShort,se.toString());
+ se.printStackTrace();
+ } catch (NoSuchMethodException nsme) {
+ showFailure(demoShort,nsme.toString());
+ nsme.printStackTrace();
+ } catch (IllegalArgumentException iae) {
+ showFailure(demoShort,iae.toString());
+ iae.printStackTrace();
+ } catch (IllegalAccessException iae) {
+ showFailure(demoShort,iae.toString());
+ iae.printStackTrace();
+ } catch (InvocationTargetException ite) {
+ showFailure(demoShort,ite.toString());
+ ite.printStackTrace();
+ }
+ repaint();
+ }
+ }
+ }
+
+ }
+
+ /* This creates a Frame for the demo applet. */
+ protected Frame createDemoFrame(DemoApplet applet) {
+ return new LauncherFrame(applet);
+ }
+
+ /**
+ * The main function which defines the behavior of the Demo
+ * applet when an applet is started.
+ */
+ public static void main(String[] args) {
+ new Launcher().showDemo();
+ }
+}
diff --git a/demos/src/com/ibm/icu/dev/demo/calendar/CalendarApp.java b/demos/src/com/ibm/icu/dev/demo/calendar/CalendarApp.java
new file mode 100644
index 0000000..2940d59
--- /dev/null
+++ b/demos/src/com/ibm/icu/dev/demo/calendar/CalendarApp.java
@@ -0,0 +1,37 @@
+/*
+ *******************************************************************************
+ * Copyright (C) 1997-2010, International Business Machines Corporation and *
+ * others. All Rights Reserved. *
+ *******************************************************************************
+ */
+
+package com.ibm.icu.dev.demo.calendar;
+
+import java.awt.Frame;
+
+import com.ibm.icu.dev.demo.impl.DemoApplet;
+
+/**
+ * CalendarApp demonstrates how Calendar works.
+ */
+public class CalendarApp extends DemoApplet
+{
+ /**
+ * For serialization
+ */
+ private static final long serialVersionUID = -4270137898405840825L;
+
+ /**
+ * The main function which defines the behavior of the CalendarDemo
+ * applet when an applet is started.
+ */
+ public static void main(String argv[]) {
+
+ new CalendarApp().showDemo();
+ }
+
+ /* This creates a CalendarFrame for the demo applet. */
+ public Frame createDemoFrame(DemoApplet applet) {
+ return new CalendarFrame(applet);
+ }
+}
diff --git a/demos/src/com/ibm/icu/dev/demo/calendar/CalendarCalc.java b/demos/src/com/ibm/icu/dev/demo/calendar/CalendarCalc.java
new file mode 100644
index 0000000..ff9a75b
--- /dev/null
+++ b/demos/src/com/ibm/icu/dev/demo/calendar/CalendarCalc.java
@@ -0,0 +1,595 @@
+/*
+ *******************************************************************************
+ * Copyright (C) 1997-2008, International Business Machines Corporation and *
+ * others. All Rights Reserved. *
+ *******************************************************************************
+ */
+
+package com.ibm.icu.dev.demo.calendar;
+
+import java.awt.Button;
+import java.awt.Checkbox;
+import java.awt.CheckboxGroup;
+import java.awt.Choice;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.FlowLayout;
+import java.awt.Font;
+import java.awt.Frame;
+import java.awt.GridLayout;
+import java.awt.Label;
+import java.awt.Panel;
+import java.awt.TextField;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.awt.event.KeyEvent;
+import java.awt.event.WindowEvent;
+import java.text.ParsePosition;
+import java.util.Date;
+import java.util.Locale;
+
+import javax.swing.JTextField;
+
+import com.ibm.icu.dev.demo.impl.DemoApplet;
+import com.ibm.icu.dev.demo.impl.DemoUtility;
+import com.ibm.icu.text.DateFormat;
+import com.ibm.icu.text.SimpleDateFormat;
+import com.ibm.icu.util.BuddhistCalendar;
+import com.ibm.icu.util.Calendar;
+import com.ibm.icu.util.GregorianCalendar;
+import com.ibm.icu.util.HebrewCalendar;
+import com.ibm.icu.util.IslamicCalendar;
+import com.ibm.icu.util.JapaneseCalendar;
+import com.ibm.icu.util.TimeZone;
+
+/**
+ * CalendarCalc demonstrates how Date/Time formatter works.
+ */
+public class CalendarCalc extends DemoApplet
+{
+ /**
+ * For serialization
+ */
+ private static final long serialVersionUID = 4540103433916539296L;
+
+ /**
+ * The main function which defines the behavior of the MultiCalendarDemo
+ * applet when an applet is started.
+ */
+ public static void main(String argv[]) {
+ new CalendarCalc().showDemo();
+ }
+
+ /**
+ * This creates a CalendarCalcFrame for the demo applet.
+ */
+ public Frame createDemoFrame(DemoApplet applet) {
+ return new CalendarCalcFrame(applet);
+ }
+}
+
+/**
+ * A Frame is a top-level window with a title. The default layout for a frame
+ * is BorderLayout. The CalendarCalcFrame class defines the window layout of
+ * MultiCalendarDemo.
+ */
+class CalendarCalcFrame extends Frame implements ActionListener
+{
+ /**
+ * For serialization
+ */
+ private static final long serialVersionUID = 8901485296258761846L;
+
+ static final Locale[] locales = DemoUtility.getG7Locales();
+
+ private DemoApplet applet;
+ private long time = System.currentTimeMillis();
+
+ private static final RollAddField kRollAddFields[] = {
+ new RollAddField(Calendar.YEAR, "Year" ),
+ new RollAddField(Calendar.MONTH, "Month" ),
+ new RollAddField(Calendar.WEEK_OF_MONTH, "Week of Month" ),
+ new RollAddField(Calendar.WEEK_OF_YEAR, "Week of Year" ),
+ new RollAddField(Calendar.DAY_OF_MONTH, "Day of Month" ),
+ new RollAddField(Calendar.DAY_OF_WEEK, "Day of Week" ),
+ new RollAddField(Calendar.DAY_OF_WEEK_IN_MONTH, "Day of Week in Month" ),
+ new RollAddField(Calendar.DAY_OF_YEAR, "Day of Year" ),
+ new RollAddField(Calendar.AM_PM, "AM/PM" ),
+ new RollAddField(Calendar.HOUR_OF_DAY, "Hour of day" ),
+ new RollAddField(Calendar.HOUR, "Hour" ),
+ new RollAddField(Calendar.MINUTE, "Minute" ),
+ new RollAddField(Calendar.SECOND, "Second" ),
+ };
+
+ /**
+ * Constructs a new CalendarCalcFrame that is initially invisible.
+ */
+ public CalendarCalcFrame(DemoApplet applet)
+ {
+ super("Multiple Calendar Demo");
+ this.applet = applet;
+ init();
+ start();
+ }
+
+ /**
+ * Initializes the applet. You never need to call this directly, it
+ * is called automatically by the system once the applet is created.
+ */
+ public void init()
+ {
+ buildGUI();
+
+ patternText.setText( calendars[0].toPattern() );
+
+ // Force an update of the display
+ cityChanged();
+ millisFormat();
+ enableEvents(KeyEvent.KEY_RELEASED);
+ enableEvents(WindowEvent.WINDOW_CLOSING);
+ }
+
+ //------------------------------------------------------------
+ // package private
+ //------------------------------------------------------------
+ void addWithFont(Container container, Component foo, Font font) {
+ if (font != null)
+ foo.setFont(font);
+ container.add(foo);
+ }
+
+ /**
+ * Called to start the applet. You never need to call this method
+ * directly, it is called when the applet's document is visited.
+ */
+ public void start()
+ {
+ // do nothing
+ }
+
+ TextField patternText;
+
+ Choice dateMenu;
+ Choice localeMenu;
+
+ Button up;
+ Button down;
+
+ Checkbox getRoll;
+ Checkbox getAdd;
+
+ public void buildGUI()
+ {
+ setBackground(DemoUtility.bgColor);
+ setLayout(new FlowLayout()); // shouldn't be necessary, but it is.
+
+// TITLE
+ Label label1=new Label("Calendar Converter", Label.CENTER);
+ label1.setFont(DemoUtility.titleFont);
+ add(label1);
+ add(DemoUtility.createSpacer());
+
+// IO Panel
+ Panel topPanel = new Panel();
+ topPanel.setLayout(new FlowLayout());
+
+ CheckboxGroup group1= new CheckboxGroup();
+
+ // Set up the controls for each calendar we're demonstrating
+ for (int i = 0; i < calendars.length; i++)
+ {
+ Label label = new Label(calendars[i].name, Label.RIGHT);
+ label.setFont(DemoUtility.labelFont);
+ topPanel.add(label);
+
+ topPanel.add(calendars[i].text);
+
+ final int j = i;
+ calendars[i].text.addActionListener( new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ textChanged(j);
+ }
+ } );
+
+ calendars[i].rollAdd.setCheckboxGroup(group1);
+ topPanel.add(calendars[i].rollAdd);
+ }
+ calendars[0].rollAdd.setState(true); // Make the first one selected
+
+ Label label4=new Label("Pattern", Label.RIGHT);
+ label4.setFont(DemoUtility.labelFont);
+ topPanel.add(label4);
+
+ patternText=new TextField(FIELD_COLUMNS);
+ patternText.setFont(DemoUtility.editFont);
+ topPanel.add(patternText);
+ topPanel.add(new Label(""));
+
+ DemoUtility.fixGrid(topPanel,3);
+ add(topPanel);
+ add(DemoUtility.createSpacer());
+
+// ROLL / ADD
+ Panel rollAddPanel=new Panel();
+ {
+ rollAddPanel.setLayout(new FlowLayout());
+
+ Panel rollAddBoxes = new Panel();
+ {
+ rollAddBoxes.setLayout(new GridLayout(2,1));
+ CheckboxGroup group2= new CheckboxGroup();
+ getRoll = new Checkbox("Roll",group2, false);
+ getAdd = new Checkbox("Add",group2, true);
+
+ rollAddBoxes.add(getRoll);
+ rollAddBoxes.add(getAdd);
+ }
+
+ Label dateLabel=new Label("Date Fields");
+ dateLabel.setFont(DemoUtility.labelFont);
+
+ dateMenu= new Choice();
+ dateMenu.setBackground(DemoUtility.choiceColor);
+ for (int i = 0; i < kRollAddFields.length; i++) {
+ dateMenu.addItem(kRollAddFields[i].name);
+ if (kRollAddFields[i].field == Calendar.MONTH) {
+ dateMenu.select(i);
+ }
+ }
+
+ Panel upDown = new Panel();
+ {
+ upDown.setLayout(new GridLayout(2,1));
+
+ // *** If the images are not found, we use the label.
+ up = new Button("^");
+ down = new Button("v");
+ up.setBackground(DemoUtility.bgColor);
+ down.setBackground(DemoUtility.bgColor);
+ upDown.add(up);
+ upDown.add(down);
+ up.addActionListener(this);
+ down.addActionListener(this);
+ }
+
+ rollAddPanel.add(dateLabel);
+ rollAddPanel.add(dateMenu);
+ rollAddPanel.add(rollAddBoxes);
+ rollAddPanel.add(upDown);
+
+ }
+ Panel localePanel = new Panel();
+ {
+ // Make the locale popup menus
+ localeMenu= new Choice();
+ Locale defaultLocale = Locale.getDefault();
+ int bestMatch = -1, thisMatch = -1;
+ int selectMe = 0;
+
+ for (int i = 0; i < locales.length; i++) {
+ if (i > 0 && locales[i].getLanguage().equals(locales[i-1].getLanguage()) ||
+ i < locales.length - 1 &&
+ locales[i].getLanguage().equals(locales[i+1].getLanguage()))
+ {
+ localeMenu.addItem( locales[i].getDisplayName() );
+ } else {
+ localeMenu.addItem( locales[i].getDisplayLanguage());
+ }
+
+ thisMatch = DemoUtility.compareLocales(locales[i], defaultLocale);
+
+ if (thisMatch >= bestMatch) {
+ bestMatch = thisMatch;
+ selectMe = i;
+ }
+ }
+
+ localeMenu.setBackground(DemoUtility.choiceColor);
+ localeMenu.select(selectMe);
+
+ Label localeLabel =new Label("Display Locale");
+ localeLabel.setFont(DemoUtility.labelFont);
+
+ localePanel.add(localeLabel);
+ localePanel.add(localeMenu);
+ DemoUtility.fixGrid(localePanel,2);
+
+ localeMenu.addItemListener( new ItemListener() {
+ public void itemStateChanged(ItemEvent e) {
+ Locale loc = locales[localeMenu.getSelectedIndex()];
+ System.out.println("Change locale to " + loc.getDisplayName());
+
+ for (int i = 0; i < calendars.length; i++) {
+ calendars[i].setLocale(loc);
+ }
+ millisFormat();
+ }
+ } );
+ }
+ add(rollAddPanel);
+ add(DemoUtility.createSpacer());
+ add(localePanel);
+ add(DemoUtility.createSpacer());
+
+// COPYRIGHT
+ Panel copyrightPanel = new Panel();
+ addWithFont (copyrightPanel,new Label(DemoUtility.copyright1, Label.LEFT),
+ DemoUtility.creditFont);
+ DemoUtility.fixGrid(copyrightPanel,1);
+ add(copyrightPanel);
+ }
+
+ /**
+ * This function is called when users change the pattern text.
+ */
+ public void setFormatFromPattern() {
+ String timePattern = patternText.getText();
+
+ for (int i = 0; i < calendars.length; i++) {
+ calendars[i].applyPattern(timePattern);
+ }
+
+ millisFormat();
+ }
+
+ /**
+ * This function is called when it is necessary to parse the time
+ * string in one of the formatted date fields
+ */
+ public void textChanged(int index) {
+ String rightString = calendars[index].text.getText();
+
+ ParsePosition status = new ParsePosition(0);
+
+ if (rightString.length() == 0)
+ {
+ errorText("Error: no input to parse!");
+ return;
+ }
+
+ try {
+ Date date = calendars[index].format.parse(rightString, status);
+ time = date.getTime();
+ }
+ catch (Exception e) {
+ for (int i = 0; i < calendars.length; i++) {
+ if (i != index) {
+ calendars[i].text.setText("ERROR");
+ }
+ }
+ errorText("Exception: " + e.getClass().toString() + " parsing: "+rightString);
+ return;
+ }
+
+ int start = calendars[index].text.getSelectionStart();
+ int end = calendars[index].text.getSelectionEnd();
+
+ millisFormat();
+
+ calendars[index].text.select(start,end);
+ }
+
+ /**
+ * This function is called when it is necessary to format the time
+ * in the "Millis" text field.
+ */
+ public void millisFormat() {
+ String out = "";
+
+ for (int i = 0; i < calendars.length; i++) {
+ try {
+ out = calendars[i].format.format(new Date(time));
+ calendars[i].text.setText(out);
+ }
+ catch (Exception e) {
+ calendars[i].text.setText("ERROR");
+ errorText("Exception: " + e.getClass().toString() + " formatting "
+ + calendars[i].name + " " + time);
+ }
+ }
+ }
+
+
+ /**
+ * This function is called when users change the pattern text.
+ */
+ public void patternTextChanged() {
+ setFormatFromPattern();
+ }
+
+ /**
+ * This function is called when users select a new representative city.
+ */
+ public void cityChanged() {
+ TimeZone timeZone = TimeZone.getDefault();
+
+ for (int i = 0; i < calendars.length; i++) {
+ calendars[i].format.setTimeZone(timeZone);
+ }
+ millisFormat();
+ }
+
+ /**
+ * This function is called when users select a new time field
+ * to add or roll its value.
+ */
+ public void dateFieldChanged(boolean isUp) {
+ int field = kRollAddFields[dateMenu.getSelectedIndex()].field;
+
+ for (int i = 0; i < calendars.length; i++)
+ {
+ if (calendars[i].rollAdd.getState())
+ {
+ Calendar c = calendars[i].calendar;
+ c.setTime(new Date(time));
+
+ if (getAdd.getState()) {
+ c.add(field, isUp ? 1 : -1);
+ } else {
+ c.roll(field, isUp);
+ }
+
+ time = c.getTime().getTime();
+ millisFormat();
+ break;
+ }
+ }
+ }
+
+ /**
+ * Print out the error message while debugging this program.
+ */
+ public void errorText(String s)
+ {
+ if (true) {
+ System.out.println(s);
+ }
+ }
+
+ /**
+ * Called if an action occurs in the CalendarCalcFrame object.
+ */
+ public void actionPerformed(ActionEvent evt)
+ {
+ // *** Button events are handled here.
+ Object obj = evt.getSource();
+ System.out.println("action " + obj);
+ if (obj instanceof Button) {
+ if (evt.getSource() == up) {
+ dateFieldChanged(false);
+ } else
+ if (evt.getSource() == down) {
+ dateFieldChanged(true);
+ }
+ }
+ }
+
+ /**
+ * Handles the event. Returns true if the event is handled and should not
+ * be passed to the parent of this component. The default event handler
+ * calls some helper methods to make life easier on the programmer.
+ */
+ protected void processKeyEvent(KeyEvent evt)
+ {
+ System.out.println("key " + evt);
+ if (evt.getID() == KeyEvent.KEY_RELEASED) {
+ if (evt.getSource() == patternText) {
+ patternTextChanged();
+ }
+ else {
+ for (int i = 0; i < calendars.length; i++) {
+ if (evt.getSource() == calendars[i].text) {
+ textChanged(i);
+ }
+ }
+ }
+ }
+ }
+
+ protected void processWindowEvent(WindowEvent evt)
+ {
+ System.out.println("window " + evt);
+ if (evt.getID() == WindowEvent.WINDOW_CLOSING &&
+ evt.getSource() == this) {
+ this.hide();
+ this.dispose();
+
+ if (applet != null) {
+ applet.demoClosed();
+ } else System.exit(0);
+ }
+ }
+
+ /*
+ protected void processEvent(AWTEvent evt)
+ {
+ if (evt.getID() == AWTEvent. Event.ACTION_EVENT && evt.target == up) {
+ dateFieldChanged(true);
+ return true;
+ }
+ else if (evt.id == Event.ACTION_EVENT && evt.target == down) {
+ dateFieldChanged(false);
+ return true;
+ }
+ }
+ */
+
+ private static final int FIELD_COLUMNS = 35;
+
+
+ class CalendarRec {
+ public CalendarRec(String nameStr, Calendar cal)
+ {
+ name = nameStr;
+ calendar = cal;
+ rollAdd = new Checkbox();
+
+ text = new JTextField("",FIELD_COLUMNS);
+ text.setFont(DemoUtility.editFont);
+
+ format = DateFormat.getDateInstance(cal, DateFormat.FULL,
+ Locale.getDefault());
+ //format.applyPattern(DEFAULT_FORMAT);
+ }
+
+ public void setLocale(Locale loc) {
+ String pattern = toPattern();
+
+ format = DateFormat.getDateInstance(calendar, DateFormat.FULL,
+ loc);
+ applyPattern(pattern);
+ }
+
+ public void applyPattern(String pattern) {
+ if (format instanceof SimpleDateFormat) {
+ ((SimpleDateFormat)format).applyPattern(pattern);
+//hey {al} -
+// } else if (format instanceof java.text.SimpleDateFormat) {
+// ((java.text.SimpleDateFormat)format).applyPattern(pattern);
+ }
+ }
+
+ private String toPattern() {
+ if (format instanceof SimpleDateFormat) {
+ return ((SimpleDateFormat)format).toPattern();
+//hey {al} -
+// } else if (format instanceof java.text.SimpleDateFormat) {
+// return ((java.text.SimpleDateFormat)format).toPattern();
+ }
+ return "";
+ }
+
+ Calendar calendar;
+ DateFormat format;
+ String name;
+ JTextField text;
+ Checkbox rollAdd;
+ }
+
+ private final CalendarRec[] calendars = {
+ new CalendarRec("Gregorian", new GregorianCalendar()),
+ new CalendarRec("Hebrew", new HebrewCalendar()),
+ new CalendarRec("Islamic (civil)", makeIslamic(true)),
+ new CalendarRec("Islamic (true)", makeIslamic(false)),
+ new CalendarRec("Buddhist", new BuddhistCalendar()),
+ new CalendarRec("Japanese", new JapaneseCalendar()),
+// new CalendarRec("Chinese", new ChineseCalendar()),
+ };
+
+ static private final Calendar makeIslamic(boolean civil) {
+ IslamicCalendar cal = new IslamicCalendar();
+ cal.setCivil(civil);
+ return cal;
+ }
+}
+
+class RollAddField {
+ RollAddField(int field, String name) {
+ this.field = field;
+ this.name = name;
+ }
+ int field;
+ String name;
+}
diff --git a/demos/src/com/ibm/icu/dev/demo/calendar/CalendarFrame.java b/demos/src/com/ibm/icu/dev/demo/calendar/CalendarFrame.java
new file mode 100644
index 0000000..fd76ec7
--- /dev/null
+++ b/demos/src/com/ibm/icu/dev/demo/calendar/CalendarFrame.java
@@ -0,0 +1,442 @@
+/*
+ *******************************************************************************
+ * Copyright (C) 1997-2007, International Business Machines Corporation and *
+ * others. All Rights Reserved. *
+ *******************************************************************************
+ */
+
+package com.ibm.icu.dev.demo.calendar;
+
+import java.awt.BorderLayout;
+import java.awt.Button;
+import java.awt.Choice;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Frame;
+import java.awt.Graphics;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Label;
+import java.awt.Panel;
+import java.awt.Rectangle;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.util.Date;
+import java.util.Locale;
+
+import com.ibm.icu.dev.demo.impl.DemoApplet;
+import com.ibm.icu.dev.demo.impl.DemoUtility;
+import com.ibm.icu.text.DateFormat;
+import com.ibm.icu.util.BuddhistCalendar;
+import com.ibm.icu.util.Calendar;
+import com.ibm.icu.util.GregorianCalendar;
+import com.ibm.icu.util.HebrewCalendar;
+import com.ibm.icu.util.IslamicCalendar;
+import com.ibm.icu.util.JapaneseCalendar;
+import com.ibm.icu.util.SimpleTimeZone;
+
+/**
+ * A Frame is a top-level window with a title. The default layout for a frame
+ * is BorderLayout. The CalendarFrame class defines the window layout of
+ * CalendarDemo.
+ */
+class CalendarFrame extends Frame
+{
+ /**
+ * For serialization
+ */
+ private static final long serialVersionUID = -4289697663503820619L;
+
+ private static final boolean DEBUG = false;
+
+ private DemoApplet applet;
+
+ /**
+ * Constructs a new CalendarFrame that is initially invisible.
+ */
+ public CalendarFrame(DemoApplet myApplet)
+ {
+ super("Calendar Demo");
+ this.applet = myApplet;
+ init();
+
+ // When the window is closed, we want to shut down the applet or application
+ addWindowListener(
+ new WindowAdapter() {
+ public void windowClosing(WindowEvent e) {
+ setVisible(false);
+ dispose();
+
+ if (applet != null) {
+ applet.demoClosed();
+ } else System.exit(0);
+ }
+ } );
+ }
+
+ private Choice displayMenu;
+ private Locale[] locales = DemoUtility.getG7Locales();
+
+ private Calendar calendars[] = new Calendar[2];
+ private Choice calMenu[] = new Choice[2];
+ private ColoredLabel monthLabel[] = new ColoredLabel[2];
+ private DateFormat monthFormat[] = new DateFormat[2];
+
+ private Button prevYear;
+ private Button prevMonth;
+ private Button gotoToday;
+ private Button nextMonth;
+ private Button nextYear;
+ private CalendarPanel calendarPanel;
+
+ private static void add(Container container, Component component,
+ GridBagLayout g, GridBagConstraints c,
+ int gridwidth, int weightx)
+ {
+ c.gridwidth = gridwidth;
+ c.weightx = weightx;
+ g.setConstraints(component, c);
+ container.add(component);
+ }
+
+ /**
+ * Initializes the applet. You never need to call this directly, it
+ * is called automatically by the system once the applet is created.
+ */
+ public void init() {
+ setBackground(DemoUtility.bgColor);
+ setLayout(new BorderLayout(10,10));
+
+ Panel topPanel = new Panel();
+ GridBagLayout g = new GridBagLayout();
+ topPanel.setLayout(g);
+ GridBagConstraints c = new GridBagConstraints();
+ c.fill = GridBagConstraints.HORIZONTAL;
+
+ // Build the two menus for selecting which calendar is displayed,
+ // plus the month/year label for each calendar
+ for (int i = 0; i < 2; i++) {
+ calMenu[i] = new Choice();
+ for (int j = 0; j < CALENDARS.length; j++) {
+ calMenu[i].addItem(CALENDARS[j].name);
+ }
+ calMenu[i].setBackground(DemoUtility.choiceColor);
+ calMenu[i].select(i);
+ calMenu[i].addItemListener(new CalMenuListener());
+
+ // Label for the current month name
+ monthLabel[i] = new ColoredLabel("", COLORS[i]);
+ monthLabel[i].setFont(DemoUtility.titleFont);
+
+ // And the default calendar to use for this slot
+ calendars[i] = CALENDARS[i].calendar;
+
+ add(topPanel, calMenu[i], g, c, 5, 0);
+ add(topPanel, monthLabel[i], g, c, GridBagConstraints.REMAINDER, 1);
+ }
+
+ // Now add the next/previous year/month buttons:
+ prevYear = new Button("<<");
+ prevYear.addActionListener(new AddAction(Calendar.YEAR, -1));
+
+ prevMonth = new Button("<");
+ prevMonth.addActionListener(new AddAction(Calendar.MONTH, -1));
+
+ gotoToday = new Button("Today");
+ gotoToday.addActionListener( new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e) {
+ calendarPanel.setDate( new Date() );
+ updateMonthName();
+ }
+ } );
+
+ nextMonth = new Button(">");
+ nextMonth.addActionListener(new AddAction(Calendar.MONTH, 1));
+
+ nextYear = new Button(">>");
+ nextYear.addActionListener(new AddAction(Calendar.YEAR, 1));
+
+ c.fill = GridBagConstraints.NONE;
+ add(topPanel, prevYear, g, c, 1, 0);
+ add(topPanel, prevMonth, g, c, 1, 0);
+ add(topPanel, gotoToday, g, c, 1, 0);
+ add(topPanel, nextMonth, g, c, 1, 0);
+ add(topPanel, nextYear, g, c, 1, 0);
+
+ // Now add the menu for selecting the display language
+ Panel displayPanel = new Panel();
+ {
+ displayMenu = new Choice();
+ Locale defaultLocale = Locale.getDefault();
+ int bestMatch = -1, thisMatch = -1;
+ int selectMe = 0;
+
+ for (int i = 0; i < locales.length; i++) {
+ if (i > 0 &&
+ locales[i].getLanguage().equals(locales[i-1].getLanguage()) ||
+ i < locales.length - 1 &&
+ locales[i].getLanguage().equals(locales[i+1].getLanguage()))
+ {
+ displayMenu.addItem( locales[i].getDisplayName() );
+ } else {
+ displayMenu.addItem( locales[i].getDisplayLanguage());
+ }
+
+ thisMatch = DemoUtility.compareLocales(locales[i], defaultLocale);
+
+ if (thisMatch >= bestMatch) {
+ bestMatch = thisMatch;
+ selectMe = i;
+ }
+ }
+
+ displayMenu.setBackground(DemoUtility.choiceColor);
+ displayMenu.select(selectMe);
+
+ displayMenu.addItemListener( new ItemListener()
+ {
+ public void itemStateChanged(ItemEvent e) {
+ Locale loc = locales[displayMenu.getSelectedIndex()];
+ calendarPanel.setLocale( loc );
+ monthFormat[0] = monthFormat[1] = null;
+ updateMonthName();
+ repaint();
+ }
+ } );
+
+ Label l1 = new Label("Display Language:", Label.RIGHT);
+ l1.setFont(DemoUtility.labelFont);
+
+ displayPanel.setLayout(new FlowLayout());
+ displayPanel.add(l1);
+ displayPanel.add(displayMenu);
+
+ }
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.EAST;
+
+ add(topPanel, displayPanel, g, c, GridBagConstraints.REMAINDER, 0);
+
+ // The title, buttons, etc. go in a panel at the top of the window
+ add("North", topPanel);
+
+ // The copyright notice goes at the bottom of the window
+ Label copyright = new Label(DemoUtility.copyright1, Label.LEFT);
+ copyright.setFont(DemoUtility.creditFont);
+ add("South", copyright);
+
+ // Now create the big calendar panel and stick it in the middle
+ calendarPanel = new CalendarPanel( locales[displayMenu.getSelectedIndex()] );
+ add("Center", calendarPanel);
+
+ for (int i = 0; i < 2; i++) {
+ calendarPanel.setCalendar(i, calendars[i]);
+ calendarPanel.setColor(i, COLORS[i]);
+ }
+
+ updateMonthName();
+ }
+
+
+ private void updateMonthName()
+ {
+ for (int i = 0; i < 2; i++) {
+ try {
+ if (monthFormat[i] == null) { // TODO: optimize
+ DateFormat f = DateFormat.getDateTimeInstance(
+ calendars[i], DateFormat.MEDIUM, -1,
+ locales[displayMenu.getSelectedIndex()]);
+ if (f instanceof com.ibm.icu.text.SimpleDateFormat) {
+ com.ibm.icu.text.SimpleDateFormat f1 = (com.ibm.icu.text.SimpleDateFormat) f;
+ f1.applyPattern("MMMM, yyyy G");
+ f1.setTimeZone(new SimpleTimeZone(0, "UTC"));
+ }
+ monthFormat[i] = f;
+ }
+ } catch (ClassCastException e) {
+ //hey {lw} - there's something wrong in this routine that cuases exceptions.
+ System.out.println(e);
+ }
+
+ monthLabel[i].setText( monthFormat[i].format( calendarPanel.firstOfMonth() ));
+ }
+ }
+
+ /**
+ * CalMenuListener responds to events in the two popup menus that select
+ * the calendar systems to be used in the display. It figures out which
+ * of the two menus the event occurred in and updates the corresponding
+ * element of the calendars[] array to match the new selection.
+ */
+ private class CalMenuListener implements ItemListener
+ {
+ public void itemStateChanged(ItemEvent e)
+ {
+ for (int i = 0; i < calMenu.length; i++)
+ {
+ if (e.getItemSelectable() == calMenu[i])
+ {
+ // We found the menu that the event happened in.
+ // Figure out which new calendar they selected.
+ Calendar newCal = CALENDARS[ calMenu[i].getSelectedIndex() ].calendar;
+
+ if (newCal != calendars[i])
+ {
+ // If any of the other menus are set to the same new calendar
+ // we're about to use for this menu, set them to the current
+ // calendar from *this* menu so we won't have two the same
+ for (int j = 0; j < calendars.length; j++) {
+ if (j != i && calendars[j] == newCal) {
+ calendars[j] = calendars[i];
+ calendarPanel.setCalendar(j, calendars[j]);
+ monthFormat[j] = null;
+
+ for (int k = 0; k < CALENDARS.length; k++) {
+ if (calendars[j] == CALENDARS[k].calendar) {
+ calMenu[j].select(k);
+ break;
+ }
+ }
+ }
+ }
+ // Now update this menu to use the new calendar the user selected
+ calendars[i] = newCal;
+ calendarPanel.setCalendar(i, newCal);
+ monthFormat[i] = null;
+
+ updateMonthName();
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * AddAction handles the next/previous year/month buttons...
+ */
+ private class AddAction implements ActionListener {
+ AddAction(int field, int amount) {
+ this.field = field;
+ this.amount = amount;
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ calendarPanel.add(field, amount);
+ updateMonthName();
+ }
+
+ private int field, amount;
+ }
+
+ /**
+ * ColoredLabel is similar to java.awt.Label, with two differences:
+ *
+ * - You can set its text color
+ *
+ * - It draws text using drawString rather than using a host-specific
+ * "Peer" object like AWT does. On 1.2, using drawString gives
+ * us Bidi reordering for free.
+ */
+ static private class ColoredLabel extends Component {
+ /**
+ * For serialization
+ */
+ private static final long serialVersionUID = 5004484960341875722L;
+ public ColoredLabel(String label) {
+ text = label;
+ }
+
+ public ColoredLabel(String label, Color c) {
+ text = label;
+ color = c;
+ }
+
+ public void setText(String label) {
+ text = label;
+ repaint();
+ }
+
+ public void setFont(Font f) {
+ font = f;
+ repaint();
+ }
+
+ public void paint(Graphics g) {
+ FontMetrics fm = g.getFontMetrics(font);
+
+ Rectangle bounds = getBounds();
+
+ g.setColor(color);
+ g.setFont(font);
+ g.drawString(text, fm.stringWidth("\u00a0"),
+ bounds.height/2 + fm.getHeight()
+ - fm.getAscent() + fm.getLeading()/2);
+ }
+
+ public Dimension getPreferredSize() {
+ return getMinimumSize();
+ }
+
+ public Dimension getMinimumSize() {
+ FontMetrics fm = getFontMetrics(font);
+
+ return new Dimension( fm.stringWidth(text) + 2*fm.stringWidth("\u00a0"),
+ fm.getHeight() + fm.getLeading()*2);
+ }
+
+ String text;
+ Color color = Color.black;
+ Font font = DemoUtility.labelFont;
+ }
+
+ /**
+ * Print out the error message while debugging this program.
+ */
+ public void errorText(String s)
+ {
+ if (DEBUG)
+ {
+ System.out.println(s);
+ }
+ }
+
+ class CalendarRec {
+ public CalendarRec(String nameStr, Calendar cal)
+ {
+ name = nameStr;
+ calendar = cal;
+ }
+
+ Calendar calendar;
+ String name;
+ }
+
+ private final CalendarRec[] CALENDARS = {
+ new CalendarRec("Gregorian Calendar", new GregorianCalendar()),
+ new CalendarRec("Hebrew Calendar", new HebrewCalendar()),
+ new CalendarRec("Islamic Calendar", makeIslamic(false)),
+ new CalendarRec("Islamic Civil Calendar ", makeIslamic(true)),
+ new CalendarRec("Buddhist Calendar", new BuddhistCalendar()),
+ new CalendarRec("Japanese Calendar", new JapaneseCalendar()),
+ };
+
+ static private final Calendar makeIslamic(boolean civil) {
+ IslamicCalendar cal = new IslamicCalendar();
+ cal.setCivil(civil);
+ return cal;
+ }
+
+ static final Color[] COLORS = { Color.blue, Color.black };
+}
+
diff --git a/demos/src/com/ibm/icu/dev/demo/calendar/CalendarPanel.java b/demos/src/com/ibm/icu/dev/demo/calendar/CalendarPanel.java
new file mode 100644
index 0000000..8ea94d3
--- /dev/null
+++ b/demos/src/com/ibm/icu/dev/demo/calendar/CalendarPanel.java
@@ -0,0 +1,365 @@
+/*
+ *******************************************************************************
+ * Copyright (C) 1997-2007, International Business Machines Corporation and *
+ * others. All Rights Reserved. *
+ *******************************************************************************
+ */
+
+package com.ibm.icu.dev.demo.calendar;
+
+import java.awt.Canvas;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Point;
+import java.util.Date;
+import java.util.Locale;
+
+import com.ibm.icu.dev.demo.impl.DemoUtility;
+import com.ibm.icu.text.DateFormatSymbols;
+import com.ibm.icu.util.Calendar;
+import com.ibm.icu.util.SimpleTimeZone;
+
+class CalendarPanel extends Canvas {
+
+ /**
+ * For serialization
+ */
+ private static final long serialVersionUID = 625400018027387141L;
+
+ public CalendarPanel( Locale locale ) {
+ setLocale(locale);
+ }
+
+ public void setLocale(Locale locale) {
+ if (fDisplayLocale == null || !fDisplayLocale.equals(locale)) {
+ fDisplayLocale = locale;
+ dirty = true;
+
+ for (int i = 0; i < fCalendar.length; i++) {
+ if (fCalendar[i] != null) {
+ fSymbols[i] = new DateFormatSymbols(fCalendar[i],
+ fDisplayLocale);
+ }
+ }
+ String lang = locale.getLanguage();
+ leftToRight = !(lang.equals("iw") || lang.equals("ar"));
+
+ repaint();
+ }
+ }
+
+ public void setDate(Date date) {
+ fStartOfMonth = date;
+ dirty = true;
+ repaint();
+ }
+
+ public void add(int field, int delta)
+ {
+ synchronized(fCalendar) {
+ fCalendar[0].setTime(fStartOfMonth);
+ fCalendar[0].add(field, delta);
+ fStartOfMonth = fCalendar[0].getTime();
+ }
+ dirty = true;
+ repaint();
+ }
+
+ public void setColor(int index, Color c) {
+ fColor[index] = c;
+ repaint();
+ }
+
+ public void setCalendar(int index, Calendar c) {
+ Date date = (fCalendar[index] == null) ? new Date()
+ : fCalendar[index].getTime();
+
+ fCalendar[index] = c;
+ fCalendar[index].setTime(date);
+
+ fSymbols[index] = new DateFormatSymbols(c, fDisplayLocale);
+ dirty = true;
+ repaint();
+ }
+
+ public Calendar getCalendar(int index) {
+ return fCalendar[index];
+ }
+
+ public Locale getDisplayLocale() {
+ return fDisplayLocale;
+ }
+
+ public Date firstOfMonth() {
+ return fStartOfMonth;
+ }
+
+ private Date startOfMonth(Date dateInMonth)
+ {
+ synchronized(fCalendar) {
+ fCalendar[0].setTime(dateInMonth);
+
+ int era = fCalendar[0].get(Calendar.ERA);
+ int year = fCalendar[0].get(Calendar.YEAR);
+ int month = fCalendar[0].get(Calendar.MONTH);
+
+ fCalendar[0].clear();
+ fCalendar[0].set(Calendar.ERA, era);
+ fCalendar[0].set(Calendar.YEAR, year);
+ fCalendar[0].set(Calendar.MONTH, month);
+ fCalendar[0].set(Calendar.DATE, 1);
+
+ return fCalendar[0].getTime();
+ }
+ }
+
+ private void calculate()
+ {
+ //
+ // As a workaround for JDK 1.1.3 and below, where Calendars and time
+ // zones are a bit goofy, always set my calendar's time zone to UTC.
+ // You would think I would want to do this in the "set" function above,
+ // but if I do that, the program hangs when this class is loaded,
+ // perhaps due to some sort of static initialization ordering problem.
+ // So I do it here instead.
+ //
+ fCalendar[0].setTimeZone(new SimpleTimeZone(0, "UTC"));
+
+ Calendar c = (Calendar)fCalendar[0].clone(); // Temporary copy
+
+ fStartOfMonth = startOfMonth(fStartOfMonth);
+
+ // Stash away a few useful constants for this calendar and display
+ minDay = c.getMinimum(Calendar.DAY_OF_WEEK);
+ daysInWeek = c.getMaximum(Calendar.DAY_OF_WEEK) - minDay + 1;
+
+ firstDayOfWeek = Calendar.getInstance(fDisplayLocale).getFirstDayOfWeek();
+
+ // Stash away a Date for the start of this month
+
+ // Find the day of week of the first day in this month
+ c.setTime(fStartOfMonth);
+ firstDayInMonth = c.get(Calendar.DAY_OF_WEEK);
+ int firstWeek = c.get(Calendar.WEEK_OF_MONTH);
+
+ // Now find the # of days in the month
+ c.roll(Calendar.DATE, false);
+ daysInMonth = c.get(Calendar.DATE);
+
+ // Finally, find the end of the month, i.e. the start of the next one
+ c.roll(Calendar.DATE, true);
+ c.add(Calendar.MONTH, 1);
+ c.getTime(); // JDK 1.1.2 bug workaround
+ c.add(Calendar.SECOND, -1);
+ Date endOfMonth = c.getTime();
+ if(endOfMonth==null){
+ //do nothing
+ }
+ endOfMonth = null;
+ int lastWeek = c.get(Calendar.WEEK_OF_MONTH);
+
+ // Calculate the number of full or partial weeks in this month.
+ numWeeks = lastWeek - firstWeek + 1;
+
+ dirty = false;
+ }
+
+ static final int XINSET = 4;
+ static final int YINSET = 2;
+
+ /*
+ * Convert from the day number within a month (1-based)
+ * to the cell coordinates on the calendar (0-based)
+ */
+ private void dateToCell(int date, Point pos)
+ {
+ int cell = (date + firstDayInMonth - firstDayOfWeek - minDay);
+ if (firstDayInMonth < firstDayOfWeek) {
+ cell += daysInWeek;
+ }
+
+ pos.x = cell % daysInWeek;
+ pos.y = cell / daysInWeek;
+ }
+ //private Point dateToCell(int date) {
+ // Point p = new Point(0,0);
+ // dateToCell(date, p);
+ // return p;
+ //}
+
+ public void paint(Graphics g) {
+
+ if (dirty) {
+ calculate();
+ }
+
+ Point cellPos = new Point(0,0); // Temporary variable
+ Dimension d = this.getSize();
+
+ g.setColor(Color.lightGray);
+ g.fillRect(0,0,d.width,d.height);
+
+ // Draw the day names at the top
+ g.setColor(Color.black);
+ g.setFont(DemoUtility.labelFont);
+ FontMetrics fm = g.getFontMetrics();
+ int labelHeight = fm.getHeight() + YINSET * 2;
+
+ int v = fm.getAscent() + YINSET;
+ for (int i = 0; i < daysInWeek; i++) {
+ int dayNum = (i + minDay + firstDayOfWeek - 2) % daysInWeek + 1;
+ String dayName = fSymbols[0].getWeekdays()[dayNum];
+
+
+ double h;
+ if (leftToRight) {
+ h = d.width*(i + 0.5) / daysInWeek;
+ } else {
+ h = d.width*(daysInWeek - i - 0.5) / daysInWeek;
+ }
+ h -= fm.stringWidth(dayName) / 2;
+
+ g.drawString(dayName, (int)h, v);
+ }
+
+ double cellHeight = (d.height - labelHeight - 1) / numWeeks;
+ double cellWidth = (double)(d.width - 1) / daysInWeek;
+
+ // Draw a white background in the part of the calendar
+ // that displays this month.
+ // First figure out how much of the first week should be shaded.
+ {
+ g.setColor(Color.white);
+ dateToCell(1, cellPos);
+ int width = (int)(cellPos.x*cellWidth); // Width of unshaded area
+
+ if (leftToRight) {
+ g.fillRect((int)(width), labelHeight ,
+ d.width - width, (int)cellHeight);
+ } else {
+ g.fillRect(0, labelHeight ,
+ d.width - width, (int)cellHeight);
+ }
+
+ // All of the intermediate weeks get shaded completely
+ g.fillRect(0, (int)(labelHeight + cellHeight),
+ d.width, (int)(cellHeight * (numWeeks - 2)));
+
+ // Now figure out the last week.
+ dateToCell(daysInMonth, cellPos);
+ width = (int)((cellPos.x+1)*cellWidth); // Width of shaded area
+
+ if (leftToRight) {
+ g.fillRect(0, (int)(labelHeight + (numWeeks-1) * cellHeight),
+ width, (int)cellHeight);
+ } else {
+ g.fillRect(d.width - width, (int)(labelHeight + (numWeeks-1) * cellHeight),
+ width, (int)cellHeight);
+ }
+
+ }
+ // Draw the X/Y grid lines
+ g.setColor(Color.black);
+ for (int i = 0; i <= numWeeks; i++) {
+ int y = (int)(labelHeight + i * cellHeight);
+ g.drawLine(0, y, d.width - 1, y);
+ }
+ for (int i = 0; i <= daysInWeek; i++) {
+ int x = (int)(i * cellWidth);
+ g.drawLine(x, labelHeight, x, d.height - 1);
+ }
+
+ // Now loop through all of the days in the month, figure out where
+ // they go in the grid, and draw the day # for each one
+
+ // Figure out the date of the first cell in the calendar display
+ int cell = (1 + firstDayInMonth - firstDayOfWeek - minDay);
+ if (firstDayInMonth < firstDayOfWeek) {
+ cell += daysInWeek;
+ }
+
+ Calendar c = (Calendar)fCalendar[0].clone();
+ c.setTime(fStartOfMonth);
+ c.add(Calendar.DATE, -cell);
+
+ StringBuffer buffer = new StringBuffer();
+
+ for (int row = 0; row < numWeeks; row++) {
+ for (int col = 0; col < daysInWeek; col++) {
+
+ g.setFont(DemoUtility.numberFont);
+ g.setColor(Color.black);
+ fm = g.getFontMetrics();
+
+ int cellx;
+ if (leftToRight) {
+ cellx = (int)((col) * cellWidth);
+ } else {
+ cellx = (int)((daysInWeek - col - 1) * cellWidth);
+ }
+
+ int celly = (int)(row * cellHeight + labelHeight);
+
+ for (int i = 0; i < 2; i++) {
+ fCalendar[i].setTime(c.getTime());
+
+ int date = fCalendar[i].get(Calendar.DATE);
+ buffer.setLength(0);
+ buffer.append(date);
+ String dayNum = buffer.toString();
+
+ int x;
+
+ if (leftToRight) {
+ x = cellx + (int)cellWidth - XINSET - fm.stringWidth(dayNum);
+ } else {
+ x = cellx + XINSET;
+ }
+ int y = celly + + fm.getAscent() + YINSET + i * fm.getHeight();
+
+ if (fColor[i] != null) {
+ g.setColor(fColor[i]);
+ }
+ g.drawString(dayNum, x, y);
+
+ if (date == 1 || row == 0 && col == 0) {
+ g.setFont(DemoUtility.numberFont);
+ String month = fSymbols[i].getMonths()[
+ fCalendar[i].get(Calendar.MONTH)];
+
+ if (leftToRight) {
+ x = cellx + XINSET;
+ } else {
+ x = cellx + (int)cellWidth - XINSET - fm.stringWidth(month);
+ }
+ g.drawString(month, x, y);
+ }
+ }
+
+ c.add(Calendar.DATE, 1);
+ }
+ }
+ }
+
+ // Important state variables
+ private Calendar[] fCalendar = new Calendar[4];
+ private Color[] fColor = new Color[4];
+
+ private Locale fDisplayLocale;
+ private DateFormatSymbols[] fSymbols = new DateFormatSymbols[4];
+
+ private Date fStartOfMonth = new Date(); // 00:00:00 on first day of month
+
+ // Cached calculations to make drawing faster.
+ private transient int minDay; // Minimum legal day #
+ private transient int daysInWeek; // # of days in a week
+ private transient int firstDayOfWeek; // First day to display in week
+ private transient int numWeeks; // # full or partial weeks in month
+ private transient int daysInMonth; // # days in this month
+ private transient int firstDayInMonth; // Day of week of first day in month
+ private transient boolean leftToRight;
+
+ private transient boolean dirty = true;
+}
diff --git a/demos/src/com/ibm/icu/dev/demo/calendar/package.html b/demos/src/com/ibm/icu/dev/demo/calendar/package.html
new file mode 100644
index 0000000..c1bb105
--- /dev/null
+++ b/demos/src/com/ibm/icu/dev/demo/calendar/package.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!-- Copyright (C) 2000-2004, International Business Machines Corporation and
+ others. All Rights Reserved.
+
+-->
+</head>
+<body bgcolor="white">
+Calendar demo applications including date/time arithmetic.
+</body>
+</html>
\ No newline at end of file
diff --git a/demos/src/com/ibm/icu/dev/demo/charsetdet/DetectingViewer.java b/demos/src/com/ibm/icu/dev/demo/charsetdet/DetectingViewer.java
new file mode 100644
index 0000000..284d16d
--- /dev/null
+++ b/demos/src/com/ibm/icu/dev/demo/charsetdet/DetectingViewer.java
@@ -0,0 +1,421 @@
+/*
+ **************************************************************************
+ * Copyright (C) 2005-2010, International Business Machines Corporation *
+ * and others. All Rights Reserved. *
+ **************************************************************************
+ *
+ */
+
+package com.ibm.icu.dev.demo.charsetdet;
+
+import java.awt.Font;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.security.AccessControlException;
+
+import javax.swing.JFileChooser;
+import javax.swing.JFrame;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.JOptionPane;
+import javax.swing.JScrollPane;
+import javax.swing.JTextPane;
+import javax.swing.KeyStroke;
+
+import com.ibm.icu.charset.CharsetICU;
+import com.ibm.icu.dev.demo.impl.DemoApplet;
+import com.ibm.icu.text.CharsetDetector;
+import com.ibm.icu.text.CharsetMatch;
+
+/**
+ * This simple application demonstrates how to use the CharsetDetector API. It
+ * opens a file or web page, detects the encoding, and then displays it using that
+ * encoding.
+ */
+public class DetectingViewer extends JFrame implements ActionListener
+{
+
+ /**
+ * For serialization
+ */
+ private static final long serialVersionUID = -2307065724464747775L;
+ private JTextPane text;
+ private JFileChooser fileChooser;
+
+ /**
+ * @throws java.awt.HeadlessException
+ */
+ public DetectingViewer()
+ {
+ super();
+ DemoApplet.demoFrameOpened();
+
+ try {
+ fileChooser = new JFileChooser();
+ } catch (AccessControlException ace) {
+ System.err.println("no file chooser - access control exception. Continuing without file browsing. "+ace.toString());
+ fileChooser = null; //
+ }
+
+// setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ setSize(800, 800);
+
+ setJMenuBar(makeMenus());
+ text = new JTextPane();
+ text.setContentType("text/plain");
+ text.setText("");
+ text.setSize(800, 800);
+
+ Font font = new Font("Arial Unicode MS", Font.PLAIN, 24);
+ text.setFont(font);
+
+ JScrollPane scrollPane = new JScrollPane(text);
+
+ getContentPane().add(scrollPane);
+ setVisible(true);
+
+ addWindowListener(
+ new WindowAdapter() {
+ public void windowClosing(WindowEvent e) {
+// setVisible(false);
+// dispose();
+
+ doQuit();
+ }
+ } );
+
+
+ }
+
+ public void actionPerformed(ActionEvent event)
+ {
+ String cmd = event.getActionCommand();
+
+ if (cmd.equals("New...")) {
+ doNew();
+ } else if (cmd.equals("Open File...")) {
+ doOpenFile();
+ } else if (cmd.equals("Open URL...")) {
+ doOpenURL();
+ } else if (cmd.equals("Quit")) {
+ doQuit();
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ new DetectingViewer();
+ }
+
+ private void errorDialog(String title, String msg)
+ {
+ JOptionPane.showMessageDialog(this, msg, title, JOptionPane.ERROR_MESSAGE);
+ }
+
+ private BufferedInputStream openFile(File file)
+ {
+ FileInputStream fileStream = null;
+
+ try {
+ fileStream = new FileInputStream(file);
+ } catch (Exception e) {
+ errorDialog("Error Opening File", e.getMessage());
+ return null;
+ }
+
+ return new BufferedInputStream(fileStream);
+ }
+
+// private void openFile(String directory, String filename)
+// {
+// openFile(new File(directory, filename));
+// }
+
+
+ private BufferedInputStream openURL(String url)
+ {
+ InputStream s = null;
+
+ try {
+ URL aURL = new URL(url);
+ s = aURL.openStream();
+ } catch (Exception e) {
+ errorDialog("Error Opening URL", e.getMessage());
+ return null;
+ }
+
+ return new BufferedInputStream(s);
+ }
+
+ private String encodingName(CharsetMatch match)
+ {
+ return match.getName() + " (" + match.getLanguage() + ")";
+ }
+
+ private void setMatchMenu(CharsetMatch[] matches)
+ {
+ JMenu menu = getJMenuBar().getMenu(1);
+ JMenuItem menuItem;
+
+ menu.removeAll();
+
+ for (int i = 0; i < matches.length; i += 1) {
+ CharsetMatch match = matches[i];
+
+ menuItem = new JMenuItem(encodingName(match) + " " + match.getConfidence());
+
+ menu.add(menuItem);
+ }
+ }
+
+ private byte[] scriptTag = {(byte) 's', (byte) 'c', (byte) 'r', (byte) 'i', (byte) 'p', (byte) 't'};
+ private byte[] styleTag = {(byte) 's', (byte) 't', (byte) 'y', (byte) 'l', (byte) 'e'};
+ private static int BUFFER_SIZE = 100000;
+
+ private boolean openTag(byte[] buffer, int offset, int length, byte[] tag)
+ {
+ int tagLen = tag.length;
+ int bufRem = length - offset;
+ int b;
+
+ for (b = 0; b < tagLen && b < bufRem; b += 1) {
+ if (buffer[b + offset] != tag[b]) {
+ return false;
+ }
+ }
+
+ return b == tagLen;
+ }
+
+ private boolean closedTag(byte[] buffer, int offset, int length, byte[] tag)
+ {
+ if (buffer[offset] != (byte) '/') {
+ return false;
+ }
+
+ return openTag(buffer, offset + 1, length, tag);
+ }
+
+ private byte[] filter(InputStream in)
+ {
+ byte[] buffer = new byte[BUFFER_SIZE];
+ int bytesRemaining = BUFFER_SIZE;
+ int bufLen = 0;
+
+ in.mark(BUFFER_SIZE);
+
+ try {
+ while (bytesRemaining > 0) {
+ int bytesRead = in.read(buffer, bufLen, bytesRemaining);
+
+ if (bytesRead <= 0) {
+ break;
+ }
+
+ bufLen += bytesRead;
+ bytesRemaining -= bytesRead;
+ }
+ } catch (Exception e) {
+ // TODO: error handling?
+ return null;
+ }
+
+ boolean inTag = false;
+ boolean skip = false;
+ int out = 0;
+
+ for (int i = 0; i < bufLen; i += 1) {
+ byte b = buffer[i];
+
+ if (b == (byte) '<') {
+ inTag = true;
+
+ if (openTag(buffer, i + 1, bufLen, scriptTag) ||
+ openTag(buffer, i + 1, bufLen, styleTag)) {
+ skip = true;
+ } else if (closedTag(buffer, i + 1, bufLen, scriptTag) ||
+ closedTag(buffer, i + 1, bufLen, styleTag)) {
+ skip = false;
+ }
+ } else if (b == (byte) '>') {
+ inTag = false;
+ } else if (! (inTag || skip)) {
+ buffer[out++] = b;
+ }
+ }
+
+ byte[] filtered = new byte[out];
+
+ System.arraycopy(buffer, 0, filtered, 0, out);
+ return filtered;
+ }
+
+ private CharsetMatch[] detect(byte[] bytes)
+ {
+ CharsetDetector det = new CharsetDetector();
+
+ det.setText(bytes);
+
+ return det.detectAll();
+ }
+
+ private CharsetMatch[] detect(BufferedInputStream inputStream)
+ {
+ CharsetDetector det = new CharsetDetector();
+
+ try {
+ det.setText(inputStream);
+
+ return det.detectAll();
+ } catch (Exception e) {
+ // TODO: error message?
+ return null;
+ }
+ }
+
+ private void show(InputStream inputStream, CharsetMatch[] matches, String title)
+ {
+ InputStreamReader isr;
+ char[] buffer = new char[1024];
+ int bytesRead = 0;
+
+ if (matches == null || matches.length == 0) {
+ errorDialog("Match Error", "No matches!");
+ return;
+ }
+
+ try {
+ StringBuffer sb = new StringBuffer();
+ String encoding = matches[0].getName();
+
+ inputStream.reset();
+
+ if (encoding.startsWith("UTF-32")) {
+ byte[] bytes = new byte[1024];
+ int offset = 0;
+ int chBytes = 0;
+ Charset utf32 = CharsetICU.forNameICU(encoding);
+
+ while ((bytesRead = inputStream.read(bytes, offset, 1024)) >= 0) {
+ offset = bytesRead % 4;
+ chBytes = bytesRead - offset;
+
+ sb.append(utf32.decode(ByteBuffer.wrap(bytes)).toString());
+
+ if (offset != 0) {
+ for (int i = 0; i < offset; i += 1) {
+ bytes[i] = bytes[chBytes + i];
+ }
+ }
+ }
+ } else {
+ isr = new InputStreamReader(inputStream, encoding);
+
+ while ((bytesRead = isr.read(buffer, 0, 1024)) >= 0) {
+ sb.append(buffer, 0, bytesRead);
+ }
+
+ isr.close();
+ }
+
+ this.setTitle(title + " - " + encodingName(matches[0]));
+
+ setMatchMenu(matches);
+ text.setText(sb.toString());
+ } catch (IOException e) {
+ errorDialog("IO Error", e.getMessage());
+ } catch (Exception e) {
+ errorDialog("Internal Error", e.getMessage());
+ }
+ }
+
+ private void doNew()
+ {
+ // open a new window...
+ }
+
+ private void doOpenFile()
+ {
+ int retVal = fileChooser.showOpenDialog(this);
+
+ if (retVal == JFileChooser.APPROVE_OPTION) {
+ File file = fileChooser.getSelectedFile();
+ BufferedInputStream inputStream = openFile(file);
+
+ if (inputStream != null) {
+ CharsetMatch[] matches = detect(inputStream);
+
+ show(inputStream, matches, file.getName());
+ }
+ }
+ }
+
+ private void doOpenURL()
+ {
+ String url = (String) JOptionPane.showInputDialog(this, "URL to open:", "Open URL", JOptionPane.PLAIN_MESSAGE,
+ null, null, null);
+
+ if (url != null && url.length() > 0) {
+ BufferedInputStream inputStream = openURL(url);
+
+ if (inputStream != null) {
+ byte[] filtered = filter(inputStream);
+ CharsetMatch[] matches = detect(filtered);
+
+ show(inputStream, matches, url);
+ }
+ }
+}
+
+ private void doQuit()
+ {
+ DemoApplet.demoFrameClosed();
+ this.setVisible(false);
+ this.dispose();
+ }
+
+ private JMenuBar makeMenus()
+ {
+ JMenu menu = new JMenu("File");
+ JMenuItem mi;
+
+ mi = new JMenuItem("Open File...");
+ mi.setAccelerator((KeyStroke.getKeyStroke(KeyEvent.VK_O, ActionEvent.CTRL_MASK)));
+ mi.addActionListener(this);
+ menu.add(mi);
+ if(fileChooser == null) {
+ mi.setEnabled(false); // no file chooser.
+ }
+
+ mi = new JMenuItem("Open URL...");
+ mi.setAccelerator((KeyStroke.getKeyStroke(KeyEvent.VK_U, ActionEvent.CTRL_MASK)));
+ mi.addActionListener(this);
+ menu.add(mi);
+
+ mi = new JMenuItem("Quit");
+ mi.setAccelerator((KeyStroke.getKeyStroke(KeyEvent.VK_Q, ActionEvent.CTRL_MASK)));
+ mi.addActionListener(this);
+ menu.add(mi);
+
+ JMenuBar mbar = new JMenuBar();
+ mbar.add(menu);
+
+ menu = new JMenu("Detected Encodings");
+ mbar.add(menu);
+
+ return mbar;
+ }
+}
diff --git a/demos/src/com/ibm/icu/dev/demo/holiday/HolidayBorderPanel.java b/demos/src/com/ibm/icu/dev/demo/holiday/HolidayBorderPanel.java
new file mode 100644
index 0000000..cd81ef1
--- /dev/null
+++ b/demos/src/com/ibm/icu/dev/demo/holiday/HolidayBorderPanel.java
@@ -0,0 +1,552 @@
+/*
+ *******************************************************************************
+ * Copyright (C) 1997-2010, International Business Machines Corporation and *
+ * others. All Rights Reserved. *
+ *******************************************************************************
+ */
+package com.ibm.icu.dev.demo.holiday;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Insets;
+import java.awt.Panel;
+
+/**
+ * Various graphical borders. The border itself is a Panel so that it can
+ * contain other Components (i.e. it borders something). You use the
+ * HolidayBorderPanel like any other Panel: you set the layout that you prefer and
+ * add Components to it. Beware that a null layout does not obey the insets
+ * of the panel so if you use null layouts, adjust your measurements to
+ * handle the border by calling insets().
+ *
+ * @author Andy Clark, Taligent Inc.
+ * @version 1.0
+ */
+public class HolidayBorderPanel extends Panel {
+ /**
+ * For serialization
+ */
+ private static final long serialVersionUID = 4669213306492461159L;
+ // Constants
+
+ /** Solid border. */
+ public final static int SOLID = 0;
+ /** A raised border. */
+ public final static int RAISED = 1;
+ /** A lowered border. */
+ public final static int LOWERED = 2;
+ /** An etched in border. */
+ public final static int IN = 3;
+ /** An etched out border. */
+ public final static int OUT = 4;
+
+ /** Left alignment. */
+ public final static int LEFT = 0;
+ /** Center alignment. */
+ public final static int CENTER = 1;
+ /** Right alignment. */
+ public final static int RIGHT = 2;
+
+ /** Default style (IN). */
+ public final static int DEFAULT_STYLE = IN;
+ /** Default thickness (10). */
+ public final static int DEFAULT_THICKNESS = 10;
+ /** Default thickness for solid borders (4). */
+ public final static int DEFAULT_SOLID_THICKNESS = 4;
+ /** Default thickness for raised borders (2). */
+ public final static int DEFAULT_RAISED_THICKNESS = 2;
+ /** Default thickness for lowered borders (2). */
+ public final static int DEFAULT_LOWERED_THICKNESS = 2;
+ /** Default thickness for etched-in borders (10). */
+ public final static int DEFAULT_IN_THICKNESS = 10;
+ /** Default thickness for etched-out borders (10). */
+ public final static int DEFAULT_OUT_THICKNESS = 10;
+ /** Default gap between border and contained component (5). */
+ public final static int DEFAULT_GAP = 5;
+ /** Default color (black). Applies to SOLID and etched borders. */
+ public final static Color DEFAULT_COLOR = Color.black;
+
+ /** Default font (TimesRoman,PLAIN,14). Only applies to etched borders. */
+ public final static Font DEFAULT_FONT = new Font("TimesRoman", Font.PLAIN, 14);
+ /** Default alignment (LEFT). Only applies to etched borders. */
+ public final static int DEFAULT_ALIGNMENT = LEFT;
+
+ // Data
+ private int style;
+ private int thickness;
+ private int gap;
+ private Color color;
+
+ private Font font;
+ private String text;
+ private int alignment;
+
+ /**
+ * Constructor. Makes default border.
+ */
+ public HolidayBorderPanel() {
+
+ // initialize data
+ style = DEFAULT_STYLE;
+ thickness = DEFAULT_THICKNESS;
+ gap = DEFAULT_GAP;
+ color = DEFAULT_COLOR;
+
+ text = null;
+ font = DEFAULT_FONT;
+ alignment = DEFAULT_ALIGNMENT;
+
+ }
+
+ /**
+ * Constructor. Makes an etched IN border with given text caption.
+ *
+ * @param text Text caption
+ */
+ public HolidayBorderPanel(String text) {
+ this();
+
+ style = IN;
+ this.text = text;
+ }
+
+ /**
+ * Constructor. Makes SOLID border with color and thickness given.
+ *
+ * @param color The color for the border.
+ * @param thickness The thickness of the border.
+ */
+ public HolidayBorderPanel(Color color, int thickness) {
+ this();
+
+ style = SOLID;
+ this.color = color;
+ this.thickness = thickness;
+ }
+
+ /**
+ * Constructor. Makes a border of the given style with the default
+ * thickness for that style.
+ *
+ * @param style The style for this border.
+ */
+ public HolidayBorderPanel(int style) {
+ this();
+
+ // set thickness appropriate to this style
+ switch (style) {
+ case SOLID: thickness = DEFAULT_SOLID_THICKNESS; break;
+ case RAISED: thickness = DEFAULT_RAISED_THICKNESS; break;
+ case LOWERED: thickness = DEFAULT_LOWERED_THICKNESS; break;
+ case IN: thickness = DEFAULT_IN_THICKNESS; break;
+ case OUT: thickness = DEFAULT_OUT_THICKNESS; break;
+ default:
+ thickness = DEFAULT_THICKNESS;
+ }
+
+ this.style = style;
+ }
+
+ /**
+ * Constructor. Makes border with given style and thickness.
+ *
+ * @param style The style for this border.
+ * @param thickness The thickness for this border.
+ */
+ public HolidayBorderPanel(int style, int thickness) {
+ this();
+
+ this.style = style;
+ this.thickness = thickness;
+ }
+
+ /**
+ * Returns the insets of this panel..
+ */
+ public Insets getInsets() {
+ int adjustment = 0;
+
+ // adjust for text string
+ if (style == IN || style == OUT) {
+ if (text != null && text.length() > 0) {
+ try {
+ // set font and get info
+ int height = getGraphics().getFontMetrics(font).getHeight();
+ if (height > thickness)
+ adjustment = height - thickness;
+ }
+ catch (Exception e) {
+ // nothing: just in case there is no graphics context
+ // at the beginning.
+ System.out.print("");
+ }
+ }
+ }
+
+ // return appropriate insets
+ int dist = thickness + gap;
+ return new Insets(dist + adjustment, dist, dist, dist);
+ }
+
+ /**
+ * Sets the style of the border
+ *
+ * @param style The new style.
+ */
+ public HolidayBorderPanel setStyle(int style) {
+
+ // set the style and re-layout the panel
+ this.style = style;
+ doLayout();
+ repaint();
+
+ return this;
+ }
+
+ /**
+ * Gets the style of the border
+ */
+ public int getStyle() {
+
+ return style;
+ }
+
+ /**
+ * Sets the thickness of the border.
+ *
+ * @param thickness The new thickness
+ */
+ public HolidayBorderPanel setThickness(int thickness) {
+
+ if (thickness > 0) {
+ this.thickness = thickness;
+ doLayout();
+ repaint();
+ }
+
+ return this;
+ }
+
+ /**
+ * Gets the thickness of the border.
+ */
+ public int getThickness() {
+
+ return thickness;
+ }
+
+ /**
+ * Sets the gap between the border and the contained Component.
+ *
+ * @param gap The new gap, in pixels.
+ */
+ public HolidayBorderPanel setGap(int gap) {
+
+ if (gap > -1) {
+ this.gap = gap;
+ doLayout();
+ repaint();
+ }
+
+ return this;
+ }
+
+ /**
+ * Gets the gap between the border and the contained Component.
+ */
+ public int getGap() {
+
+ return gap;
+ }
+
+ /**
+ * Sets the current color for SOLID borders and the caption text
+ * color for etched borders.
+ *
+ * @param color The new color.
+ */
+ public HolidayBorderPanel setColor(Color color) {
+
+ this.color = color;
+ if (style == SOLID || style == IN || style == OUT)
+ repaint();
+
+ return this;
+ }
+
+ /**
+ * Gets the current color for SOLID borders and the caption
+ * text color for etched borders.
+ */
+ public Color getColor() {
+
+ return color;
+ }
+
+ /**
+ * Sets the font. Only applies to etched borders.
+ */
+ public HolidayBorderPanel setTextFont(Font font) {
+
+ // set font
+ if (font != null) {
+ this.font = font;
+ if (style == IN || style == OUT) {
+ doLayout();
+ repaint();
+ }
+ }
+
+ return this;
+ }
+
+ /**
+ * Gets the font of the text. Only applies to etched borders.
+ */
+ public Font getTextFont() {
+
+ return font;
+ }
+
+ /**
+ * Sets the text. Only applies to etched borders.
+ *
+ * @param text The new text.
+ */
+ public HolidayBorderPanel setText(String text) {
+
+ this.text = text;
+ if (style == IN || style == OUT) {
+ doLayout();
+ repaint();
+ }
+
+ return this;
+ }
+
+ /**
+ * Gets the text. Only applies to etched borders.
+ */
+ public String getText() {
+
+ return text;
+ }
+
+ /**
+ * Sets the text alignment. Only applies to etched borders.
+ *
+ * @param alignment The new alignment.
+ */
+ public HolidayBorderPanel setAlignment(int alignment) {
+
+ this.alignment = alignment;
+ if (style == IN || style == OUT) {
+ doLayout();
+ repaint();
+ }
+
+ return this;
+ }
+
+ /**
+ * Gets the text alignment.
+ */
+ public int getAlignment() {
+
+ return alignment;
+ }
+
+ /**
+ * Repaints the border.
+ *
+ * @param g The graphics context.
+ */
+ public void paint(Graphics g) {
+
+ // get current dimensions
+ Dimension size = getSize();
+ int width = size.width;
+ int height = size.height;
+
+ // set colors
+ Color light = getBackground().brighter().brighter().brighter();
+ Color dark = getBackground().darker().darker().darker();
+
+ // Draw border
+ switch (style) {
+ case RAISED: // 3D Border (in or out)
+ case LOWERED:
+ Color topleft = null;
+ Color bottomright = null;
+
+ // set colors
+ if (style == RAISED) {
+ topleft = light;
+ bottomright = dark;
+ }
+ else {
+ topleft = dark;
+ bottomright = light;
+ }
+
+ // draw border
+ g.setColor(topleft);
+ for (int i = 0; i < thickness; i++) {
+ g.drawLine(i, i, width - i - 2, i);
+ g.drawLine(i, i + 1, i, height - i - 1);
+ }
+ g.setColor(bottomright);
+ for (int i = 0; i < thickness; i++) {
+ g.drawLine(i + 1, height - i - 1, width - i - 1, height - i - 1);
+ g.drawLine(width - i - 1, i, width - i - 1, height - i - 2);
+ }
+ break;
+
+ case IN: // Etched Border (in or out)
+ case OUT:
+ int adjust1 = 0;
+ int adjust2 = 0;
+
+ // set font and get info
+ Font oldfont = g.getFont();
+ g.setFont(font);
+ FontMetrics fm = g.getFontMetrics();
+ int ascent = fm.getAscent();
+
+ // set adjustment
+ if (style == IN)
+ adjust1 = 1;
+ else
+ adjust2 = 1;
+
+ // Calculate adjustment for text
+ int adjustment = 0;
+ if (text != null && text.length() > 0) {
+ if (ascent > thickness)
+ adjustment = (ascent - thickness) / 2;
+ }
+
+ // The adjustment is there so that we always draw the
+ // light rectangle first. Otherwise, your eye picks up
+ // the discrepancy where the light rect. passes over
+ // the darker rect.
+ int x = thickness / 2;
+ int y = thickness / 2 + adjustment;
+ int w = width - thickness - 1;
+ int h = height - thickness - 1 - adjustment;
+
+ // draw rectangles
+ g.setColor(light);
+ g.drawRect(x + adjust1, y + adjust1, w, h);
+ g.setColor(dark);
+ g.drawRect(x + adjust2, y + adjust2, w, h);
+
+ // draw text, if applicable
+ if (text != null && text.length() > 0) {
+ // calculate drawing area
+ int fontheight = fm.getHeight();
+ int strwidth = fm.stringWidth(text);
+
+ int textwidth = width - 2 * (thickness + 5);
+ if (strwidth > textwidth)
+ strwidth = textwidth;
+
+ // calculate offset for alignment
+ int offset;
+ switch (alignment) {
+ case CENTER:
+ offset = (width - strwidth) / 2;
+ break;
+ case RIGHT:
+ offset = width - strwidth - thickness - 5;
+ break;
+ case LEFT:
+ default: // assume left alignment if invalid
+ offset = thickness + 5;
+ break;
+ }
+
+ // clear drawing area and set clipping region
+ g.clearRect(offset - 5, 0, strwidth + 10, fontheight);
+ g.clipRect(offset, 0, strwidth, fontheight);
+
+ // draw text
+ g.setColor(color);
+ g.drawString(text, offset, ascent);
+
+ // restore old clipping area
+ g.clipRect(0, 0, width, height);
+ }
+
+ g.setFont(oldfont);
+ break;
+
+ case SOLID:
+ default: // assume SOLID
+ g.setColor(color);
+ for (int i = 0; i < thickness; i++)
+ g.drawRect(i, i, width - 2 * i - 1, height - 2 * i - 1);
+ }
+
+ }
+
+ /**
+ * Returns the settings of this HolidayBorderPanel instance as a string.
+ */
+ public String toString() {
+ StringBuffer str = new StringBuffer("HolidayBorderPanel[");
+
+ // style
+ str.append("style=");
+ switch (style) {
+ case SOLID: str.append("SOLID"); break;
+ case RAISED: str.append("RAISED"); break;
+ case LOWERED: str.append("LOWERED"); break;
+ case IN: str.append("IN"); break;
+ case OUT: str.append("OUT"); break;
+ default: str.append("unknown");
+ }
+ str.append(",");
+
+ // thickness
+ str.append("thickness=");
+ str.append(thickness);
+ str.append(",");
+
+ // gap
+ str.append("gap=");
+ str.append(gap);
+ str.append(",");
+
+ // color
+ str.append(color);
+ str.append(",");
+
+ // font
+ str.append(font);
+ str.append(",");
+
+ // text
+ str.append("text=");
+ str.append(text);
+ str.append(",");
+
+ // alignment
+ str.append("alignment=");
+ switch (alignment) {
+ case LEFT: str.append("LEFT"); break;
+ case CENTER: str.append("CENTER"); break;
+ case RIGHT: str.append("RIGHT"); break;
+ default: str.append("unknown");
+ }
+
+ str.append("]");
+
+ return str.toString();
+ }
+
+ }
+
diff --git a/demos/src/com/ibm/icu/dev/demo/holiday/HolidayCalendarDemo.java b/demos/src/com/ibm/icu/dev/demo/holiday/HolidayCalendarDemo.java
new file mode 100644
index 0000000..e6ffae5
--- /dev/null
+++ b/demos/src/com/ibm/icu/dev/demo/holiday/HolidayCalendarDemo.java
@@ -0,0 +1,730 @@
+/*
+ *******************************************************************************
+ * Copyright (C) 1996-2013, International Business Machines Corporation and *
+ * others. All Rights Reserved. *
+ *******************************************************************************
+ */
+
+package com.ibm.icu.dev.demo.holiday;
+
+import java.awt.BorderLayout;
+import java.awt.Button;
+import java.awt.Canvas;
+import java.awt.Choice;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Frame;
+import java.awt.Graphics;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Label;
+import java.awt.Panel;
+import java.awt.Point;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.awt.event.WindowEvent;
+import java.text.DateFormatSymbols;
+import java.util.Date;
+import java.util.Locale;
+import java.util.Vector;
+
+import com.ibm.icu.dev.demo.impl.DemoApplet;
+import com.ibm.icu.dev.demo.impl.DemoTextBox;
+import com.ibm.icu.dev.demo.impl.DemoUtility;
+import com.ibm.icu.text.SimpleDateFormat;
+import com.ibm.icu.util.Calendar;
+import com.ibm.icu.util.Holiday;
+
+/**
+ * CalendarDemo demonstrates how Calendar works.
+ */
+public class HolidayCalendarDemo extends DemoApplet
+{
+ /**
+ * For serialization
+ */
+ private static final long serialVersionUID = 4546085430817359372L;
+
+ /**
+ * The main function which defines the behavior of the CalendarDemo
+ * applet when an applet is started.
+ */
+ public static void main(String argv[]) {
+
+ new HolidayCalendarDemo().showDemo();
+ }
+
+ /* This creates a CalendarFrame for the demo applet. */
+ public Frame createDemoFrame(DemoApplet applet) {
+ return new CalendarFrame(applet);
+ }
+
+ /**
+ * A Frame is a top-level window with a title. The default layout for a frame
+ * is BorderLayout. The CalendarFrame class defines the window layout of
+ * CalendarDemo.
+ */
+ private static class CalendarFrame extends Frame implements ActionListener,
+ ItemListener
+ {
+ /**
+ * For serialization
+ */
+ private static final long serialVersionUID = -7023296782393042761L;
+
+ private static final boolean DEBUG = false;
+
+ //private Locale curLocale = Locale.US; // unused
+
+ private DemoApplet applet;
+
+ private static final Locale[] calendars = {
+ //new Locale("de","AT"),
+ Locale.CANADA,
+ Locale.CANADA_FRENCH,
+ Locale.FRANCE,
+ Locale.GERMANY,
+ new Locale("iw","IL"),
+ new Locale("el","GR"),
+ //new Locale("es","MX"),
+ Locale.UK,
+ Locale.US,
+ };
+ private static final Locale[] displays = {
+ Locale.CANADA,
+ Locale.UK,
+ Locale.US,
+ Locale.FRANCE,
+ Locale.CANADA_FRENCH,
+ //new Locale("de","AT"),
+ Locale.GERMAN,
+ new Locale("el","GR"),
+ //new Locale("iw","IL"),
+ new Locale("es","MX"),
+ };
+
+ /**
+ * Constructs a new CalendarFrame that is initially invisible.
+ */
+ public CalendarFrame(DemoApplet applet)
+ {
+ super("Calendar Demo");
+ this.applet = applet;
+ init();
+ start();
+ enableEvents(WindowEvent.WINDOW_CLOSING);
+ }
+
+ /**
+ * Initializes the applet. You never need to call this directly, it
+ * is called automatically by the system once the applet is created.
+ */
+ public void init()
+ {
+ // Get G7 locales only for demo purpose. To get all the locales
+ // supported, switch to calling Calendar.getAvailableLocales().
+ // commented
+ locales = displays;
+
+ buildGUI();
+ }
+
+ //------------------------------------------------------------
+ // package private
+ //------------------------------------------------------------
+ void addWithFont(Container container, Component foo, Font font) {
+ if (font != null)
+ foo.setFont(font);
+ container.add(foo);
+ }
+
+ /**
+ * Called to start the applet. You never need to call this method
+ * directly, it is called when the applet's document is visited.
+ */
+ public void start()
+ {
+ // do nothing
+ }
+
+ private Choice localeMenu;
+ private Choice displayMenu;
+ private Locale[] locales;
+
+ private Label monthLabel;
+ private Button prevYear;
+ private Button prevMonth;
+ private Button gotoToday;
+ private Button nextMonth;
+ private Button nextYear;
+ private CalendarPanel calendarPanel;
+
+ private static final Locale kFirstLocale = Locale.US;
+
+ private static void add(Container container, Component component,
+ GridBagLayout g, GridBagConstraints c)
+ {
+ g.setConstraints(component, c);
+ container.add(component);
+ }
+
+ public void buildGUI()
+ {
+ setBackground(DemoUtility.bgColor);
+ setLayout(new BorderLayout(10,10));
+
+ // Label for the demo's title
+ Label titleLabel = new Label("Calendar Demo", Label.CENTER);
+ titleLabel.setFont(DemoUtility.titleFont);
+
+ // Label for the current month name
+ monthLabel = new Label("", Label.LEFT);
+ monthLabel.setFont(new Font(DemoUtility.titleFont.getName(),
+ DemoUtility.titleFont.getStyle(),
+ (DemoUtility.titleFont.getSize() * 3)/2));
+
+ // Make the locale popup menus
+ localeMenu= new Choice();
+ localeMenu.addItemListener(this);
+ int selectMe = 0;
+
+ for (int i = 0; i < calendars.length; i++) {
+ if (i > 0 &&
+ calendars[i].getCountry().equals(calendars[i-1].getCountry()) ||
+ i < calendars.length - 1 &&
+ calendars[i].getCountry().equals(calendars[i+1].getCountry()))
+ {
+ localeMenu.addItem(calendars[i].getDisplayCountry() + " (" +
+ calendars[i].getDisplayLanguage() + ")");
+ } else {
+ localeMenu.addItem( calendars[i].getDisplayCountry() );
+ }
+
+ if (calendars[i].equals(kFirstLocale)) {
+ selectMe = i;
+ }
+ }
+
+ localeMenu.setBackground(DemoUtility.choiceColor);
+ localeMenu.select(selectMe);
+
+ displayMenu = new Choice();
+ displayMenu.addItemListener(this);
+
+ selectMe = 0;
+ for (int i = 0; i < locales.length; i++) {
+ if (i > 0 &&
+ locales[i].getLanguage().equals(locales[i-1].getLanguage()) ||
+ i < locales.length - 1 &&
+ locales[i].getLanguage().equals(locales[i+1].getLanguage()))
+ {
+ displayMenu.addItem( locales[i].getDisplayName() );
+ } else {
+ displayMenu.addItem( locales[i].getDisplayLanguage());
+ }
+
+ if (locales[i].equals(kFirstLocale)) {
+ selectMe = i;
+ }
+ }
+
+ displayMenu.setBackground(DemoUtility.choiceColor);
+ displayMenu.select(selectMe);
+
+ // Make all the next/previous/today buttons
+ prevYear = new Button("<<");
+ prevYear.addActionListener(this);
+ prevMonth = new Button("<");
+ prevMonth.addActionListener(this);
+ gotoToday = new Button("Today");
+ gotoToday.addActionListener(this);
+ nextMonth = new Button(">");
+ nextMonth.addActionListener(this);
+ nextYear = new Button(">>");
+ nextYear.addActionListener(this);
+
+ // The month name and the control buttons are bunched together
+ Panel monthPanel = new Panel();
+ {
+ GridBagLayout g = new GridBagLayout();
+ GridBagConstraints c = new GridBagConstraints();
+ monthPanel.setLayout(g);
+
+ c.weightx = 1;
+ c.weighty = 1;
+
+ c.gridwidth = 1;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.gridwidth = GridBagConstraints.REMAINDER;
+ add(monthPanel, monthLabel, g, c);
+
+ c.gridwidth = 1;
+ add(monthPanel, prevYear, g, c);
+ add(monthPanel, prevMonth, g, c);
+ add(monthPanel, gotoToday, g, c);
+ add(monthPanel, nextMonth, g, c);
+ c.gridwidth = GridBagConstraints.REMAINDER;
+ add(monthPanel, nextYear, g, c);
+ }
+
+ // Stick the menu and buttons in a little "control panel"
+ Panel menuPanel = new Panel();
+ {
+ GridBagLayout g = new GridBagLayout();
+ GridBagConstraints c = new GridBagConstraints();
+ menuPanel.setLayout(g);
+
+ c.weightx = 1;
+ c.weighty = 1;
+
+ c.fill = GridBagConstraints.HORIZONTAL;
+
+ c.gridwidth = GridBagConstraints.RELATIVE;
+ Label l1 = new Label("Holidays");
+ l1.setFont(DemoUtility.labelFont);
+ add(menuPanel, l1, g, c);
+
+ c.gridwidth = GridBagConstraints.REMAINDER;
+ add(menuPanel, localeMenu, g, c);
+
+ c.gridwidth = GridBagConstraints.RELATIVE;
+ Label l2 = new Label("Display:");
+ l2.setFont(DemoUtility.labelFont);
+ add(menuPanel, l2, g, c);
+
+ c.gridwidth = GridBagConstraints.REMAINDER;
+ add(menuPanel, displayMenu, g, c);
+ }
+
+ // The title, buttons, etc. go in a panel at the top of the window
+ Panel topPanel = new Panel();
+ {
+ topPanel.setLayout(new BorderLayout());
+
+ //topPanel.add("North", titleLabel);
+ topPanel.add("Center", monthPanel);
+ topPanel.add("East", menuPanel);
+ }
+ add("North", topPanel);
+
+ // The copyright notice goes at the bottom of the window
+ Label copyright = new Label(DemoUtility.copyright1, Label.LEFT);
+ copyright.setFont(DemoUtility.creditFont);
+ add("South", copyright);
+
+ // Now create the big calendar panel and stick it in the middle
+ calendarPanel = new CalendarPanel( kFirstLocale );
+ add("Center", calendarPanel);
+
+ updateMonthName();
+ }
+
+ private void updateMonthName()
+ {
+ SimpleDateFormat f = new SimpleDateFormat("MMMM yyyyy",
+ calendarPanel.getDisplayLocale());
+ f.setCalendar(calendarPanel.getCalendar());
+ monthLabel.setText( f.format( calendarPanel.firstOfMonth() ));
+ }
+
+ /**
+ * Handles the event. Returns true if the event is handled and should not
+ * be passed to the parent of this component. The default event handler
+ * calls some helper methods to make life easier on the programmer.
+ */
+ public void actionPerformed(ActionEvent e)
+ {
+ Object obj = e.getSource();
+
+ // *** Button events are handled here.
+ if (obj instanceof Button) {
+ if (obj == nextMonth) {
+ calendarPanel.add(Calendar.MONTH, +1);
+ }
+ else
+ if (obj == prevMonth) {
+ calendarPanel.add(Calendar.MONTH, -1);
+ }
+ else
+ if (obj == prevYear) {
+ calendarPanel.add(Calendar.YEAR, -1);
+ }
+ else
+ if (obj == nextYear) {
+ calendarPanel.add(Calendar.YEAR, +1);
+ }
+ else
+ if (obj == gotoToday) {
+ calendarPanel.set( new Date() );
+ }
+ updateMonthName();
+ }
+ }
+
+ public void itemStateChanged(ItemEvent e)
+ {
+ Object obj = e.getSource();
+ if (obj == localeMenu) {
+ calendarPanel.setCalendarLocale(calendars[localeMenu.getSelectedIndex()]);
+ updateMonthName();
+ }
+ else
+ if (obj == displayMenu) {
+ calendarPanel.setDisplayLocale(locales[displayMenu.getSelectedIndex()]);
+ updateMonthName();
+ }
+ }
+
+ /**
+ * Print out the error message while debugging this program.
+ */
+ public void errorText(String s)
+ {
+ if (DEBUG)
+ {
+ System.out.println(s);
+ }
+ }
+
+ protected void processWindowEvent(WindowEvent e)
+ {
+ System.out.println("event " + e);
+ if (e.getID() == WindowEvent.WINDOW_CLOSING) {
+ this.hide();
+ this.dispose();
+
+ if (applet != null) {
+ applet.demoClosed();
+ } else {
+ System.exit(0);
+ }
+ }
+ }
+ }
+
+
+ private static class CalendarPanel extends Canvas {
+
+ /**
+ * For serialization
+ */
+ private static final long serialVersionUID = 1521099412250120821L;
+
+ public CalendarPanel( Locale locale ) {
+ set(locale, locale, new Date());
+ }
+
+ public void setCalendarLocale(Locale locale) {
+ set(locale, fDisplayLocale, fCalendar.getTime());
+ }
+
+ public void setDisplayLocale(Locale locale) {
+ set(fCalendarLocale, locale, fCalendar.getTime());
+ }
+
+ public void set(Date date) {
+ set(fCalendarLocale, fDisplayLocale, date);
+ }
+
+ public void set(Locale loc, Locale display, Date date)
+ {
+ if (fCalendarLocale == null || !loc.equals(fCalendarLocale)) {
+ fCalendarLocale = loc;
+ fCalendar = Calendar.getInstance(fCalendarLocale);
+ fAllHolidays = Holiday.getHolidays(fCalendarLocale);
+ }
+ if (fDisplayLocale == null || !display.equals(fDisplayLocale)) {
+ fDisplayLocale = display;
+ fSymbols = new DateFormatSymbols(fDisplayLocale);
+ }
+
+ fStartOfMonth = date;
+
+ dirty = true;
+ repaint();
+ }
+
+ public void add(int field, int delta)
+ {
+ synchronized(fCalendar) {
+ fCalendar.setTime(fStartOfMonth);
+ fCalendar.add(field, delta);
+ fStartOfMonth = fCalendar.getTime();
+ }
+ dirty = true;
+ repaint();
+ }
+
+ public com.ibm.icu.util.Calendar getCalendar() {
+ return fCalendar;
+ }
+
+ public Locale getCalendarLocale() {
+ return fCalendarLocale;
+ }
+
+ public Locale getDisplayLocale() {
+ return fDisplayLocale;
+ }
+
+
+ public Date firstOfMonth() {
+ return fStartOfMonth;
+ }
+
+ private Date startOfMonth(Date dateInMonth)
+ {
+ synchronized(fCalendar) {
+ fCalendar.setTime(dateInMonth); // TODO: synchronization
+
+ int era = fCalendar.get(Calendar.ERA);
+ int year = fCalendar.get(Calendar.YEAR);
+ int month = fCalendar.get(Calendar.MONTH);
+
+ fCalendar.clear();
+ fCalendar.set(Calendar.ERA, era);
+ fCalendar.set(Calendar.YEAR, year);
+ fCalendar.set(Calendar.MONTH, month);
+ fCalendar.set(Calendar.DATE, 1);
+
+ return fCalendar.getTime();
+ }
+ }
+
+ private void calculate()
+ {
+ Calendar c = (Calendar)fCalendar.clone(); // Temporary copy
+
+ fStartOfMonth = startOfMonth(fStartOfMonth);
+
+ // Stash away a few useful constants for this calendar and display
+ minDay = c.getMinimum(Calendar.DAY_OF_WEEK);
+ daysInWeek = c.getMaximum(Calendar.DAY_OF_WEEK) - minDay + 1;
+
+ firstDayOfWeek = Calendar.getInstance(fDisplayLocale).getFirstDayOfWeek();
+
+ // Stash away a Date for the start of this month
+
+ // Find the day of week of the first day in this month
+ c.setTime(fStartOfMonth);
+ firstDayInMonth = c.get(Calendar.DAY_OF_WEEK);
+
+ // Now find the # of days in the month
+ c.roll(Calendar.DATE, false);
+ daysInMonth = c.get(Calendar.DATE);
+
+ // Finally, find the end of the month, i.e. the start of the next one
+ c.roll(Calendar.DATE, true);
+ c.add(Calendar.MONTH, 1);
+ c.getTime(); // JDK 1.1.2 bug workaround
+ c.add(Calendar.SECOND, -1);
+ Date endOfMonth = c.getTime();
+
+ //
+ // Calculate the number of full or partial weeks in this month.
+ // To do this I can just reuse the code that calculates which
+ // calendar cell contains a given date.
+ //
+ numWeeks = dateToCell(daysInMonth).y - dateToCell(1).y + 1;
+
+ // Remember which holidays fall on which days in this month,
+ // to save the trouble of having to do it later
+ fHolidays.setSize(0);
+
+ for (int h = 0; h < fAllHolidays.length; h++)
+ {
+ Date d = fStartOfMonth;
+ while ( (d = fAllHolidays[h].firstBetween(d, endOfMonth) ) != null)
+ {
+ c.setTime(d);
+ fHolidays.addElement( new HolidayInfo(c.get(Calendar.DATE),
+ fAllHolidays[h],
+ fAllHolidays[h].getDisplayName(fDisplayLocale) ));
+
+ d.setTime( d.getTime() + 1000 ); // "d++"
+ }
+ }
+ dirty = false;
+ }
+
+ static final int INSET = 2;
+
+ /*
+ * Convert from the day number within a month (1-based)
+ * to the cell coordinates on the calendar (0-based)
+ */
+ private void dateToCell(int date, Point pos)
+ {
+ int cell = (date + firstDayInMonth - firstDayOfWeek - minDay);
+ if (firstDayInMonth < firstDayOfWeek) {
+ cell += daysInWeek;
+ }
+
+ pos.x = cell % daysInWeek;
+ pos.y = cell / daysInWeek;
+ }
+ private Point dateToCell(int date) {
+ Point p = new Point(0,0);
+ dateToCell(date, p);
+ return p;
+ }
+
+ public void paint(Graphics g) {
+
+ if (dirty) {
+ calculate();
+ }
+
+ Point cellPos = new Point(0,0); // Temporary variable
+ Dimension d = getSize();
+
+ g.setColor(DemoUtility.bgColor);
+ g.fillRect(0,0,d.width,d.height);
+
+ // Draw the day names at the top
+ g.setColor(Color.black);
+ g.setFont(DemoUtility.labelFont);
+ FontMetrics fm = g.getFontMetrics();
+ int labelHeight = fm.getHeight() + INSET * 2;
+
+ int v = fm.getAscent() + INSET;
+ for (int i = 0; i < daysInWeek; i++) {
+ int dayNum = (i + minDay + firstDayOfWeek - 2) % daysInWeek + 1;
+ String dayName = fSymbols.getWeekdays()[dayNum];
+
+ int h = (int) (d.width * (i + 0.5)) / daysInWeek;
+ h -= fm.stringWidth(dayName) / 2;
+
+ g.drawString(dayName, h, v);
+ }
+
+ double cellHeight = (d.height - labelHeight - 1) / numWeeks;
+ double cellWidth = (double)(d.width - 1) / daysInWeek;
+
+ // Draw a white background in the part of the calendar
+ // that displays this month.
+ // First figure out how much of the first week should be shaded.
+ {
+ g.setColor(Color.white);
+ dateToCell(1, cellPos);
+ int width = (int)(cellPos.x*cellWidth); // Width of unshaded area
+
+ g.fillRect((int)(width), labelHeight ,
+ (int)(d.width - width), (int)cellHeight);
+
+ // All of the intermediate weeks get shaded completely
+ g.fillRect(0, (int)(labelHeight + cellHeight),
+ d.width, (int)(cellHeight * (numWeeks - 2)));
+
+ // Now figure out the last week.
+ dateToCell(daysInMonth, cellPos);
+ width = (int)((cellPos.x+1)*cellWidth); // Width of shaded area
+
+ g.fillRect(0, (int)(labelHeight + (numWeeks-1) * cellHeight),
+ width, (int)(cellHeight));
+
+ }
+ // Draw the X/Y grid lines
+ g.setColor(Color.black);
+ for (int i = 0; i <= numWeeks; i++) {
+ int y = (int)(labelHeight + i * cellHeight);
+ g.drawLine(0, y, d.width - 1, y);
+ }
+ for (int i = 0; i <= daysInWeek; i++) {
+ int x = (int)(i * cellWidth);
+ g.drawLine(x, labelHeight, x, d.height - 1);
+ }
+
+ // Now loop through all of the days in the month, figure out where
+ // they go in the grid, and draw the day # for each one
+ Font numberFont = new Font("Helvetica",Font.PLAIN,12);
+ // not used Font holidayFont = DemoUtility.creditFont;
+
+ Calendar c = (Calendar)fCalendar.clone();
+ c.setTime(fStartOfMonth);
+
+ for (int i = 1, h = 0; i <= daysInMonth; i++) {
+ g.setFont(numberFont);
+ g.setColor(Color.black);
+ fm = g.getFontMetrics();
+
+ dateToCell(i, cellPos);
+ int x = (int)((cellPos.x + 1) * cellWidth);
+ int y = (int)(cellPos.y * cellHeight + labelHeight);
+
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(i);
+ String dayNum = buffer.toString();
+
+ x = x - INSET - fm.stringWidth(dayNum);
+ y = y + fm.getAscent() + INSET;
+
+ g.drawString(dayNum, x, y);
+
+ // See if any of the holidays land on this day....
+ HolidayInfo info = null;
+
+ // Coordinates of lower-left corner of cell.
+ x = (int)((cellPos.x) * cellWidth);
+ y = (int)((cellPos.y+1) * cellHeight) + labelHeight;
+
+ while (h < fHolidays.size() &&
+ (info = (HolidayInfo)fHolidays.elementAt(h)).date <= i)
+ {
+ if (info.date == i) {
+ // Draw the holiday here.
+ g.setFont(numberFont);
+ g.setColor(Color.red);
+
+ DemoTextBox box = new DemoTextBox(g, info.name, (int)(cellWidth - INSET));
+ box.draw(g, x + INSET, y - INSET - box.getHeight());
+
+ y -= (box.getHeight() + INSET);
+ }
+ h++;
+ }
+ }
+ }
+
+ // Important state variables
+ private Locale fCalendarLocale; // Whose calendar
+ private Calendar fCalendar; // Calendar for calculations
+
+ private Locale fDisplayLocale; // How to display it
+ private DateFormatSymbols fSymbols; // Symbols for drawing
+
+ private Date fStartOfMonth; // 00:00:00 on first day of month
+
+ // Cached calculations to make drawing faster.
+ private transient int minDay; // Minimum legal day #
+ private transient int daysInWeek; // # of days in a week
+ private transient int firstDayOfWeek; // First day to display in week
+ private transient int numWeeks; // # full or partial weeks in month
+ private transient int daysInMonth; // # days in this month
+ private transient int firstDayInMonth; // Day of week of first day in month
+
+ private transient Holiday[] fAllHolidays;
+ private transient Vector fHolidays = new Vector(5,5);
+
+ private transient boolean dirty = true;
+ }
+
+ private static class HolidayInfo {
+ public HolidayInfo(int date, Holiday holiday, String name) {
+ this.date = date;
+ this.holiday = holiday;
+ this.name = name;
+ }
+
+ public Holiday holiday;
+ public int date;
+ public String name;
+ }
+}
+
diff --git a/demos/src/com/ibm/icu/dev/demo/holiday/package.html b/demos/src/com/ibm/icu/dev/demo/holiday/package.html
new file mode 100644
index 0000000..d05e2f5
--- /dev/null
+++ b/demos/src/com/ibm/icu/dev/demo/holiday/package.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!-- Copyright (C) 2000-2004, International Business Machines Corporation and
+ others. All Rights Reserved.
+
+-->
+</head>
+<body bgcolor="white">
+Holiday demo application.
+</body>
+</html>
\ No newline at end of file
diff --git a/demos/src/com/ibm/icu/dev/demo/impl/AppletFrame.java b/demos/src/com/ibm/icu/dev/demo/impl/AppletFrame.java
new file mode 100644
index 0000000..d408936
--- /dev/null
+++ b/demos/src/com/ibm/icu/dev/demo/impl/AppletFrame.java
@@ -0,0 +1,149 @@
+/*
+ *******************************************************************************
+ * Copyright (C) 1996-2010, International Business Machines Corporation and *
+ * others. All Rights Reserved. *
+ *******************************************************************************
+ */
+package com.ibm.icu.dev.demo.impl;
+import java.applet.Applet;
+import java.applet.AppletContext;
+import java.applet.AppletStub;
+import java.applet.AudioClip;
+import java.awt.Frame;
+import java.awt.Image;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.Iterator;
+
+/**
+ * <p>A Frame that runs an Applet within itself, making it possible
+ * for an applet to run as an application. Usage:
+ *
+ * <pre>
+ * public class MyApplet extends Applet {
+ * public static void main(String args[]) {
+ * MyApplet applet = new MyApplet();
+ * new AppletFrame("My Applet Running As An App", applet, 640, 480);
+ * }
+ * ...
+ * }
+ * <pre>
+ *
+ * @author Alan Liu
+ */
+public class AppletFrame extends Frame implements AppletStub, AppletContext {
+
+ /**
+ * For serialization
+ */
+ private static final long serialVersionUID = 818828281190757725L;
+ Applet applet;
+
+ /**
+ * Construct a Frame running the given Applet with the default size
+ * of 640 by 480.
+ * When the Frame is closed, the applet's stop() method is called,
+ * the Frame is dispose()d of, and System.exit(0) is called.
+ *
+ * @param name the Frame title
+ * @param applet the applet to be run
+ */
+ public AppletFrame(String name, Applet applet) {
+ this(name, applet, 640, 480);
+ }
+
+ /**
+ * Construct a Frame running the given Applet with the given size.
+ * When the Frame is closed, the applet's stop() method is called,
+ * the Frame is dispose()d of, and System.exit(0) is called.
+ *
+ * @param name the Frame title
+ * @param applet the applet to be run
+ * @param width width of the Frame
+ * @param height height of the Frame
+ */
+ public AppletFrame(String name, Applet applet, int width, int height) {
+ super(name);
+ this.applet = applet;
+ applet.setStub(this);
+
+ setSize(width, height);
+ add("Center", applet);
+ show();
+ addWindowListener(new WindowAdapter() {
+ public void windowClosing(WindowEvent e) {
+ AppletFrame.this.applet.stop();
+ dispose();
+ System.exit(0);
+ }
+ });
+
+ applet.init();
+ applet.start();
+ }
+
+ // AppletStub API
+ public void appletResize(int width, int height) {
+ setSize(width, height);
+ }
+
+ public AppletContext getAppletContext() {
+ return this;
+ }
+
+ public URL getCodeBase() {
+ return null;
+ }
+
+ public URL getDocumentBase() {
+ return null;
+ }
+
+ public String getParameter(String name) {
+ return "PARAMETER";
+ }
+
+ public boolean isActive() {
+ return true;
+ }
+
+
+ // AppletContext API
+ public Applet getApplet(String name) {
+ return applet;
+ }
+
+ public Enumeration getApplets() {
+ return null;
+ }
+
+ public AudioClip getAudioClip(URL url) {
+ return null;
+ }
+
+ public Image getImage(URL url) {
+ return null;
+ }
+
+ public void showDocument(URL url) {}
+ public void showDocument(URL url, String target) {}
+
+ public void showStatus(String status) {
+ System.out.println(status);
+ }
+
+ public void setStream(String key, InputStream stream) throws IOException {
+ }
+
+ public InputStream getStream(String key) {
+ return null;
+ }
+
+ public Iterator getStreamKeys() {
+ return null;
+ }
+}
diff --git a/demos/src/com/ibm/icu/dev/demo/impl/DemoApplet.java b/demos/src/com/ibm/icu/dev/demo/impl/DemoApplet.java
new file mode 100644
index 0000000..339e6a7
--- /dev/null
+++ b/demos/src/com/ibm/icu/dev/demo/impl/DemoApplet.java
@@ -0,0 +1,80 @@
+/*
+ *******************************************************************************
+ * Copyright (C) 1997-2010, International Business Machines Corporation and *
+ * others. All Rights Reserved. *
+ *******************************************************************************
+ */
+
+package com.ibm.icu.dev.demo.impl;
+
+import java.awt.Button;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+public abstract class DemoApplet extends java.applet.Applet {
+ private static final long serialVersionUID = -8983602961925702071L;
+ private Button demoButton;
+ private Frame demoFrame;
+ private static int demoFrameCount = 0;
+
+ protected abstract Frame createDemoFrame(DemoApplet applet);
+ protected Dimension getDefaultFrameSize(DemoApplet applet, Frame f) {
+ return new Dimension(700, 550);
+ }
+
+ //Create a button that will display the demo
+ public void init()
+ {
+ setBackground(Color.white);
+ demoButton = new Button("Demo");
+ demoButton.setBackground(Color.yellow);
+ add( demoButton );
+
+ demoButton.addActionListener( new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ if (e.getID() == ActionEvent.ACTION_PERFORMED) {
+ demoButton.setLabel("loading");
+
+ if (demoFrame == null) {
+ demoFrame = createDemoFrame(DemoApplet.this);
+ showDemo();
+ }
+
+ demoButton.setLabel("Demo");
+ }
+ }
+ } );
+ }
+
+ public void showDemo()
+ {
+ demoFrame = createDemoFrame(this);
+ demoFrame.doLayout();
+ Dimension d = getDefaultFrameSize(this, demoFrame);
+ demoFrame.setSize(d.width, d.height);
+ demoFrame.show();
+ demoFrameOpened();
+ }
+
+ public void demoClosed()
+ {
+ demoFrame = null;
+ demoFrameClosed();
+ }
+
+ public static void demoFrameOpened() {
+ demoFrameCount++;
+ System.err.println("DemoFrameOpened, now at:"+demoFrameCount);
+ }
+ public static void demoFrameClosed() {
+ if (--demoFrameCount == 0) {
+ System.err.println("DemoFrameClosed, now at:"+demoFrameCount + " - quitting");
+ System.exit(0);
+ }
+ System.err.println("DemoFrameClosed, now at:"+demoFrameCount);
+ }
+}
+
diff --git a/demos/src/com/ibm/icu/dev/demo/impl/DemoTextBox.java b/demos/src/com/ibm/icu/dev/demo/impl/DemoTextBox.java
new file mode 100644
index 0000000..a3d8349
--- /dev/null
+++ b/demos/src/com/ibm/icu/dev/demo/impl/DemoTextBox.java
@@ -0,0 +1,96 @@
+/*
+ *******************************************************************************
+ * Copyright (C) 1997-2010, International Business Machines Corporation and *
+ * others. All Rights Reserved. *
+ *******************************************************************************
+ */
+package com.ibm.icu.dev.demo.impl;
+
+
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.text.BreakIterator;
+
+public class DemoTextBox {
+
+ public DemoTextBox(Graphics g, String text, int width)
+ {
+ this.text = text;
+ this.chars = new char[text.length()];
+ text.getChars(0, text.length(), chars, 0);
+
+ this.width = width;
+// this.port = g;
+ this.metrics = g.getFontMetrics();
+
+ breakText();
+ }
+
+ public int getHeight() {
+ return (nbreaks + 1) * metrics.getHeight();
+ }
+
+ public void draw(Graphics g, int x, int y)
+ {
+ int index = 0;
+
+ y += metrics.getAscent();
+
+ for (int i = 0; i < nbreaks; i++)
+ {
+ g.drawChars(chars, index, breakPos[i] - index, x, y);
+ index = breakPos[i];
+ y += metrics.getHeight();
+ }
+
+ g.drawChars(chars, index, chars.length - index, x, y);
+ }
+
+
+ private void breakText()
+ {
+ if (metrics.charsWidth(chars, 0, chars.length) > width)
+ {
+ BreakIterator iter = BreakIterator.getWordInstance();
+ iter.setText(text);
+
+ int start = iter.first();
+ int end = start;
+ int pos;
+
+ while ( (pos = iter.next()) != BreakIterator.DONE )
+ {
+ int w = metrics.charsWidth(chars, start, pos - start);
+ if (w > width)
+ {
+ // We've gone past the maximum width, so break the line
+ if (end > start) {
+ // There was at least one break position before this point
+ breakPos[nbreaks++] = end;
+ start = end;
+ end = pos;
+ } else {
+ // There weren't any break positions before this one, so
+ // let this word overflow the margin (yuck)
+ breakPos[nbreaks++] = pos;
+ start = end = pos;
+ }
+ } else {
+ // the current position still fits on the line; it's the best
+ // tentative break position we have so far.
+ end = pos;
+ }
+
+ }
+ }
+ }
+
+ private String text;
+ private char[] chars;
+// private Graphics port;
+ private FontMetrics metrics;
+ private int width;
+
+ private int[] breakPos = new int[10]; // TODO: get real
+ private int nbreaks = 0;
+}
\ No newline at end of file
diff --git a/demos/src/com/ibm/icu/dev/demo/impl/DemoUtility.java b/demos/src/com/ibm/icu/dev/demo/impl/DemoUtility.java
new file mode 100644
index 0000000..c838a13
--- /dev/null
+++ b/demos/src/com/ibm/icu/dev/demo/impl/DemoUtility.java
@@ -0,0 +1,136 @@
+/*
+ *******************************************************************************
+ * Copyright (C) 1997-2010, International Business Machines Corporation and *
+ * others. All Rights Reserved. *
+ *******************************************************************************
+ */
+package com.ibm.icu.dev.demo.impl;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Font;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.Label;
+import java.awt.Panel;
+import java.awt.TextComponent;
+import java.util.Locale;
+
+public class DemoUtility
+{
+ public static final Font titleFont = new Font("TimesRoman",Font.BOLD,18);
+ public static final Font labelFont = new Font("TimesRoman",Font.BOLD,14);
+ public static final Font choiceFont = new Font("Helvetica",Font.BOLD,12);
+ public static final Font editFont = new Font("Helvetica",Font.PLAIN,14);
+ public static final Font creditFont = new Font("Helvetica",Font.PLAIN,10);
+ public static final Font numberFont = new Font("sansserif", Font.PLAIN, 14);
+
+ public static final Color bgColor = Color.lightGray;
+ public static final Color choiceColor = Color.white;
+
+ public static final String copyright1 =
+ "Copyright (C) IBM Corp and others. 1997 - 2002 All Rights Reserved";
+
+ /**
+ Provides easy way to use basic functions of GridBagLayout, without
+ the complications. After building a panel, and inserting all the
+ * subcomponents, call this to lay it out in the desired number of columns.
+ */
+ public static void fixGrid(Container cont, int columns) {
+ GridBagLayout gridbag = new GridBagLayout();
+ cont.setLayout(gridbag);
+
+ GridBagConstraints c = new GridBagConstraints();
+ c.fill = GridBagConstraints.VERTICAL;
+ c.weightx = 1.0;
+ c.insets = new Insets(2,2,2,2);
+
+ Component[] components = cont.getComponents();
+ for (int i = 0; i < components.length; ++i) {
+ // not used int colNumber = i%columns;
+ c.gridwidth = 1; // default
+ if ((i%columns) == columns - 1)
+ c.gridwidth = GridBagConstraints.REMAINDER; // last in grid
+ if (components[i] instanceof Label) {
+ switch (((Label)components[i]).getAlignment()) {
+ case Label.CENTER: c.anchor = GridBagConstraints.CENTER; break;
+ case Label.LEFT: c.anchor = GridBagConstraints.WEST; break;
+ case Label.RIGHT: c.anchor = GridBagConstraints.EAST; break;
+ }
+ }
+ gridbag.setConstraints(components[i], c);
+ }
+
+ }
+
+ /**
+ Provides easy way to change the spacing around an object in a GridBagLayout.
+ Call AFTER fixGridBag, passing in the container, the component, and the
+ new insets.
+ */
+ public static void setInsets(Container cont, Component comp, Insets insets) {
+ GridBagLayout gbl = (GridBagLayout)cont.getLayout();
+ GridBagConstraints g = gbl.getConstraints(comp);
+ g.insets = insets;
+ gbl.setConstraints(comp,g);
+ }
+
+ public static Panel createSpacer() {
+ Panel spacer = new Panel();
+ spacer.setLayout(null);
+ spacer.setSize(1000, 1);
+ return spacer;
+ }
+
+ // to avoid goofy updates and misplaced cursors
+ public static void setText(TextComponent area, String newText) {
+ String foo = area.getText();
+ if (foo.equals(newText)) return;
+ area.setText(newText);
+ }
+
+ /**
+ * Compares two locals. Return value is negative
+ * if they're different, and more positive the more
+ * fields that match.
+ */
+
+ public static int compareLocales(Locale l1, Locale l2)
+ {
+ int result = -1;
+
+ if (l1.getLanguage().equals(l2.getLanguage())) {
+ result += 1;
+
+ if (l1.getCountry().equals(l2.getCountry())) {
+ result += 1;
+
+ if (l1.getVariant().equals(l2.getVariant())) {
+ result += 1;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Get the G7 locale list for demos.
+ */
+ public static Locale[] getG7Locales() {
+ return localeList;
+ }
+ private static Locale[] localeList = {
+ new Locale("DA", "DK", ""),
+ new Locale("EN", "US", ""),
+ new Locale("EN", "GB", ""),
+ new Locale("EN", "CA", ""),
+ new Locale("FR", "FR", ""),
+ new Locale("FR", "CA", ""),
+ new Locale("DE", "DE", ""),
+ new Locale("IT", "IT", ""),
+ //new Locale("JA", "JP", ""),
+ };
+}
diff --git a/demos/src/com/ibm/icu/dev/demo/impl/DumbTextComponent.java b/demos/src/com/ibm/icu/dev/demo/impl/DumbTextComponent.java
new file mode 100644
index 0000000..e6147be
--- /dev/null
+++ b/demos/src/com/ibm/icu/dev/demo/impl/DumbTextComponent.java
@@ -0,0 +1,827 @@
+/*
+ *******************************************************************************
+ * Copyright (C) 1996-2010, International Business Machines Corporation and *
+ * others. All Rights Reserved. *
+ *******************************************************************************
+ */
+package com.ibm.icu.dev.demo.impl;
+import java.awt.AWTEventMulticaster;
+import java.awt.Canvas;
+import java.awt.Color;
+import java.awt.Cursor;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.StringSelection;
+import java.awt.datatransfer.Transferable;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+import java.awt.event.TextEvent;
+import java.awt.event.TextListener;
+import java.text.BreakIterator;
+
+// LIU: Changed from final to non-final
+public class DumbTextComponent extends Canvas
+ implements KeyListener, MouseListener, MouseMotionListener, FocusListener
+{
+
+ /**
+ * For serialization
+ */
+ private static final long serialVersionUID = 8265547730738652151L;
+
+// private transient static final String copyright =
+// "Copyright \u00A9 1998, Mark Davis. All Rights Reserved.";
+ private transient static boolean DEBUG = false;
+
+ private String contents = "";
+ private Selection selection = new Selection();
+ private int activeStart = -1;
+ private boolean editable = true;
+
+ private transient Selection tempSelection = new Selection();
+ private transient boolean focus;
+ private transient BreakIterator lineBreaker = BreakIterator.getLineInstance();
+ private transient BreakIterator wordBreaker = BreakIterator.getWordInstance();
+ private transient BreakIterator charBreaker = BreakIterator.getCharacterInstance();
+ private transient int lineAscent;
+ private transient int lineHeight;
+ private transient int lineLeading;
+ private transient int lastHeight = 10;
+ private transient int lastWidth = 50;
+ private static final int MAX_LINES = 200; // LIU: Use symbolic name
+ private transient int[] lineStarts = new int[MAX_LINES]; // LIU
+ private transient int lineCount = 1;
+
+ private transient boolean valid = false;
+ private transient FontMetrics fm;
+ private transient boolean redoLines = true;
+ private transient boolean doubleClick = false;
+ private transient TextListener textListener;
+ private transient ActionListener selectionListener;
+ private transient Image cacheImage;
+ private transient Dimension mySize;
+ private transient int xInset = 5;
+ private transient int yInset = 5;
+ private transient Point startPoint = new Point();
+ private transient Point endPoint = new Point();
+ private transient Point caretPoint = new Point();
+ private transient Point activePoint = new Point();
+
+ //private transient static String clipBoard;
+
+ private static final char CR = '\015'; // LIU
+
+ // ============================================
+
+ public DumbTextComponent() {
+ addMouseListener(this);
+ addMouseMotionListener(this);
+ addKeyListener(this);
+ addFocusListener(this);
+ setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR));
+
+ }
+
+// ================ Events ====================
+
+ // public boolean isFocusTraversable() { return true; }
+
+ public void addActionListener(ActionListener l) {
+ selectionListener = AWTEventMulticaster.add(selectionListener, l);
+ }
+
+ public void removeActionListener(ActionListener l) {
+ selectionListener = AWTEventMulticaster.remove(selectionListener, l);
+ }
+
+ public void addTextListener(TextListener l) {
+ textListener = AWTEventMulticaster.add(textListener, l);
+ }
+
+ public void removeTextListener(TextListener l) {
+ textListener = AWTEventMulticaster.remove(textListener, l);
+ }
+
+ private transient boolean pressed;
+
+ public void mousePressed(MouseEvent e) {
+ if (DEBUG) System.out.println("mousePressed");
+ if (pressed) {
+ select(e,false);
+ } else {
+ doubleClick = e.getClickCount() > 1;
+ requestFocus();
+ select(e, true);
+ pressed = true;
+ }
+ }
+
+ public void mouseDragged(MouseEvent e) {
+ if (DEBUG) System.out.println("mouseDragged");
+ select(e, false);
+ }
+
+ public void mouseReleased(MouseEvent e) {
+ if (DEBUG) System.out.println("mouseReleased");
+ pressed = false;
+ }
+
+ public void mouseEntered(MouseEvent e) {
+ //if (pressed) select(e, false);
+ }
+
+ public void mouseExited(MouseEvent e){
+ //if (pressed) select(e, false);
+ }
+
+ public void mouseClicked(MouseEvent e) {}
+ public void mouseMoved(MouseEvent e) {}
+
+
+ public void focusGained(FocusEvent e) {
+ if (DEBUG) System.out.println("focusGained");
+ focus = true;
+ valid = false;
+ repaint(16);
+ }
+ public void focusLost(FocusEvent e) {
+ if (DEBUG) System.out.println("focusLost");
+ focus = false;
+ valid = false;
+ repaint(16);
+ }
+
+ public void select(MouseEvent e, boolean first) {
+ setKeyStart(-1);
+ point2Offset(e.getPoint(), tempSelection);
+ if (first) {
+ if ((e.getModifiers() & InputEvent.SHIFT_MASK) == 0) {
+ tempSelection.anchor = tempSelection.caret;
+ }
+ }
+ // fix words
+ if (doubleClick) {
+ tempSelection.expand(wordBreaker);
+ }
+ select(tempSelection);
+ }
+
+ public void keyPressed(KeyEvent e) {
+ int code = e.getKeyCode();
+ if (DEBUG) System.out.println("keyPressed "
+ + hex((char)code) + ", " + hex((char)e.getModifiers()));
+ int start = selection.getStart();
+ int end = selection.getEnd();
+ boolean shift = (e.getModifiers() & InputEvent.SHIFT_MASK) != 0;
+ boolean ctrl = (e.getModifiers() & InputEvent.CTRL_MASK) != 0;
+
+ switch (code) {
+ case KeyEvent.VK_Q:
+ if (!ctrl || !editable) break;
+ setKeyStart(-1);
+ fixHex();
+ break;
+ case KeyEvent.VK_V:
+ if (!ctrl) break;
+ if (!editable) {
+ this.getToolkit().beep();
+ } else {
+ paste();
+ }
+ break;
+ case KeyEvent.VK_C:
+ if (!ctrl) break;
+ copy();
+ break;
+ case KeyEvent.VK_X:
+ if (!ctrl) break;
+ if (!editable) {
+ this.getToolkit().beep();
+ } else {
+ copy();
+ insertText("");
+ }
+ break;
+ case KeyEvent.VK_A:
+ if (!ctrl) break;
+ setKeyStart(-1);
+ select(Integer.MAX_VALUE, 0, false);
+ break;
+ case KeyEvent.VK_RIGHT:
+ setKeyStart(-1);
+ tempSelection.set(selection);
+ tempSelection.nextBound(ctrl ? wordBreaker : charBreaker, +1, shift);
+ select(tempSelection);
+ break;
+ case KeyEvent.VK_LEFT:
+ setKeyStart(-1);
+ tempSelection.set(selection);
+ tempSelection.nextBound(ctrl ? wordBreaker : charBreaker, -1, shift);
+ select(tempSelection);
+ break;
+ case KeyEvent.VK_UP: // LIU: Add support for up arrow
+ setKeyStart(-1);
+ tempSelection.set(selection);
+ tempSelection.caret = lineDelta(tempSelection.caret, -1);
+ if (!shift) {
+ tempSelection.anchor = tempSelection.caret;
+ }
+ select(tempSelection);
+ break;
+ case KeyEvent.VK_DOWN: // LIU: Add support for down arrow
+ setKeyStart(-1);
+ tempSelection.set(selection);
+ tempSelection.caret = lineDelta(tempSelection.caret, +1);
+ if (!shift) {
+ tempSelection.anchor = tempSelection.caret;
+ }
+ select(tempSelection);
+ break;
+ case KeyEvent.VK_DELETE: // LIU: Add delete key support
+ if (!editable) break;
+ setKeyStart(-1);
+ if (contents.length() == 0) break;
+ start = selection.getStart();
+ end = selection.getEnd();
+ if (start == end) {
+ ++end;
+ if (end > contents.length()) {
+ getToolkit().beep();
+ return;
+ }
+ }
+ replaceRange("", start, end);
+ break;
+ }
+ }
+
+ void copy() {
+ Clipboard cb = this.getToolkit().getSystemClipboard();
+ StringSelection ss = new StringSelection(
+ contents.substring(selection.getStart(), selection.getEnd()));
+ cb.setContents(ss, ss);
+ }
+
+ void paste () {
+ Clipboard cb = this.getToolkit().getSystemClipboard();
+ Transferable t = cb.getContents(this);
+ if (t == null) {
+ this.getToolkit().beep();
+ return;
+ }
+ try {
+ String temp = (String) t.getTransferData(DataFlavor.stringFlavor);
+ insertText(temp);
+ } catch (Exception e) {
+ this.getToolkit().beep();
+ }
+ }
+
+ /**
+ * LIU: Given an offset into contents, moves up or down by lines,
+ * according to lineStarts[].
+ * @param off the offset into contents
+ * @param delta how many lines to move up (< 0) or down (> 0)
+ * @return the new offset into contents
+ */
+ private int lineDelta(int off, int delta) {
+ int line = findLine(off, false);
+ int posInLine = off - lineStarts[line];
+ // System.out.println("off=" + off + " at " + line + ":" + posInLine);
+ line += delta;
+ if (line < 0) {
+ line = posInLine = 0;
+ } else if (line >= lineCount) {
+ return contents.length();
+ }
+ off = lineStarts[line] + posInLine;
+ if (off >= lineStarts[line+1]) {
+ off = lineStarts[line+1] - 1;
+ }
+ return off;
+ }
+
+ public void keyReleased(KeyEvent e) {
+ int code = e.getKeyCode();
+ if (DEBUG) System.out.println("keyReleased "
+ + hex((char)code) + ", " + hex((char)e.getModifiers()));
+ }
+
+ public void keyTyped(KeyEvent e) {
+ char ch = e.getKeyChar();
+ if (DEBUG) System.out.println("keyTyped "
+ + hex((char)ch) + ", " + hex((char)e.getModifiers()));
+ if ((e.getModifiers() & InputEvent.CTRL_MASK) != 0) return;
+ int start, end;
+ switch (ch) {
+ case KeyEvent.CHAR_UNDEFINED:
+ break;
+ case KeyEvent.VK_BACK_SPACE:
+ //setKeyStart(-1);
+ if (!editable) break;
+ if (contents.length() == 0) break;
+ start = selection.getStart();
+ end = selection.getEnd();
+ if (start == end) {
+ --start;
+ if (start < 0) {
+ getToolkit().beep(); // LIU: Add audio feedback of NOP
+ return;
+ }
+ }
+ replaceRange("", start, end);
+ break;
+ case KeyEvent.VK_DELETE:
+ //setKeyStart(-1);
+ if (!editable) break;
+ if (contents.length() == 0) break;
+ start = selection.getStart();
+ end = selection.getEnd();
+ if (start == end) {
+ ++end;
+ if (end > contents.length()) {
+ getToolkit().beep(); // LIU: Add audio feedback of NOP
+ return;
+ }
+ }
+ replaceRange("", start, end);
+ break;
+ default:
+ if (!editable) break;
+ // LIU: Dispatch to subclass API
+ handleKeyTyped(e);
+ break;
+ }
+ }
+
+ // LIU: Subclass API for handling of key typing
+ protected void handleKeyTyped(KeyEvent e) {
+ insertText(String.valueOf(e.getKeyChar()));
+ }
+
+ protected void setKeyStart(int keyStart) {
+ if (activeStart != keyStart) {
+ activeStart = keyStart;
+ repaint(10);
+ }
+ }
+
+ protected void validateKeyStart() {
+ if (activeStart > selection.getStart()) {
+ activeStart = selection.getStart();
+ repaint(10);
+ }
+ }
+
+ protected int getKeyStart() {
+ return activeStart;
+ }
+
+// ===================== Control ======================
+
+ public synchronized void setEditable(boolean b) {
+ editable = b;
+ }
+
+ public boolean isEditable() {
+ return editable;
+ }
+
+ public void select(Selection newSelection) {
+ newSelection.pin(contents);
+ if (!selection.equals(newSelection)) {
+ selection.set(newSelection);
+ if (selectionListener != null) {
+ selectionListener.actionPerformed(
+ new ActionEvent(this, ActionEvent.ACTION_PERFORMED,
+ "Selection Changed", 0));
+ }
+ repaint(10);
+ valid = false;
+ }
+ }
+
+ public void select(int start, int end) {
+ select(start, end, false);
+ }
+
+ public void select(int start, int end, boolean clickAfter) {
+ tempSelection.set(start, end, clickAfter);
+ select(tempSelection);
+ }
+
+ public int getSelectionStart() {
+ return selection.getStart();
+ }
+
+ public int getSelectionEnd() {
+ return selection.getEnd();
+ }
+
+ public void setBounds(int x, int y, int w, int h) {
+ super.setBounds(x,y,w,h);
+ redoLines = true;
+ }
+
+ public Dimension getPreferredSize() {
+ return new Dimension(lastWidth,lastHeight);
+ }
+
+ public Dimension getMaximumSize() {
+ return new Dimension(lastWidth,lastHeight);
+ }
+
+ public Dimension getMinimumSize() {
+ return new Dimension(lastHeight,lastHeight);
+ }
+
+ public void setText(String text) {
+ setText2(text);
+ select(tempSelection.set(selection).pin(contents));
+ }
+
+ public void setText2(String text) {
+ contents = text;
+ charBreaker.setText(text);
+ wordBreaker.setText(text);
+ lineBreaker.setText(text);
+ redoLines = true;
+ if (textListener != null)
+ textListener.textValueChanged(
+ new TextEvent(this, TextEvent.TEXT_VALUE_CHANGED));
+ repaint(16);
+ }
+
+ public void insertText(String text) {
+ if (activeStart == -1) activeStart = selection.getStart();
+ replaceRange(text, selection.getStart(), selection.getEnd());
+ }
+
+ public void replaceRange(String s, int start, int end) {
+ setText2(contents.substring(0,start) + s
+ + contents.substring(end));
+ select(tempSelection.set(selection).
+ fixAfterReplace(start, end, s.length()));
+ validateKeyStart();
+ }
+
+ public String getText() {
+ return contents;
+ }
+
+ public void setFont(Font font) {
+ super.setFont(font);
+ redoLines = true;
+ repaint(16);
+ }
+
+ // ================== Graphics ======================
+
+ public void update(Graphics g) {
+ if (DEBUG) System.out.println("update");
+ paint(g);
+ }
+
+ public void paint(Graphics g) {
+ mySize = getSize();
+ if (cacheImage == null
+ || cacheImage.getHeight(this) != mySize.height
+ || cacheImage.getWidth(this) != mySize.width) {
+ cacheImage = createImage(mySize.width, mySize.height);
+ valid = false;
+ }
+ if (!valid || redoLines) {
+ if (DEBUG) System.out.println("painting");
+ paint2(cacheImage.getGraphics());
+ valid = true;
+ }
+ //getToolkit().sync();
+ if (DEBUG) System.out.println("copying");
+ g.drawImage(cacheImage,
+ 0, 0, mySize.width, mySize.height,
+ 0, 0, mySize.width, mySize.height,
+ this);
+ }
+
+ public void paint2(Graphics g) {
+ g.clearRect(0, 0, mySize.width, mySize.height);
+ if (DEBUG) System.out.println("print");
+ if (focus) g.setColor(Color.black);
+ else g.setColor(Color.gray);
+ g.drawRect(0,0,mySize.width-1,mySize.height-1);
+ g.setClip(1,1,
+ mySize.width-2,mySize.height-2);
+ g.setColor(Color.black);
+ g.setFont(getFont());
+ fm = g.getFontMetrics();
+ lineAscent = fm.getAscent();
+ lineLeading = fm.getLeading();
+ lineHeight = lineAscent + fm.getDescent() + lineLeading;
+ int y = yInset + lineAscent;
+ String lastSubstring = "";
+ if (redoLines) fixLineStarts(mySize.width-xInset-xInset);
+ for (int i = 0; i < lineCount; y += lineHeight, ++i) {
+ // LIU: Don't display terminating ^M characters
+ int lim = lineStarts[i+1];
+ if (lim > 0 && contents.length() > 0 &&
+ contents.charAt(lim-1) == CR) --lim;
+ lastSubstring = contents.substring(lineStarts[i],lim);
+ g.drawString(lastSubstring, xInset, y);
+ }
+ drawSelection(g, lastSubstring);
+ lastHeight = y + yInset - lineHeight + yInset;
+ lastWidth = mySize.width-xInset-xInset;
+ }
+
+ void paintRect(Graphics g, int x, int y, int w, int h) {
+ if (focus) {
+ g.fillRect(x, y, w, h);
+ } else {
+ g.drawRect(x, y, w-1, h-1);
+ }
+ }
+
+ public void drawSelection(Graphics g, String lastSubstring) {
+ g.setXORMode(Color.black);
+ if (activeStart != -1) {
+ offset2Point(activeStart, false, activePoint);
+ g.setColor(Color.magenta);
+ int line = activePoint.x - 1;
+ g.fillRect(line, activePoint.y, 1, lineHeight);
+ }
+ if (selection.isCaret()) {
+ offset2Point(selection.caret, selection.clickAfter, caretPoint);
+ } else {
+ if (focus) g.setColor(Color.blue);
+ else g.setColor(Color.yellow);
+ offset2Point(selection.getStart(), true, startPoint);
+ offset2Point(selection.getEnd(), false, endPoint);
+ if (selection.getStart() == selection.caret)
+ caretPoint.setLocation(startPoint);
+ else caretPoint.setLocation(endPoint);
+ if (startPoint.y == endPoint.y) {
+ paintRect(g, startPoint.x, startPoint.y,
+ Math.max(1,endPoint.x-startPoint.x), lineHeight);
+ } else {
+ paintRect(g, startPoint.x, startPoint.y,
+ (mySize.width-xInset)-startPoint.x, lineHeight);
+ if (startPoint.y + lineHeight < endPoint.y)
+ paintRect(g, xInset, startPoint.y + lineHeight,
+ (mySize.width-xInset)-xInset, endPoint.y - startPoint.y - lineHeight);
+ paintRect(g, xInset, endPoint.y, endPoint.x-xInset, lineHeight);
+ }
+ }
+ if (focus || selection.isCaret()) {
+ if (focus) g.setColor(Color.green);
+ else g.setColor(Color.red);
+ int line = caretPoint.x - (selection.clickAfter ? 0 : 1);
+ g.fillRect(line, caretPoint.y, 1, lineHeight);
+ int w = lineHeight/12 + 1;
+ int braces = line - (selection.clickAfter ? -1 : w);
+ g.fillRect(braces, caretPoint.y, w, 1);
+ g.fillRect(braces, caretPoint.y + lineHeight - 1, w, 1);
+ }
+ }
+
+ public Point offset2Point(int off, boolean start, Point p) {
+ int line = findLine(off, start);
+ int width = 0;
+ try {
+ width = fm.stringWidth(
+ contents.substring(lineStarts[line], off));
+ } catch (Exception e) {
+ System.out.println(e);
+ }
+ p.x = width + xInset;
+ if (p.x > mySize.width - xInset)
+ p.x = mySize.width - xInset;
+ p.y = lineHeight * line + yInset;
+ return p;
+ }
+
+ private int findLine(int off, boolean start) {
+ // if it is start, then go to the next line!
+ if (start) ++off;
+ for (int i = 1; i < lineCount; ++i) {
+ // LIU: This was <= ; changed to < to make caret after
+ // final CR in line appear at START of next line.
+ if (off < lineStarts[i]) return i-1;
+ }
+ // LIU: Check for special case; after CR at end of the last line
+ if (off == lineStarts[lineCount] &&
+ off > 0 && contents.length() > 0 && contents.charAt(off-1) == CR) {
+ return lineCount;
+ }
+ return lineCount-1;
+ }
+
+ // offsets on any line will go from start,true to end,false
+ // excluding start,false and end,true
+ public Selection point2Offset(Point p, Selection o) {
+ if (p.y < yInset) {
+ o.caret = 0;
+ o.clickAfter = true;
+ return o;
+ }
+ int line = (p.y - yInset)/lineHeight;
+ if (line >= lineCount) {
+ o.caret = contents.length();
+ o.clickAfter = false;
+ return o;
+ }
+ int target = p.x - xInset;
+ if (target <= 0) {
+ o.caret = lineStarts[line];
+ o.clickAfter = true;
+ return o;
+ }
+ int lowGuess = lineStarts[line];
+ int lowWidth = 0;
+ int highGuess = lineStarts[line+1];
+ int highWidth = fm.stringWidth(contents.substring(lineStarts[line],highGuess));
+ if (target >= highWidth) {
+ o.caret = lineStarts[line+1];
+ o.clickAfter = false;
+ return o;
+ }
+ while (lowGuess < highGuess - 1) {
+ int guess = (lowGuess + highGuess)/2;
+ int width = fm.stringWidth(contents.substring(lineStarts[line],guess));
+ if (width <= target) {
+ lowGuess = guess;
+ lowWidth = width;
+ if (width == target) break;
+ } else {
+ highGuess = guess;
+ highWidth = width;
+ }
+ }
+ // at end, either lowWidth < target < width(low+1), or lowWidth = target
+ int highBound = charBreaker.following(lowGuess);
+ int lowBound = charBreaker.previous();
+ // we are now at character boundaries
+ if (lowBound != lowGuess)
+ lowWidth = fm.stringWidth(contents.substring(lineStarts[line],lowBound));
+ if (highBound != highGuess)
+ highWidth = fm.stringWidth(contents.substring(lineStarts[line],highBound));
+ // we now have the right widths
+ if (target - lowWidth < highWidth - target) {
+ o.caret = lowBound;
+ o.clickAfter = true;
+ } else {
+ o.caret = highBound;
+ o.clickAfter = false;
+ }
+ // we now have the closest!
+ return o;
+ }
+
+ private void fixLineStarts(int width) {
+ lineCount = 1;
+ lineStarts[0] = 0;
+ if (contents.length() == 0) {
+ lineStarts[1] = 0;
+ return;
+ }
+ int end = 0;
+ // LIU: Add check for MAX_LINES
+ for (int start = 0; start < contents.length() && lineCount < MAX_LINES;
+ start = end) {
+ end = nextLine(fm, start, width);
+ lineStarts[lineCount++] = end;
+ if (end == start) { // LIU: Assertion
+ throw new RuntimeException("nextLine broken");
+ }
+ }
+ --lineCount;
+ redoLines = false;
+ }
+
+ // LIU: Enhanced to wrap long lines. Bug with return of start fixed.
+ public int nextLine(FontMetrics fMtr, int start, int width) {
+ int len = contents.length();
+ for (int i = start; i < len; ++i) {
+ // check for line separator
+ char ch = (contents.charAt(i));
+ if (ch >= 0x000A && ch <= 0x000D || ch == 0x2028 || ch == 0x2029) {
+ len = i + 1;
+ if (ch == 0x000D && i+1 < len && contents.charAt(i+1) == 0x000A) // crlf
+ ++len; // grab extra char
+ break;
+ }
+ }
+ String subject = contents.substring(start,len);
+ if (visibleWidth(fMtr, subject) <= width)
+ return len;
+
+ // LIU: Remainder of this method rewritten to accomodate lines
+ // longer than the component width by first trying to break
+ // into lines; then words; finally chars.
+ int n = findFittingBreak(fMtr, subject, width, lineBreaker);
+ if (n == 0) {
+ n = findFittingBreak(fMtr, subject, width, wordBreaker);
+ }
+ if (n == 0) {
+ n = findFittingBreak(fMtr, subject, width, charBreaker);
+ }
+ return n > 0 ? start + n : len;
+ }
+
+ /**
+ * LIU: Finds the longest substring that fits a given width
+ * composed of subunits returned by a BreakIterator. If the smallest
+ * subunit is too long, returns 0.
+ * @param fMtr metrics to use
+ * @param line the string to be fix into width
+ * @param width line.substring(0, result) must be <= width
+ * @param breaker the BreakIterator that will be used to find subunits
+ * @return maximum characters, at boundaries returned by breaker,
+ * that fit into width, or zero on failure
+ */
+ private int findFittingBreak(FontMetrics fMtr, String line, int width,
+ BreakIterator breaker) {
+ breaker.setText(line);
+ int last = breaker.first();
+ int end = breaker.next();
+ while (end != BreakIterator.DONE &&
+ visibleWidth(fMtr, line.substring(0, end)) <= width) {
+ last = end;
+ end = breaker.next();
+ }
+ return last;
+ }
+
+ public int visibleWidth(FontMetrics fMtr, String s) {
+ int i;
+ for (i = s.length()-1; i >= 0; --i) {
+ char ch = s.charAt(i);
+ if (!(ch == ' ' || ch >= 0x000A && ch <= 0x000D || ch == 0x2028 || ch == 0x2029))
+ return fMtr.stringWidth(s.substring(0,i+1));
+ }
+ return 0;
+ }
+
+// =============== Utility ====================
+
+ private void fixHex() {
+ if (selection.getEnd() == 0) return;
+ int store = 0;
+ int places = 1;
+ int count = 0;
+ int min = Math.min(8,selection.getEnd());
+ for (int i = 0; i < min; ++i) {
+ char ch = contents.charAt(selection.getEnd()-1-i);
+ int value = Character.getNumericValue(ch);
+ if (value < 0 || value > 15) break;
+ store += places * value;
+ ++count;
+ places *= 16;
+ }
+ String add = "";
+ int bottom = store & 0xFFFF;
+ if (store >= 0xD8000000 && store < 0xDC000000
+ && bottom >= 0xDC00 && bottom < 0xE000) { // surrogates
+ add = "" + (char)(store >> 16) + (char)bottom;
+ } else if (store > 0xFFFF && store <= 0x10FFFF) {
+ store -= 0x10000;
+ add = "" + (char)(((store >> 10) & 0x3FF) + 0xD800)
+ + (char)((store & 0x3FF) + 0xDC00);
+
+ } else if (count >= 4) {
+ count = 4;
+ add = ""+(char)(store & 0xFFFF);
+ } else {
+ count = 1;
+ char ch = contents.charAt(selection.getEnd()-1);
+ add = hex(ch);
+ if (ch >= 0xDC00 && ch <= 0xDFFF && selection.getEnd() > 1) {
+ ch = contents.charAt(selection.getEnd()-2);
+ if (ch >= 0xD800 && ch <= 0xDBFF) {
+ count = 2;
+ add = hex(ch) + add;
+ }
+ }
+ }
+ replaceRange(add, selection.getEnd()-count, selection.getEnd());
+ }
+
+ public static String hex(char ch) {
+ String result = Integer.toString(ch,16).toUpperCase();
+ result = "0000".substring(result.length(),4) + result;
+ return result;
+ }
+}
diff --git a/demos/src/com/ibm/icu/dev/demo/impl/Selection.java b/demos/src/com/ibm/icu/dev/demo/impl/Selection.java
new file mode 100644
index 0000000..c07b770
--- /dev/null
+++ b/demos/src/com/ibm/icu/dev/demo/impl/Selection.java
@@ -0,0 +1,161 @@
+/*
+ *******************************************************************************
+ * Copyright (C) 1996-2010, International Business Machines Corporation and *
+ * others. All Rights Reserved. *
+ *******************************************************************************
+ */
+package com.ibm.icu.dev.demo.impl;
+import java.text.BreakIterator;
+
+public final class Selection {
+
+ public int anchor;
+ public int caret;
+ public boolean clickAfter;
+
+ public int getStart() {
+ return anchor < caret ? anchor : caret;
+ }
+
+ public int getEnd() {
+ return anchor > caret ? anchor : caret;
+ }
+
+ public boolean isCaret() {
+ return anchor == caret;
+ }
+
+ public Selection set(Selection other) {
+ anchor = other.anchor;
+ caret = other.caret;
+ clickAfter = other.clickAfter;
+ return this;
+ }
+
+ public Selection set(int anchor, int caret, boolean clickAfter) {
+ this.anchor = anchor;
+ this.caret = caret;
+ this.clickAfter = clickAfter;
+ return this;
+ }
+
+ public boolean equals(Object other) {
+ Selection other2 = (Selection)other;
+ return anchor == other2.anchor
+ && caret == other2.caret
+ && clickAfter == other2.clickAfter;
+ }
+
+ public boolean isLessThan(Selection other) {
+ return getStart() < other.getEnd();
+ }
+
+ public Selection pin(String text) {
+ if (anchor > text.length()) {
+ anchor = text.length();
+ } else if (anchor < 0) {
+ anchor = 0;
+ }
+ if (caret > text.length()) {
+ caret = text.length();
+ clickAfter = true;
+ } else if (caret < 0) {
+ caret = 0;
+ clickAfter = false;
+ }
+ return this;
+ }
+
+ public Selection swap(Selection after) {
+ int temp = anchor;
+ anchor = after.anchor;
+ after.anchor = temp;
+ temp = caret;
+ caret = after.caret;
+ after.caret = temp;
+ boolean b = clickAfter;
+ clickAfter = after.clickAfter;
+ after.clickAfter = b;
+ return this;
+ }
+
+ public Selection fixAfterReplace(int start, int end, int len) {
+ if (anchor >= start) {
+ if (anchor < end) anchor = end;
+ anchor = start + len + anchor - end;
+ }
+ if (caret >= start) {
+ if (caret < end) caret = end;
+ caret = start + len + caret - end;
+ }
+ return this;
+ }
+
+ // Mac & Windows considerably different
+ // Mac: end++. If start!=end, start=end
+ // SHIFT: move end right
+ // CTL: no different
+ // Windows:
+ // UNSHIFTED: if start!=end, start = end, else start=end=end+1;
+ // anchor = tip = start
+ // SHIFT: tip++
+ // CTL: if start!=end, start = end = nextbound(end-1),
+ // else start=end=nextbound(end)
+ // anchor = tip = start
+ // CTL/SHIFT: tip = nextbound(tip)
+
+ public Selection nextBound(BreakIterator breaker,
+ int direction, boolean extend) {
+ if (!extend && anchor != caret) caret -= direction;
+ caret = next(caret, breaker, direction, true);
+ if (!extend) anchor = caret;
+ clickAfter = false;
+ return this;
+ }
+
+ // expand start and end to word breaks--if they are not already on one
+ public void expand(BreakIterator breaker) {
+ if (anchor <= caret) {
+ anchor = next(anchor,breaker,-1,false);
+ caret = next(caret,breaker,1,false);
+ /*
+ try {
+ breaker.following(anchor);
+ anchor = breaker.previous();
+ } catch (Exception e) {}
+ try {
+ caret = breaker.following(caret-1);
+ } catch (Exception e) {}
+ */
+ } else {
+ anchor = next(anchor,breaker,1,false);
+ caret = next(caret,breaker,-1,false);
+ /*
+ try {
+ breaker.following(caret);
+ caret = breaker.previous();
+ } catch (Exception e) {}
+ try {
+ anchor = breaker.following(anchor-1);
+ } catch (Exception e) {}
+ */
+ }
+ }
+
+ // different = false - move to next boundary, unless on one
+ // true - move to next boundary, even if on one
+ public static int next(int position, BreakIterator breaker,
+ int direction, boolean different) {
+ if (!different) position -= direction;
+ try {
+ if (direction > 0) {
+ position = breaker.following(position);
+ } else {
+ breaker.following(position-1);
+ position = breaker.previous();
+ }
+ } catch (Exception e) {}
+ return position;
+ }
+}
+
diff --git a/demos/src/com/ibm/icu/dev/demo/impl/package.html b/demos/src/com/ibm/icu/dev/demo/impl/package.html
new file mode 100644
index 0000000..a7e8d35
--- /dev/null
+++ b/demos/src/com/ibm/icu/dev/demo/impl/package.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!-- Copyright (C) 2000-2004, International Business Machines Corporation and
+ others. All Rights Reserved.
+
+-->
+</head>
+<body bgcolor="white">
+Shared utilities for demo applications and Applets.
+</body>
+</html>
\ No newline at end of file
diff --git a/demos/src/com/ibm/icu/dev/demo/number/CurrencyDemo.java b/demos/src/com/ibm/icu/dev/demo/number/CurrencyDemo.java
new file mode 100644
index 0000000..6e36765
--- /dev/null
+++ b/demos/src/com/ibm/icu/dev/demo/number/CurrencyDemo.java
@@ -0,0 +1,114 @@
+/*
+**********************************************************************
+* Copyright (c) 2003-2010, International Business Machines
+* Corporation and others. All Rights Reserved.
+**********************************************************************
+* Author: Mark Davis
+* Created: May 22 2003
+* Since: ICU 2.6
+**********************************************************************
+*/
+package com.ibm.icu.dev.demo.number;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import com.ibm.icu.impl.Utility;
+import com.ibm.icu.text.DecimalFormat;
+import com.ibm.icu.text.DecimalFormatSymbols;
+import com.ibm.icu.text.NumberFormat;
+import com.ibm.icu.util.Currency;
+
+/**
+ * Demonstration code to illustrate how to obtain ICU 2.6-like currency
+ * behavior using pre-ICU 2.6 ICU4J.
+ * @author Mark Davis
+ */
+public class CurrencyDemo {
+
+ public static void main(String[] args) {
+ testFormatHack(true);
+ }
+
+ static NumberFormat getCurrencyFormat(Currency currency,
+ Locale displayLocale,
+ boolean ICU26) {
+ // code for ICU 2.6
+ if (ICU26) {
+ NumberFormat result = NumberFormat.getCurrencyInstance(displayLocale);
+ result.setCurrency(currency);
+ return result;
+ }
+
+ // ugly work-around for 2.4
+ DecimalFormat result = (DecimalFormat)NumberFormat.getCurrencyInstance(displayLocale);
+ HackCurrencyInfo hack = (HackCurrencyInfo)(hackData.get(currency.getCurrencyCode()));
+ result.setMinimumFractionDigits(hack.decimals);
+ result.setMaximumFractionDigits(hack.decimals);
+ result.setRoundingIncrement(hack.rounding);
+ DecimalFormatSymbols symbols = result.getDecimalFormatSymbols();
+ symbols.setCurrencySymbol(hack.symbol);
+ result.setDecimalFormatSymbols(symbols);
+ return result;
+ }
+
+ static Map hackData = new HashMap();
+ static class HackCurrencyInfo {
+ int decimals;
+ double rounding;
+ String symbol;
+ HackCurrencyInfo(int decimals, double rounding, String symbol) {
+ this.decimals = decimals;
+ this.rounding = rounding;
+ this.symbol = symbol;
+ }
+ }
+ static {
+ hackData.put("USD", new HackCurrencyInfo(2, 0, "$"));
+ hackData.put("GBP", new HackCurrencyInfo(2, 0, "\u00A3"));
+ hackData.put("JPY", new HackCurrencyInfo(0, 0, "\u00A5"));
+ hackData.put("EUR", new HackCurrencyInfo(2, 0, "\u20AC"));
+ }
+
+ /**
+ * Walk through all locales and compare the output of the ICU26
+ * currency format with the "hacked" currency format.
+ * @param quiet if true, only display discrepancies. Otherwise,
+ * display all results.
+ */
+ static void testFormatHack(boolean quiet) {
+ String[] testCurrencies = {"USD","GBP","JPY","EUR"};
+ Locale[] testLocales = NumberFormat.getAvailableLocales();
+ for (int i = 0; i < testLocales.length; ++i) {
+ // since none of this should vary by country, we'll just do by language
+ if (!testLocales[i].getCountry().equals("")) continue;
+ boolean noOutput = true;
+ if (!quiet) {
+ System.out.println(testLocales[i].getDisplayName());
+ noOutput = false;
+ }
+ for (int j = 0; j < testCurrencies.length; ++j) {
+ NumberFormat nf26 = getCurrencyFormat(Currency.getInstance(testCurrencies[j]), testLocales[i], true);
+ String str26 = nf26.format(1234.567);
+ if (!quiet) {
+ System.out.print("\t" + Utility.escape(str26));
+ }
+ NumberFormat nf24 = getCurrencyFormat(Currency.getInstance(testCurrencies[j]), testLocales[i], false);
+ String str24 = nf24.format(1234.567);
+ if (!str24.equals(str26)) {
+ if (noOutput) {
+ System.out.println(testLocales[i].getDisplayName());
+ noOutput = false;
+ }
+ if (quiet) {
+ System.out.print("\t" + Utility.escape(str26));
+ }
+ System.out.print(" (" + Utility.escape(str24) + ")");
+ }
+ }
+ if (!noOutput) {
+ System.out.println();
+ }
+ }
+ }
+}
diff --git a/demos/src/com/ibm/icu/dev/demo/rbnf/RbnfDemo.java b/demos/src/com/ibm/icu/dev/demo/rbnf/RbnfDemo.java
new file mode 100644
index 0000000..76f8f01
--- /dev/null
+++ b/demos/src/com/ibm/icu/dev/demo/rbnf/RbnfDemo.java
@@ -0,0 +1,580 @@
+/*
+ *******************************************************************************
+ * Copyright (C) 1996-2010, International Business Machines Corporation and *
+ * others. All Rights Reserved. *
+ *******************************************************************************
+ */
+package com.ibm.icu.dev.demo.rbnf;
+
+import java.awt.BorderLayout;
+import java.awt.Button;
+import java.awt.CardLayout;
+import java.awt.Checkbox;
+import java.awt.Choice;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Frame;
+import java.awt.Graphics;
+import java.awt.GridLayout;
+import java.awt.Panel;
+import java.awt.ScrollPane;
+import java.awt.TextArea;
+import java.awt.TextComponent;
+import java.awt.TextField;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusAdapter;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.awt.event.TextEvent;
+import java.awt.event.TextListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.text.BreakIterator;
+import java.text.DecimalFormat;
+import java.text.ParsePosition;
+import java.util.Locale;
+
+import com.ibm.icu.dev.demo.impl.DemoApplet;
+import com.ibm.icu.text.RuleBasedNumberFormat;
+
+public class RbnfDemo extends DemoApplet {
+ /**
+ * For serialization
+ */
+ private static final long serialVersionUID = -9119861296873763536L;
+
+ /**
+ * Puts a copyright in the .class file
+ */
+// private static final String copyrightNotice
+// = "Copyright \u00a91997-1998 IBM Corp. All rights reserved.";
+
+ /*
+ * code to run the demo as an application
+ */
+ public static void main(String[] argv) {
+ new RbnfDemo().showDemo();
+ }
+
+ protected Dimension getDefaultFrameSize(DemoApplet applet, Frame f) {
+ return new Dimension(430,270);
+ }
+
+ protected Frame createDemoFrame(DemoApplet applet) {
+ final Frame window = new Frame("Number Spellout Demo");
+ window.setSize(800, 600);
+ window.setLayout(new BorderLayout());
+
+ Panel mainPanel = new Panel();
+ mainPanel.setLayout(new GridLayout(1,2));
+
+ commentaryField = new TextArea("", 0, 0, TextArea.SCROLLBARS_VERTICAL_ONLY);
+ commentaryField.setSize(800, 50);
+ commentaryField.setText(RbnfSampleRuleSets.sampleRuleSetCommentary[0]);
+ commentaryField.setEditable(false);
+ commentaryField.setFont(new Font("Helvetica", Font.PLAIN, 14));
+
+ spelloutFormatter = new RuleBasedNumberFormat(RbnfSampleRuleSets.usEnglish, Locale.US);
+ spelloutFormatter.setLenientParseMode(lenientParse);
+ populateRuleSetMenu();
+ numberFormatter = new DecimalFormat("#,##0.##########");
+ parsePosition = new ParsePosition(0);
+ theNumber = 0;
+
+ numberField = new TextField();
+ numberField.setFont(new Font("Serif", Font.PLAIN, 24));
+ textField = new DemoTextFieldHolder();
+ textField.setFont(new Font("Serif", Font.PLAIN, 24));
+ rulesField = new DemoTextFieldHolder();
+ rulesField.setFont(new Font("Serif", Font.PLAIN, 14));
+ lenientParseButton = new Checkbox("Lenient parse", lenientParse);
+
+ numberField.addTextListener(new TextListener() {
+ public void textValueChanged(TextEvent e) {
+ if (!numberFieldHasFocus)
+ return;
+
+ String fieldText = ((TextComponent)(e.getSource())).getText();
+ parsePosition.setIndex(0);
+ Number temp = numberFormatter.parse(fieldText, parsePosition);
+ if (temp == null || parsePosition.getIndex() == 0) {
+ theNumber = 0;
+ textField.setText("PARSE ERROR");
+ }
+ else {
+ theNumber = temp.doubleValue();
+ textField.setText(spelloutFormatter.format(theNumber, ruleSetName));
+ }
+ }
+ } );
+
+ numberField.addFocusListener(new FocusAdapter() {
+ public void focusLost(FocusEvent e) {
+ numberFieldHasFocus = false;
+ numberField.setText(numberFormatter.format(theNumber));
+ }
+
+ public void focusGained(FocusEvent e) {
+ numberFieldHasFocus = true;
+ numberField.selectAll();
+ }
+ } );
+
+ textField.addKeyListener(new KeyAdapter() {
+ public void keyTyped(KeyEvent e) {
+ if (e.getKeyChar() == '\t') {
+ String fieldText = ((TextComponent)(e.getSource())).getText();
+ parsePosition.setIndex(0);
+ theNumber = spelloutFormatter.parse(fieldText, parsePosition)
+ .doubleValue();
+ if (parsePosition.getIndex() == 0) {
+ theNumber = 0;
+ numberField.setText("PARSE ERROR");
+ textField.selectAll();
+ }
+ else if (parsePosition.getIndex() < fieldText.length()) {
+ textField.select(parsePosition.getIndex(), fieldText.length());
+ numberField.setText(numberFormatter.format(theNumber));
+ }
+ else {
+ textField.selectAll();
+ numberField.setText(numberFormatter.format(theNumber));
+ }
+ e.consume();
+ }
+ }
+ } );
+
+ textField.addFocusListener(new FocusAdapter() {
+ public void focusLost(FocusEvent e) {
+ String fieldText = ((TextComponent)(e.getSource())).getText();
+ parsePosition.setIndex(0);
+ theNumber = spelloutFormatter.parse(fieldText, parsePosition)
+ .doubleValue();
+ if (parsePosition.getIndex() == 0)
+ numberField.setText("PARSE ERROR");
+ else
+ numberField.setText(numberFormatter.format(theNumber));
+ textField.setText(textField.getText()); // textField.repaint() didn't work right
+ }
+
+ public void focusGained(FocusEvent e) {
+ textField.selectAll();
+ }
+ } );
+
+ rulesField.addKeyListener(new KeyAdapter() {
+ public void keyTyped(KeyEvent e) {
+ if (e.getKeyChar() == '\t') {
+ String fieldText = ((TextComponent)(e.getSource())).getText();
+ if (formatterMenu.getSelectedItem().equals("Custom") || !fieldText.equals(
+ RbnfSampleRuleSets.sampleRuleSets[formatterMenu.getSelectedIndex()])) {
+ try {
+ RuleBasedNumberFormat temp = new RuleBasedNumberFormat(fieldText);
+ temp.setLenientParseMode(lenientParse);
+ populateRuleSetMenu();
+ spelloutFormatter = temp;
+ customRuleSet = fieldText;
+ formatterMenu.select("Custom");
+ commentaryField.setText(RbnfSampleRuleSets.
+ sampleRuleSetCommentary[RbnfSampleRuleSets.
+ sampleRuleSetCommentary.length - 1]);
+ redisplay();
+ }
+ catch (Exception x) {
+ textField.setText(x.toString());
+ }
+ }
+ e.consume();
+ }
+ }
+ } );
+
+ rulesField.addFocusListener(new FocusAdapter() {
+ public void focusLost(FocusEvent e) {
+ String fieldText = ((TextComponent)(e.getSource())).getText();
+ if (formatterMenu.getSelectedItem().equals("Custom") || !fieldText.equals(
+ RbnfSampleRuleSets.sampleRuleSets[formatterMenu.getSelectedIndex()])) {
+ try {
+ RuleBasedNumberFormat temp = new RuleBasedNumberFormat(fieldText);
+ temp.setLenientParseMode(lenientParse);
+ populateRuleSetMenu();
+ spelloutFormatter = temp;
+ customRuleSet = fieldText;
+ formatterMenu.select("Custom");
+ redisplay();
+ }
+ catch (Exception x) {
+ textField.setText(x.toString());
+ }
+ }
+ rulesField.setText(rulesField.getText()); // rulesField.repaint() didn't work right
+ }
+ } );
+
+ lenientParseButton.addItemListener(new ItemListener() {
+ public void itemStateChanged(ItemEvent e) {
+ lenientParse = lenientParseButton.getState();
+ spelloutFormatter.setLenientParseMode(lenientParse);
+ }
+ } );
+
+ numberField.setText(numberFormatter.format(theNumber));
+ numberField.selectAll();
+ textField.setText(spelloutFormatter.format(theNumber, ruleSetName));
+
+ Panel leftPanel = new Panel();
+ leftPanel.setLayout(new BorderLayout());
+ Panel panel = new Panel();
+ panel.setLayout(new BorderLayout());
+ Panel panel1 = new Panel();
+ panel1.setLayout(new GridLayout(3, 1));
+ panel1.add(new Panel());
+ panel1.add(numberField, "Center");
+ panel1.add(lenientParseButton);
+ panel.add(panel1, "Center");
+ Panel panel2 = new Panel();
+ panel2.setLayout(new GridLayout(3, 3));
+ Button button = new Button("+100");
+ button.addActionListener( new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ roll(100);
+ }
+ } );
+ panel2.add(button);
+ button = new Button("+10");
+ button.addActionListener( new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ roll(10);
+ }
+ } );
+ panel2.add(button);
+ button = new Button("+1");
+ button.addActionListener( new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ roll(1);
+ }
+ } );
+ panel2.add(button);
+ button = new Button("<");
+ button.addActionListener( new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ theNumber *= 10;
+ redisplay();
+ }
+ } );
+ panel2.add(button);
+ panel2.add(new Panel());
+ button = new Button(">");
+ button.addActionListener( new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ theNumber /= 10;
+ redisplay();
+ }
+ } );
+ panel2.add(button);
+ button = new Button("-100");
+ button.addActionListener( new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ roll(-100);
+ }
+ } );
+ panel2.add(button);
+ button = new Button("-10");
+ button.addActionListener( new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ roll(-10);
+ }
+ } );
+ panel2.add(button);
+ button = new Button("-1");
+ button.addActionListener( new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ roll(-1);
+ }
+ } );
+ panel2.add(button);
+ panel.add(panel2, "East");
+ leftPanel.add(panel, "North");
+ leftPanel.add(textField, "Center");
+
+ Panel rightPanel = new Panel();
+ rightPanel.setLayout(new BorderLayout());
+ formatterMenu = new Choice();
+ for (int i = 0; i < RbnfSampleRuleSets.sampleRuleSetNames.length; i++)
+ formatterMenu.addItem(RbnfSampleRuleSets.sampleRuleSetNames[i]);
+ formatterMenu.addItem("Custom");
+ formatterMenu.addItemListener(new ItemListener() {
+ public void itemStateChanged(ItemEvent e) {
+ Choice source = (Choice)(e.getSource());
+ int item = source.getSelectedIndex();
+ Locale locale = RbnfSampleRuleSets.sampleRuleSetLocales[item];
+
+ commentaryField.setText(RbnfSampleRuleSets.
+ sampleRuleSetCommentary[item]);
+
+ if (locale != null && (locale.getLanguage().equals("iw")
+ || locale.getLanguage().equals("ru") || locale.getLanguage().equals("ja")
+ || locale.getLanguage().equals("el")
+ || locale.getLanguage().equals("zh"))) {
+ textField.togglePanes(false);
+ rulesField.togglePanes(false);
+ }
+ else {
+ textField.togglePanes(true);
+ rulesField.togglePanes(true);
+ }
+
+ makeNewSpelloutFormatter();
+ redisplay();
+ }
+ } );
+
+ ruleSetMenu = new Choice();
+ populateRuleSetMenu();
+
+ ruleSetMenu.addItemListener(new ItemListener() {
+ public void itemStateChanged(ItemEvent e) {
+ ruleSetName = ruleSetMenu.getSelectedItem();
+ redisplay();
+ }
+ } );
+
+ Panel menuPanel = new Panel();
+ menuPanel.setLayout(new GridLayout(1, 2));
+ menuPanel.add(formatterMenu);
+ menuPanel.add(ruleSetMenu);
+ rightPanel.add(menuPanel, "North");
+
+ rulesField.setText(RbnfSampleRuleSets.sampleRuleSets[formatterMenu.getSelectedIndex()]);
+ rightPanel.add(rulesField, "Center");
+
+ mainPanel.add(leftPanel);
+ mainPanel.add(rightPanel);
+
+ window.add(mainPanel, "Center");
+ window.add(commentaryField, "South");
+
+ window.doLayout();
+ window.show();
+ final DemoApplet theApplet = applet;
+ window.addWindowListener(
+ new WindowAdapter() {
+ public void windowClosing(WindowEvent e) {
+ setVisible(false);
+ window.dispose();
+
+ if (theApplet != null) {
+ theApplet.demoClosed();
+ } else System.exit(0);
+ }
+ } );
+ return window;
+ }
+
+ void roll(int delta) {
+ theNumber += delta;
+ redisplay();
+ }
+
+ void redisplay() {
+ numberField.setText(numberFormatter.format(theNumber));
+ textField.setText(spelloutFormatter.format(theNumber, ruleSetName));
+ }
+
+ void makeNewSpelloutFormatter() {
+ int item = formatterMenu.getSelectedIndex();
+ String formatterMenuItem = formatterMenu.getSelectedItem();
+
+ if (formatterMenuItem.equals("Custom")) {
+ rulesField.setText(customRuleSet);
+ spelloutFormatter = new RuleBasedNumberFormat(customRuleSet);
+ }
+ else {
+ rulesField.setText(RbnfSampleRuleSets.sampleRuleSets[item]);
+
+ Locale locale = RbnfSampleRuleSets.sampleRuleSetLocales[item];
+ if (locale == null)
+ locale = Locale.getDefault();
+
+ spelloutFormatter = new RuleBasedNumberFormat(RbnfSampleRuleSets.
+ sampleRuleSets[item], locale);
+ }
+ spelloutFormatter.setLenientParseMode(lenientParse);
+ populateRuleSetMenu();
+ }
+
+ void populateRuleSetMenu() {
+ String[] ruleSetNames = spelloutFormatter.getRuleSetNames();
+
+ if (ruleSetMenu != null) {
+ ruleSetMenu.removeAll();
+ for (int i = 0; i < ruleSetNames.length; i++)
+ ruleSetMenu.addItem(ruleSetNames[i]);
+
+ ruleSetName = ruleSetMenu.getSelectedItem();
+ }
+ else
+ ruleSetName = ruleSetNames[0];
+ }
+
+// private Frame demoWindow = null;
+
+ private TextComponent numberField;
+ private DemoTextFieldHolder textField;
+ private DemoTextFieldHolder rulesField;
+ private TextComponent commentaryField;
+ private Checkbox lenientParseButton;
+
+ private boolean numberFieldHasFocus = true;
+
+ private RuleBasedNumberFormat spelloutFormatter;
+ private DecimalFormat numberFormatter;
+ private ParsePosition parsePosition;
+
+ private boolean lenientParse = true;
+
+ private double theNumber = 0;
+// private boolean canEdit = true;
+
+ private Choice formatterMenu;
+ private Choice ruleSetMenu;
+ private String ruleSetName;
+
+ private String customRuleSet = "NO RULES!";
+}
+
+class DemoTextField extends Component {
+ /**
+ * For serialization
+ */
+ private static final long serialVersionUID = -7947090021239472658L;
+ public DemoTextField() {
+ }
+
+ public void setText(String text) {
+ this.text = text;
+ this.repaint();
+ }
+
+ public String getText() {
+ return text;
+ }
+
+ public void paint(Graphics g) {
+ Font font = getFont();
+ FontMetrics fm = g.getFontMetrics();
+ g.setFont(font);
+ String txt = getText();
+ BreakIterator bi = BreakIterator.getLineInstance();
+ bi.setText(txt);
+ int lineHeight = fm.getHeight();
+ int width = getSize().width;
+ int penY = fm.getAscent();
+ int lineStart = 0;
+ int tempLineEnd = bi.first();
+ int lineEnd = 0;
+ int maxLineEnd = 0;
+ totalHeight = 0;
+
+ while (lineStart < txt.length()) {
+ maxLineEnd = txt.indexOf('\n', lineStart);
+ if (maxLineEnd == -1)
+ maxLineEnd = Integer.MAX_VALUE;
+ while (tempLineEnd != BreakIterator.DONE && fm.stringWidth(txt.substring(
+ lineStart, tempLineEnd)) < width) {
+ lineEnd = tempLineEnd;
+ tempLineEnd = bi.next();
+ }
+ if (lineStart >= lineEnd) {
+ if (tempLineEnd == BreakIterator.DONE)
+ lineEnd = txt.length();
+ else
+ lineEnd = tempLineEnd;
+ }
+ if (lineEnd > maxLineEnd)
+ lineEnd = maxLineEnd;
+ g.drawString(txt.substring(lineStart, lineEnd), 0, penY);
+ penY += lineHeight;
+ totalHeight += lineHeight;
+ lineStart = lineEnd;
+ if (lineStart < txt.length() && txt.charAt(lineStart) == '\n')
+ ++lineStart;
+ }
+ }
+
+/*
+ public Dimension getPreferredSize() {
+ Dimension size = getParent().getSize();
+ return new Dimension(size.width, totalHeight);
+ }
+*/
+
+ private String text;
+ private int totalHeight;
+}
+
+class DemoTextFieldHolder extends Panel {
+ /**
+ * For serialization
+ */
+ private static final long serialVersionUID = 7514498764062569858L;
+ public DemoTextFieldHolder() {
+ tf1 = new TextArea("", 0, 0, TextArea.SCROLLBARS_VERTICAL_ONLY);
+ tf2 = new DemoTextField();
+ sp = new ScrollPane();
+
+ setLayout(new CardLayout());
+
+ sp.add(tf2, "TextField1");
+ sp.setVisible(false);
+ add(tf1, "TestField2");
+ add(sp, "ScrollPane");
+ }
+
+ public void addFocusListener(FocusListener l) {
+ tf1.addFocusListener(l);
+ }
+
+ public void addKeyListener(KeyListener l) {
+ tf1.addKeyListener(l);
+ }
+
+ public void setText(String text) {
+ tf1.setText(text);
+ tf2.setText(text);
+ }
+
+ public String getText() {
+ return tf1.getText();
+ }
+
+ public void select(int start, int end) {
+ tf1.select(start, end);
+ }
+
+ public void selectAll() {
+ tf1.selectAll();
+ }
+
+ public void togglePanes(boolean canShowRealTextField) {
+ if (canShowRealTextField != showingRealTextField) {
+ CardLayout layout = (CardLayout)(getLayout());
+ layout.next(this);
+ showingRealTextField = canShowRealTextField;
+ }
+ }
+
+ private TextArea tf1 = null;
+ private DemoTextField tf2 = null;
+ private ScrollPane sp = null;
+ private boolean showingRealTextField = true;
+}
diff --git a/demos/src/com/ibm/icu/dev/demo/rbnf/RbnfSampleRuleSets.java b/demos/src/com/ibm/icu/dev/demo/rbnf/RbnfSampleRuleSets.java
new file mode 100644
index 0000000..c03ed71
--- /dev/null
+++ b/demos/src/com/ibm/icu/dev/demo/rbnf/RbnfSampleRuleSets.java
@@ -0,0 +1,1941 @@
+/*
+ *******************************************************************************
+ * Copyright (C) 1996-2007, International Business Machines Corporation and *
+ * others. All Rights Reserved. *
+ *******************************************************************************
+ */
+package com.ibm.icu.dev.demo.rbnf;
+
+import java.util.Locale;
+
+/**
+ * A collection of example rule sets for use with RuleBasedNumberFormat.
+ * These examples are intended to serve both as demonstrations of what can
+ * be done with this framework, and as starting points for designing new
+ * rule sets.
+ *
+ * For those that claim to represent number-spellout rules for languages
+ * other than U.S. English, we make no claims of either accuracy or
+ * completeness. In fact, we know them to be incomplete, and suspect
+ * most have mistakes in them. If you see something that you know is wrong,
+ * please tell us!
+ *
+ * @author Richard Gillam
+ */
+public class RbnfSampleRuleSets {
+ /**
+ * Puts a copyright in the .class file
+ */
+// private static final String copyrightNotice
+// = "Copyright \u00a91997-1998 IBM Corp. All rights reserved.";
+
+ //========================================================================
+ // Spellout rules for various languages
+ //
+ // The following RuleBasedNumberFormat descriptions show the rules for
+ // spelling out numeric values in various languages. As mentioned
+ // before, we cannot vouch for the accuracy or completeness of this
+ // data, although we believe it's pretty close. Basically, this
+ // represents one day's worth of Web-surfing. If you can supply the
+ // missing information in any of these rule sets, or if you find errors,
+ // or if you can supply spellout rules for languages that aren't shown
+ // here, we want to hear from you!
+ //========================================================================
+
+ /**
+ * Spellout rules for U.S. English. This demonstration version of the
+ * U.S. English spellout rules has four variants: 1) %simplified is a
+ * set of rules showing the simple method of spelling out numbers in
+ * English: 289 is formatted as "two hundred eighty-nine". 2) %alt-teens
+ * is the same as %simplified, except that values between 1,000 and 9,999
+ * whose hundreds place isn't zero are formatted in hundreds. For example,
+ * 1,983 is formatted as "nineteen hundred eighty-three," and 2,183 is
+ * formatted as "twenty-one hundred eighty-three," but 2,083 is still
+ * formatted as "two thousand eighty-three." 3) %ordinal formats the
+ * values as ordinal numbers in English (e.g., 289 is "two hundred eighty-
+ * ninth"). 4) %default uses a more complicated algorithm to format
+ * numbers in a more natural way: 289 is formatted as "two hundred AND
+ * eighty-nine" and commas are inserted between the thousands groups for
+ * values above 100,000.
+ */
+ public static final String usEnglish =
+ // This rule set shows the normal simple formatting rules for English
+ "%simplified:\n"
+ // negative number rule. This rule is used to format negative
+ // numbers. The result of formatting the number's absolute
+ // value is placed where the >> is.
+ + " -x: minus >>;\n"
+ // faction rule. This rule is used for formatting numbers
+ // with fractional parts. The result of formatting the
+ // number's integral part is substituted for the <<, and
+ // the result of formatting the number's fractional part
+ // (one digit at a time, e.g., 0.123 is "zero point one two
+ // three") replaces the >>.
+ + " x.x: << point >>;\n"
+ // the rules for the values from 0 to 19 are simply the
+ // words for those numbers
+ + " zero; one; two; three; four; five; six; seven; eight; nine;\n"
+ + " ten; eleven; twelve; thirteen; fourteen; fifteen; sixteen;\n"
+ + " seventeen; eighteen; nineteen;\n"
+ // beginning at 20, we use the >> to mark the position where
+ // the result of formatting the number's ones digit. Thus,
+ // we only need a new rule at every multiple of 10. Text in
+ // backets is omitted if the value being formatted is an
+ // even multiple of 10.
+ + " 20: twenty[->>];\n"
+ + " 30: thirty[->>];\n"
+ + " 40: forty[->>];\n"
+ + " 50: fifty[->>];\n"
+ + " 60: sixty[->>];\n"
+ + " 70: seventy[->>];\n"
+ + " 80: eighty[->>];\n"
+ + " 90: ninety[->>];\n"
+ // beginning at 100, we can use << to mark the position where
+ // the result of formatting the multiple of 100 is to be
+ // inserted. Notice also that the meaning of >> has shifted:
+ // here, it refers to both the ones place and the tens place.
+ // The meanings of the << and >> tokens depend on the base value
+ // of the rule. A rule's divisor is (usually) the highest
+ // power of 10 that is less than or equal to the rule's base
+ // value. The value being formatted is divided by the rule's
+ // divisor, and the integral quotient is used to get the text
+ // for <<, while the remainder is used to produce the text
+ // for >>. Again, text in brackets is omitted if the value
+ // being formatted is an even multiple of the rule's divisor
+ // (in this case, an even multiple of 100)
+ + " 100: << hundred[ >>];\n"
+ // The rules for the higher numbers work the same way as the
+ // rule for 100: Again, the << and >> tokens depend on the
+ // rule's divisor, which for all these rules is also the rule's
+ // base value. To group by thousand, we simply don't have any
+ // rules between 1,000 and 1,000,000.
+ + " 1000: << thousand[ >>];\n"
+ + " 1,000,000: << million[ >>];\n"
+ + " 1,000,000,000: << billion[ >>];\n"
+ + " 1,000,000,000,000: << trillion[ >>];\n"
+ // overflow rule. This rule specifies that values of a
+ // quadrillion or more are shown in numerals rather than words.
+ // The == token means to format (with new rules) the value
+ // being formatted by this rule and place the result where
+ // the == is. The #,##0 inside the == signs is a
+ // DecimalFormat pattern. It specifies that the value should
+ // be formatted with a DecimalFormat object, and that it
+ // should be formatted with no decimal places, at least one
+ // digit, and a thousands separator.
+ + " 1,000,000,000,000,000: =#,##0=;\n"
+
+ // This rule set formats numbers between 1,000 and 9,999 somewhat
+ // differently: If the hundreds digit is not zero, the first two
+ // digits are treated as a number of hundreds. For example, 2,197
+ // would come out as "twenty-one hundred ninety-seven."
+ + "%alt-teens:\n"
+ // just use %simplified to format values below 1,000
+ + " =%simplified=;\n"
+ // values between 1,000 and 9,999 are delegated to %%alt-hundreds
+ // for formatting. The > after "1000" decreases the exponent
+ // of the rule's radix by one, causing the rule's divisor
+ // to be 100 instead of 1,000. This causes the first TWO
+ // digits of the number, instead of just the first digit,
+ // to be sent to %%alt-hundreds
+ + " 1000>: <%%alt-hundreds<[ >>];\n"
+ // for values of 10,000 and more, we again just use %simplified
+ + " 10,000: =%simplified=;\n"
+ // This rule set uses some obscure voodoo of the description language
+ // to format the first two digits of a value in the thousands.
+ // The rule at 10 formats the first two digits as a multiple of 1,000
+ // and the rule at 11 formats the first two digits as a multiple of
+ // 100. This works because of something known as the "rollback rule":
+ // if the rule applicable to the value being formatted has two
+ // substitutions, the value being formatted is an even multiple of
+ // the rule's divisor, and the rule's base value ISN'T an even multiple
+ // if the rule's divisor, then the rule that precedes this one in the
+ // list is used instead. (The [] notation is implemented internally
+ // using this notation: a rule containing [] is split into two rules,
+ // and the right one is chosen using the rollback rule.) In this case,
+ // it means that if the first two digits are an even multiple of 10,
+ // they're formatted with the 10 rule (containing "thousand"), and if
+ // they're not, they're formatted with the 11 rule (containing
+ // "hundred"). %%empty is a hack to cause the rollback rule to be
+ // invoked: it makes the 11 rule have two substitutions, even though
+ // the second substitution (calling %%empty) doesn't actually do
+ // anything.
+ + "%%alt-hundreds:\n"
+ + " 0: SHOULD NEVER GET HERE!;\n"
+ + " 10: <%simplified< thousand;\n"
+ + " 11: =%simplified= hundred>%%empty>;\n"
+ + "%%empty:\n"
+ + " 0:;"
+
+ // this rule set is the same as %simplified, except that it formats
+ // the value as an ordinal number: 234 is formatted as "two hundred
+ // thirty-fourth". Notice the calls to ^simplified: we have to
+ // call %simplified to avoid getting "second hundred thirty-fourth."
+ + "%ordinal:\n"
+ + " zeroth; first; second; third; fourth; fifth; sixth; seventh;\n"
+ + " eighth; ninth;\n"
+ + " tenth; eleventh; twelfth; thirteenth; fourteenth;\n"
+ + " fifteenth; sixteenth; seventeenth; eighteenth;\n"
+ + " nineteenth;\n"
+ + " twentieth; twenty->>;\n"
+ + " 30: thirtieth; thirty->>;\n"
+ + " 40: fortieth; forty->>;\n"
+ + " 50: fiftieth; fifty->>;\n"
+ + " 60: sixtieth; sixty->>;\n"
+ + " 70: seventieth; seventy->>;\n"
+ + " 80: eightieth; eighty->>;\n"
+ + " 90: ninetieth; ninety->>;\n"
+ + " 100: <%simplified< hundredth; <%simplified< hundred >>;\n"
+ + " 1000: <%simplified< thousandth; <%simplified< thousand >>;\n"
+ + " 1,000,000: <%simplified< millionth; <%simplified< million >>;\n"
+ + " 1,000,000,000: <%simplified< billionth;\n"
+ + " <%simplified< billion >>;\n"
+ + " 1,000,000,000,000: <%simplified< trillionth;\n"
+ + " <%simplified< trillion >>;\n"
+ + " 1,000,000,000,000,000: =#,##0=;"
+
+ // %default is a more elaborate form of %simplified; It is basically
+ // the same, except that it introduces "and" before the ones digit
+ // when appropriate (basically, between the tens and ones digits) and
+ // separates the thousands groups with commas in values over 100,000.
+ + "%default:\n"
+ // negative-number and fraction rules. These are the same
+ // as those for %simplified, but ave to be stated here too
+ // because this is an entry point
+ + " -x: minus >>;\n"
+ + " x.x: << point >>;\n"
+ // just use %simplified for values below 100
+ + " =%simplified=;\n"
+ // for values from 100 to 9,999 use %%and to decide whether or
+ // not to interpose the "and"
+ + " 100: << hundred[ >%%and>];\n"
+ + " 1000: << thousand[ >%%and>];\n"
+ // for values of 100,000 and up, use %%commas to interpose the
+ // commas in the right places (and also to interpose the "and")
+ + " 100,000>>: << thousand[>%%commas>];\n"
+ + " 1,000,000: << million[>%%commas>];\n"
+ + " 1,000,000,000: << billion[>%%commas>];\n"
+ + " 1,000,000,000,000: << trillion[>%%commas>];\n"
+ + " 1,000,000,000,000,000: =#,##0=;\n"
+ // if the value passed to this rule set is greater than 100, don't
+ // add the "and"; if it's less than 100, add "and" before the last
+ // digits
+ + "%%and:\n"
+ + " and =%default=;\n"
+ + " 100: =%default=;\n"
+ // this rule set is used to place the commas
+ + "%%commas:\n"
+ // for values below 100, add "and" (the apostrophe at the
+ // beginning is ignored, but causes the space that follows it
+ // to be significant: this is necessary because the rules
+ // calling %%commas don't put a space before it)
+ + " ' and =%default=;\n"
+ // put a comma after the thousands (or whatever preceded the
+ // hundreds)
+ + " 100: , =%default=;\n"
+ // put a comma after the millions (or whatever precedes the
+ // thousands)
+ + " 1000: , <%default< thousand, >%default>;\n"
+ // and so on...
+ + " 1,000,000: , =%default=;"
+ // %%lenient-parse isn't really a set of number formatting rules;
+ // it's a set of collation rules. Lenient-parse mode uses a Collator
+ // object to compare fragments of the text being parsed to the text
+ // in the rules, allowing more leeway in the matching text. This set
+ // of rules tells the formatter to ignore commas when parsing (it
+ // already ignores spaces, which is why we refer to the space; it also
+ // ignores hyphens, making "twenty one" and "twenty-one" parse
+ // identically)
+ + "%%lenient-parse:\n"
+ + " & ' ' , ',' ;\n";
+
+ /**
+ * Spellout rules for U.K. English. U.K. English has one significant
+ * difference from U.S. English: the names for values of 1,000,000,000
+ * and higher. In American English, each successive "-illion" is 1,000
+ * times greater than the preceding one: 1,000,000,000 is "one billion"
+ * and 1,000,000,000,000 is "one trillion." In British English, each
+ * successive "-illion" is one million times greater than the one before:
+ * "one billion" is 1,000,000,000,000 (or what Americans would call a
+ * "trillion"), and "one trillion" is 1,000,000,000,000,000,000.
+ * 1,000,000,000 in British English is "one thousand million." (This
+ * value is sometimes called a "milliard," but this word seems to have
+ * fallen into disuse.)
+ */
+ public static final String ukEnglish =
+ "%simplified:\n"
+ + " -x: minus >>;\n"
+ + " x.x: << point >>;\n"
+ + " zero; one; two; three; four; five; six; seven; eight; nine;\n"
+ + " ten; eleven; twelve; thirteen; fourteen; fifteen; sixteen;\n"
+ + " seventeen; eighteen; nineteen;\n"
+ + " 20: twenty[->>];\n"
+ + " 30: thirty[->>];\n"
+ + " 40: forty[->>];\n"
+ + " 50: fifty[->>];\n"
+ + " 60: sixty[->>];\n"
+ + " 70: seventy[->>];\n"
+ + " 80: eighty[->>];\n"
+ + " 90: ninety[->>];\n"
+ + " 100: << hundred[ >>];\n"
+ + " 1000: << thousand[ >>];\n"
+ + " 1,000,000: << million[ >>];\n"
+ + " 1,000,000,000,000: << billion[ >>];\n"
+ + " 1,000,000,000,000,000: =#,##0=;\n"
+ + "%alt-teens:\n"
+ + " =%simplified=;\n"
+ + " 1000>: <%%alt-hundreds<[ >>];\n"
+ + " 10,000: =%simplified=;\n"
+ + " 1,000,000: << million[ >%simplified>];\n"
+ + " 1,000,000,000,000: << billion[ >%simplified>];\n"
+ + " 1,000,000,000,000,000: =#,##0=;\n"
+ + "%%alt-hundreds:\n"
+ + " 0: SHOULD NEVER GET HERE!;\n"
+ + " 10: <%simplified< thousand;\n"
+ + " 11: =%simplified= hundred>%%empty>;\n"
+ + "%%empty:\n"
+ + " 0:;"
+ + "%ordinal:\n"
+ + " zeroth; first; second; third; fourth; fifth; sixth; seventh;\n"
+ + " eighth; ninth;\n"
+ + " tenth; eleventh; twelfth; thirteenth; fourteenth;\n"
+ + " fifteenth; sixteenth; seventeenth; eighteenth;\n"
+ + " nineteenth;\n"
+ + " twentieth; twenty->>;\n"
+ + " 30: thirtieth; thirty->>;\n"
+ + " 40: fortieth; forty->>;\n"
+ + " 50: fiftieth; fifty->>;\n"
+ + " 60: sixtieth; sixty->>;\n"
+ + " 70: seventieth; seventy->>;\n"
+ + " 80: eightieth; eighty->>;\n"
+ + " 90: ninetieth; ninety->>;\n"
+ + " 100: <%simplified< hundredth; <%simplified< hundred >>;\n"
+ + " 1000: <%simplified< thousandth; <%simplified< thousand >>;\n"
+ + " 1,000,000: <%simplified< millionth; <%simplified< million >>;\n"
+ + " 1,000,000,000,000: <%simplified< billionth;\n"
+ + " <%simplified< billion >>;\n"
+ + " 1,000,000,000,000,000: =#,##0=;"
+ + "%default:\n"
+ + " -x: minus >>;\n"
+ + " x.x: << point >>;\n"
+ + " =%simplified=;\n"
+ + " 100: << hundred[ >%%and>];\n"
+ + " 1000: << thousand[ >%%and>];\n"
+ + " 100,000>>: << thousand[>%%commas>];\n"
+ + " 1,000,000: << million[>%%commas>];\n"
+ + " 1,000,000,000,000: << billion[>%%commas>];\n"
+ + " 1,000,000,000,000,000: =#,##0=;\n"
+ + "%%and:\n"
+ + " and =%default=;\n"
+ + " 100: =%default=;\n"
+ + "%%commas:\n"
+ + " ' and =%default=;\n"
+ + " 100: , =%default=;\n"
+ + " 1000: , <%default< thousand, >%default>;\n"
+ + " 1,000,000: , =%default=;"
+ + "%%lenient-parse:\n"
+ + " & ' ' , ',' ;\n";
+ // Could someone please correct me if I'm wrong about "milliard" falling
+ // into disuse, or have missed any other details of how large numbers
+ // are rendered. Also, could someone please provide me with information
+ // on which other English-speaking countries use which system? Right now,
+ // I'm assuming that the U.S. system is used in Canada and that all the
+ // other English-speaking countries follow the British system. Can
+ // someone out there confirm this?
+
+ /**
+ * Spellout rules for Spanish. The Spanish rules are quite similar to
+ * the English rules, but there are some important differences:
+ * First, we have to provide separate rules for most of the twenties
+ * because the ones digit frequently picks up an accent mark that it
+ * doesn't have when standing alone. Second, each multiple of 100 has
+ * to be specified separately because the multiplier on 100 very often
+ * changes form in the contraction: 500 is "quinientos," not
+ * "cincocientos." In addition, the word for 100 is "cien" when
+ * standing alone, but changes to "ciento" when followed by more digits.
+ * There also some other differences.
+ */
+ public static final String spanish =
+ // negative-number and fraction rules
+ "-x: menos >>;\n"
+ + "x.x: << punto >>;\n"
+ // words for values from 0 to 19
+ + "cero; uno; dos; tres; cuatro; cinco; seis; siete; ocho; nueve;\n"
+ + "diez; once; doce; trece; catorce; quince; diecis\u00e9is;\n"
+ + " diecisiete; dieciocho; diecinueve;\n"
+ // words for values from 20 to 29 (necessary because the ones digit
+ // often picks up an accent mark it doesn't have when standing alone)
+ + "veinte; veintiuno; veintid\u00f3s; veintitr\u00e9s; veinticuatro;\n"
+ + " veinticinco; veintis\u00e9is; veintisiete; veintiocho;\n"
+ + " veintinueve;\n"
+ // words for multiples of 10 (notice that the tens digit is separated
+ // from the ones digit by the word "y".)
+ + "30: treinta[ y >>];\n"
+ + "40: cuarenta[ y >>];\n"
+ + "50: cincuenta[ y >>];\n"
+ + "60: sesenta[ y >>];\n"
+ + "70: setenta[ y >>];\n"
+ + "80: ochenta[ y >>];\n"
+ + "90: noventa[ y >>];\n"
+ // 100 by itself is "cien," but 100 followed by something is "cineto"
+ + "100: cien;\n"
+ + "101: ciento >>;\n"
+ // words for multiples of 100 (must be stated because they're
+ // rarely simple concatenations)
+ + "200: doscientos[ >>];\n"
+ + "300: trescientos[ >>];\n"
+ + "400: cuatrocientos[ >>];\n"
+ + "500: quinientos[ >>];\n"
+ + "600: seiscientos[ >>];\n"
+ + "700: setecientos[ >>];\n"
+ + "800: ochocientos[ >>];\n"
+ + "900: novecientos[ >>];\n"
+ // for 1,000, the multiplier on "mil" is omitted: 2,000 is "dos mil,"
+ // but 1,000 is just "mil."
+ + "1000: mil[ >>];\n"
+ + "2000: << mil[ >>];\n"
+ // 1,000,000 is "un millon," not "uno millon"
+ + "1,000,000: un mill\u00f3n[ >>];\n"
+ + "2,000,000: << mill\u00f3n[ >>];\n"
+ // overflow rule
+ + "1,000,000,000: =#,##0= (incomplete data);";
+ // The Spanish rules are incomplete. I'm missing information on negative
+ // numbers and numbers with fractional parts. I also don't have
+ // information on numbers higher than the millions
+
+ /**
+ * Spellout rules for French. French adds some interesting quirks of its
+ * own: 1) The word "et" is interposed between the tens and ones digits,
+ * but only if the ones digit if 1: 20 is "vingt," and 2 is "vingt-deux,"
+ * but 21 is "vingt-et-un." 2) There are no words for 70, 80, or 90.
+ * "quatre-vingts" ("four twenties") is used for 80, and values proceed
+ * by score from 60 to 99 (e.g., 73 is "soixante-treize" ["sixty-thirteen"]).
+ * Numbers from 1,100 to 1,199 are rendered as hundreds rather than
+ * thousands: 1,100 is "onze cents" ("eleven hundred"), rather than
+ * "mille cent" ("one thousand one hundred")
+ */
+ public static final String french =
+ // the main rule set
+ "%main:\n"
+ // negative-number and fraction rules
+ + " -x: moins >>;\n"
+ + " x.x: << virgule >>;\n"
+ // words for numbers from 0 to 10
+ + " z\u00e9ro; un; deux; trois; quatre; cinq; six; sept; huit; neuf;\n"
+ + " dix; onze; douze; treize; quatorze; quinze; seize;\n"
+ + " dix-sept; dix-huit; dix-neuf;\n"
+ // ords for the multiples of 10: %%alt-ones inserts "et"
+ // when needed
+ + " 20: vingt[->%%alt-ones>];\n"
+ + " 30: trente[->%%alt-ones>];\n"
+ + " 40: quarante[->%%alt-ones>];\n"
+ + " 50: cinquante[->%%alt-ones>];\n"
+ // rule for 60. The /20 causes this rule's multiplier to be
+ // 20 rather than 10, allowinhg us to recurse for all values
+ // from 60 to 79...
+ + " 60/20: soixante[->%%alt-ones>];\n"
+ // ...except for 71, which must be special-cased
+ + " 71: soixante et onze;\n"
+ // at 72, we have to repeat the rule for 60 to get us to 79
+ + " 72/20: soixante->%%alt-ones>;\n"
+ // at 80, we state a new rule with the phrase for 80. Since
+ // it changes form when there's a ones digit, we need a second
+ // rule at 81. This rule also includes "/20," allowing it to
+ // be used correctly for all values up to 99
+ + " 80: quatre-vingts; 81/20: quatre-vingt->>;\n"
+ // "cent" becomes plural when preceded by a multiplier, and
+ // the multiplier is omitted from the singular form
+ + " 100: cent[ >>];\n"
+ + " 200: << cents[ >>];\n"
+ + " 1000: mille[ >>];\n"
+ // values from 1,100 to 1,199 are rendered as "onze cents..."
+ // instead of "mille cent..." The > after "1000" decreases
+ // the rule's exponent, causing its multiplier to be 100 instead
+ // of 1,000. This prevents us from getting "onze cents cent
+ // vingt-deux" ("eleven hundred one hundred twenty-two").
+ + " 1100>: onze cents[ >>];\n"
+ // at 1,200, we go back to formating in thousands, so we
+ // repeat the rule for 1,000
+ + " 1200: mille >>;\n"
+ // at 2,000, the multiplier is added
+ + " 2000: << mille[ >>];\n"
+ + " 1,000,000: << million[ >>];\n"
+ + " 1,000,000,000: << milliarde[ >>];\n"
+ + " 1,000,000,000,000: << billion[ >>];\n"
+ + " 1,000,000,000,000,000: =#,##0=;\n"
+ // %%alt-ones is used to insert "et" when the ones digit is 1
+ + "%%alt-ones:\n"
+ + " ; et-un; =%main=;";
+
+ /**
+ * Spellout rules for Swiss French. Swiss French differs from French French
+ * in that it does have words for 70, 80, and 90. This rule set shows them,
+ * and is simpler as a result.
+ */
+ public static final String swissFrench =
+ "%main:\n"
+ + " -x: moins >>;\n"
+ + " x.x: << virgule >>;\n"
+ + " z\u00e9ro; un; deux; trois; quatre; cinq; six; sept; huit; neuf;\n"
+ + " dix; onze; douze; treize; quatorze; quinze; seize;\n"
+ + " dix-sept; dix-huit; dix-neuf;\n"
+ + " 20: vingt[->%%alt-ones>];\n"
+ + " 30: trente[->%%alt-ones>];\n"
+ + " 40: quarante[->%%alt-ones>];\n"
+ + " 50: cinquante[->%%alt-ones>];\n"
+ + " 60: soixante[->%%alt-ones>];\n"
+ // notice new words for 70, 80, and 90
+ + " 70: septante[->%%alt-ones>];\n"
+ + " 80: octante[->%%alt-ones>];\n"
+ + " 90: nonante[->%%alt-ones>];\n"
+ + " 100: cent[ >>];\n"
+ + " 200: << cents[ >>];\n"
+ + " 1000: mille[ >>];\n"
+ + " 1100>: onze cents[ >>];\n"
+ + " 1200: mille >>;\n"
+ + " 2000: << mille[ >>];\n"
+ + " 1,000,000: << million[ >>];\n"
+ + " 1,000,000,000: << milliarde[ >>];\n"
+ + " 1,000,000,000,000: << billion[ >>];\n"
+ + " 1,000,000,000,000,000: =#,##0=;\n"
+ + "%%alt-ones:\n"
+ + " ; et-un; =%main=;";
+ // I'm not 100% sure about Swiss French. Is
+ // this correct? Is "onze cents" commonly used for 1,100 in both France
+ // and Switzerland? Can someone fill me in on the rules for the other
+ // French-speaking countries? I've heard conflicting opinions on which
+ // version is used in Canada, and I understand there's an alternate set
+ // of words for 70, 80, and 90 that is used somewhere, but I don't know
+ // what those words are or where they're used.
+
+ /**
+ * Spellout rules for German. German also adds some interesting
+ * characteristics. For values below 1,000,000, numbers are customarily
+ * written out as a single word. And the ones digit PRECEDES the tens
+ * digit (e.g., 23 is "dreiundzwanzig," not "zwanzigunddrei").
+ */
+ public static final String german =
+ // 1 is "eins" when by itself, but turns into "ein" in most
+ // combinations
+ "%alt-ones:\n"
+ + " null; eins; =%%main=;\n"
+ + "%%main:\n"
+ // words for numbers from 0 to 12. Notice that the values
+ // from 13 to 19 can derived algorithmically, unlike in most
+ // other languages
+ + " null; ein; zwei; drei; vier; f\u00fcnf; sechs; sieben; acht; neun;\n"
+ + " zehn; elf; zw\u00f6lf; >>zehn;\n"
+ // rules for the multiples of 10. Notice that the ones digit
+ // goes on the front
+ + " 20: [>>und]zwanzig;\n"
+ + " 30: [>>und]drei\u00dfig;\n"
+ + " 40: [>>und]vierzig;\n"
+ + " 50: [>>und]f\u00fcnfzig;\n"
+ + " 60: [>>und]sechzig;\n"
+ + " 70: [>>und]siebzig;\n"
+ + " 80: [>>und]achtzig;\n"
+ + " 90: [>>und]neunzig;\n"
+ + " 100: hundert[>%alt-ones>];\n"
+ + " 200: <<hundert[>%alt-ones>];\n"
+ + " 1000: tausend[>%alt-ones>];\n"
+ + " 2000: <<tausend[>%alt-ones>];\n"
+ + " 1,000,000: eine Million[ >%alt-ones>];\n"
+ + " 2,000,000: << Millionen[ >%alt-ones>];\n"
+ + " 1,000,000,000: eine Milliarde[ >%alt-ones>];\n"
+ + " 2,000,000,000: << Milliarden[ >%alt-ones>];\n"
+ + " 1,000,000,000,000: eine Billion[ >%alt-ones>];\n"
+ + " 2,000,000,000,000: << Billionen[ >%alt-ones>];\n"
+ + " 1,000,000,000,000,000: =#,##0=;";
+ // again, I'm not 100% sure of these rules. I think both "hundert" and
+ // "einhundert" are correct or 100, but I'm not sure which is preferable
+ // in situations where this framework is likely to be used. Also, is it
+ // really true that numbers are run together into compound words all the
+ // time? And again, I'm missing information on negative numbers and
+ // decimals.
+
+ /**
+ * Spellout rules for Italian. Like German, most Italian numbers are
+ * written as single words. What makes these rules complicated is the rule
+ * that says that when a word ending in a vowel and a word beginning with
+ * a vowel are combined into a compound, the vowel is dropped from the
+ * end of the first word: 180 is "centottanta," not "centoottanta."
+ * The complexity of this rule set is to produce this behavior.
+ */
+ public static final String italian =
+ // main rule set. Follows the patterns of the preceding rule sets,
+ // except that the final vowel is omitted from words ending in
+ // vowels when they are followed by another word; instead, we have
+ // separate rule sets that are identical to this one, except that
+ // all the words that don't begin with a vowel have a vowel tacked
+ // onto them at the front. A word ending in a vowel calls a
+ // substitution that will supply that vowel, unless that vowel is to
+ // be elided.
+ "%main:\n"
+ + " -x: meno >>;\n"
+ + " x.x: << virgola >>;\n"
+ + " zero; uno; due; tre; quattro; cinque; sei; sette; otto;\n"
+ + " nove;\n"
+ + " dieci; undici; dodici; tredici; quattordici; quindici; sedici;\n"
+ + " diciasette; diciotto; diciannove;\n"
+ + " 20: venti; vent>%%with-i>;\n"
+ + " 30: trenta; trent>%%with-i>;\n"
+ + " 40: quaranta; quarant>%%with-a>;\n"
+ + " 50: cinquanta; cinquant>%%with-a>;\n"
+ + " 60: sessanta; sessant>%%with-a>;\n"
+ + " 70: settanta; settant>%%with-a>;\n"
+ + " 80: ottanta; ottant>%%with-a>;\n"
+ + " 90: novanta; novant>%%with-a>;\n"
+ + " 100: cento; cent[>%%with-o>];\n"
+ + " 200: <<cento; <<cent[>%%with-o>];\n"
+ + " 1000: mille; mill[>%%with-i>];\n"
+ + " 2000: <<mila; <<mil[>%%with-a>];\n"
+ + " 100,000>>: <<mila[ >>];\n"
+ + " 1,000,000: =#,##0= (incomplete data);\n"
+ + "%%with-a:\n"
+ + " azero; uno; adue; atre; aquattro; acinque; asei; asette; otto;\n"
+ + " anove;\n"
+ + " adieci; undici; adodici; atredici; aquattordici; aquindici; asedici;\n"
+ + " adiciasette; adiciotto; adiciannove;\n"
+ + " 20: aventi; avent>%%with-i>;\n"
+ + " 30: atrenta; atrent>%%with-i>;\n"
+ + " 40: aquaranta; aquarant>%%with-a>;\n"
+ + " 50: acinquanta; acinquant>%%with-a>;\n"
+ + " 60: asessanta; asessant>%%with-a>;\n"
+ + " 70: asettanta; asettant>%%with-a>;\n"
+ + " 80: ottanta; ottant>%%with-a>;\n"
+ + " 90: anovanta; anovant>%%with-a>;\n"
+ + " 100: acento; acent[>%%with-o>];\n"
+ + " 200: <%%with-a<cento; <%%with-a<cent[>%%with-o>];\n"
+ + " 1000: amille; amill[>%%with-i>];\n"
+ + " 2000: <%%with-a<mila; <%%with-a<mil[>%%with-a>];\n"
+ + " 100,000: =%main=;\n"
+ + "%%with-i:\n"
+ + " izero; uno; idue; itre; iquattro; icinque; isei; isette; otto;\n"
+ + " inove;\n"
+ + " idieci; undici; idodici; itredici; iquattordici; iquindici; isedici;\n"
+ + " idiciasette; idiciotto; idiciannove;\n"
+ + " 20: iventi; ivent>%%with-i>;\n"
+ + " 30: itrenta; itrent>%%with-i>;\n"
+ + " 40: iquaranta; iquarant>%%with-a>;\n"
+ + " 50: icinquanta; icinquant>%%with-a>;\n"
+ + " 60: isessanta; isessant>%%with-a>;\n"
+ + " 70: isettanta; isettant>%%with-a>;\n"
+ + " 80: ottanta; ottant>%%with-a>;\n"
+ + " 90: inovanta; inovant>%%with-a>;\n"
+ + " 100: icento; icent[>%%with-o>];\n"
+ + " 200: <%%with-i<cento; <%%with-i<cent[>%%with-o>];\n"
+ + " 1000: imille; imill[>%%with-i>];\n"
+ + " 2000: <%%with-i<mila; <%%with-i<mil[>%%with-a>];\n"
+ + " 100,000: =%main=;\n"
+ + "%%with-o:\n"
+ + " ozero; uno; odue; otre; oquattro; ocinque; osei; osette; otto;\n"
+ + " onove;\n"
+ + " odieci; undici; ododici; otredici; oquattordici; oquindici; osedici;\n"
+ + " odiciasette; odiciotto; odiciannove;\n"
+ + " 20: oventi; ovent>%%with-i>;\n"
+ + " 30: otrenta; otrent>%%with-i>;\n"
+ + " 40: oquaranta; oquarant>%%with-a>;\n"
+ + " 50: ocinquanta; ocinquant>%%with-a>;\n"
+ + " 60: osessanta; osessant>%%with-a>;\n"
+ + " 70: osettanta; osettant>%%with-a>;\n"
+ + " 80: ottanta; ottant>%%with-a>;\n"
+ + " 90: onovanta; onovant>%%with-a>;\n"
+ + " 100: ocento; ocent[>%%with-o>];\n"
+ + " 200: <%%with-o<cento; <%%with-o<cent[>%%with-o>];\n"
+ + " 1000: omille; omill[>%%with-i>];\n"
+ + " 2000: <%%with-o<mila; <%%with-o<mil[>%%with-a>];\n"
+ + " 100,000: =%main=;\n";
+ // Can someone confirm that I did the vowel-eliding thing right? I'm
+ // not 100% sure I'm doing it in all the right places, or completely
+ // correctly. Also, I don't have information for negatives and decimals,
+ // and I lack words fror values from 1,000,000 on up.
+
+ /**
+ * Spellout rules for Swedish.
+ */
+ public static final String swedish =
+ "noll; ett; tv\u00e5; tre; fyra; fem; sex; sjo; \u00e5tta; nio;\n"
+ + "tio; elva; tolv; tretton; fjorton; femton; sexton; sjutton; arton; nitton;\n"
+ + "20: tjugo[>>];\n"
+ + "30: trettio[>>];\n"
+ + "40: fyrtio[>>];\n"
+ + "50: femtio[>>];\n"
+ + "60: sextio[>>];\n"
+ + "70: sjuttio[>>];\n"
+ + "80: \u00e5ttio[>>];\n"
+ + "90: nittio[>>];\n"
+ + "100: hundra[>>];\n"
+ + "200: <<hundra[>>];\n"
+ + "1000: tusen[ >>];\n"
+ + "2000: << tusen[ >>];\n"
+ + "1,000,000: en miljon[ >>];\n"
+ + "2,000,000: << miljon[ >>];\n"
+ + "1,000,000,000: en miljard[ >>];\n"
+ + "2,000,000,000: << miljard[ >>];\n"
+ + "1,000,000,000,000: en biljon[ >>];\n"
+ + "2,000,000,000,000: << biljon[ >>];\n"
+ + "1,000,000,000,000,000: =#,##0=";
+ // can someone supply me with information on negatives and decimals?
+
+ /**
+ * Spellout rules for Dutch. Notice that in Dutch, as in German,
+ * the ones digit precedes the tens digit.
+ */
+ public static final String dutch =
+ " -x: min >>;\n"
+ + "x.x: << komma >>;\n"
+ + "(zero?); een; twee; drie; vier; vijf; zes; zeven; acht; negen;\n"
+ + "tien; elf; twaalf; dertien; veertien; vijftien; zestien;\n"
+ + "zeventien; achtien; negentien;\n"
+ + "20: [>> en ]twintig;\n"
+ + "30: [>> en ]dertig;\n"
+ + "40: [>> en ]veertig;\n"
+ + "50: [>> en ]vijftig;\n"
+ + "60: [>> en ]zestig;\n"
+ + "70: [>> en ]zeventig;\n"
+ + "80: [>> en ]tachtig;\n"
+ + "90: [>> en ]negentig;\n"
+ + "100: << honderd[ >>];\n"
+ + "1000: << duizend[ >>];\n"
+ + "1,000,000: << miljoen[ >>];\n"
+ + "1,000,000,000: << biljoen[ >>];\n"
+ + "1,000,000,000,000: =#,##0=";
+
+ /**
+ * Spellout rules for Japanese. In Japanese, there really isn't any
+ * distinction between a number written out in digits and a number
+ * written out in words: the ideographic characters are both digits
+ * and words. This rule set provides two variants: %traditional
+ * uses the traditional CJK numerals (which are also used in China
+ * and Korea). %financial uses alternate ideographs for many numbers
+ * that are harder to alter than the traditional numerals (one could
+ * fairly easily change a one to
+ * a three just by adding two strokes, for example). This is also done in
+ * the other countries using Chinese idographs, but different ideographs
+ * are used in those places.
+ */
+ public static final String japanese =
+ "%financial:\n"
+ + " \u96f6; \u58f1; \u5f10; \u53c2; \u56db; \u4f0d; \u516d; \u4e03; \u516b; \u4e5d;\n"
+ + " \u62fe[>>];\n"
+ + " 20: <<\u62fe[>>];\n"
+ + " 100: <<\u767e[>>];\n"
+ + " 1000: <<\u5343[>>];\n"
+ + " 10,000: <<\u4e07[>>];\n"
+ + " 100,000,000: <<\u5104[>>];\n"
+ + " 1,000,000,000,000: <<\u5146[>>];\n"
+ + " 10,000,000,000,000,000: =#,##0=;\n"
+ + "%traditional:\n"
+ + " \u96f6; \u4e00; \u4e8c; \u4e09; \u56db; \u4e94; \u516d; \u4e03; \u516b; \u4e5d;\n"
+ + " \u5341[>>];\n"
+ + " 20: <<\u5341[>>];\n"
+ + " 100: <<\u767e[>>];\n"
+ + " 1000: <<\u5343[>>];\n"
+ + " 10,000: <<\u4e07[>>];\n"
+ + " 100,000,000: <<\u5104[>>];\n"
+ + " 1,000,000,000,000: <<\u5146[>>];\n"
+ + " 10,000,000,000,000,000: =#,##0=;";
+ // Can someone supply me with the right fraud-proof ideographs for
+ // Simplified and Traditional Chinese, and for Korean? Can someone
+ // supply me with information on negatives and decimals?
+
+ /**
+ * Spellout rules for Greek. Again in Greek we have to supply the words
+ * for the multiples of 100 because they can't be derived algorithmically.
+ * Also, the tens dgit changes form when followed by a ones digit: an
+ * accent mark disappears from the tens digit and moves to the ones digit.
+ * Therefore, instead of using the [] notation, we actually have to use
+ * two separate rules for each multiple of 10 to show the two forms of
+ * the word.
+ */
+ public static final String greek =
+ "zero (incomplete data); \u03ad\u03bd\u03b1; \u03b4\u03cd\u03bf; \u03b4\u03c1\u03af\u03b1; "
+ + "\u03c4\u03ad\u03c3\u03c3\u03b5\u03c1\u03b1; \u03c0\u03ad\u03bd\u03c4\u03b5; "
+ + "\u03ad\u03be\u03b9; \u03b5\u03c0\u03c4\u03ac; \u03bf\u03ba\u03c4\u03ce; "
+ + "\u03b5\u03bd\u03bd\u03ad\u03b1;\n"
+ + "10: \u03b4\u03ad\u03ba\u03b1; "
+ + "\u03ad\u03bd\u03b4\u03b5\u03ba\u03b1; \u03b4\u03ce\u03b4\u03b5\u03ba\u03b1; "
+ + "\u03b4\u03b5\u03ba\u03b1>>;\n"
+ + "20: \u03b5\u03af\u03ba\u03bf\u03c3\u03b9; \u03b5\u03b9\u03ba\u03bf\u03c3\u03b9>>;\n"
+ + "30: \u03c4\u03c1\u03b9\u03ac\u03bd\u03c4\u03b1; \u03c4\u03c1\u03b9\u03b1\u03bd\u03c4\u03b1>>;\n"
+ + "40: \u03c3\u03b1\u03c1\u03ac\u03bd\u03c4\u03b1; \u03c3\u03b1\u03c1\u03b1\u03bd\u03c4\u03b1>>;\n"
+ + "50: \u03c0\u03b5\u03bd\u03ae\u03bd\u03c4\u03b1; \u03c0\u03b5\u03bd\u03b7\u03bd\u03c4\u03b1>>;\n"
+ + "60: \u03b5\u03be\u03ae\u03bd\u03c4\u03b1; \u03b5\u03be\u03b7\u03bd\u03c4\u03b1>>;\n"
+ + "70: \u03b5\u03b2\u03b4\u03bf\u03bc\u03ae\u03bd\u03c4\u03b1; "
+ + "\u03b5\u03b2\u03b4\u03bf\u03bc\u03b7\u03bd\u03c4\u03b1>>;\n"
+ + "80: \u03bf\u03b3\u03b4\u03cc\u03bd\u03c4\u03b1; \u03bf\u03b3\u03b4\u03bf\u03bd\u03c4\u03b1>>;\n"
+ + "90: \u03b5\u03bd\u03bd\u03b5\u03bd\u03ae\u03bd\u03c4\u03b1; "
+ + "\u03b5\u03bd\u03bd\u03b5\u03bd\u03b7\u03bd\u03c4\u03b1>>;\n"
+ + "100: \u03b5\u03ba\u03b1\u03c4\u03cc[\u03bd >>];\n"
+ + "200: \u03b4\u03b9\u03b1\u03ba\u03cc\u03c3\u03b9\u03b1[ >>];\n"
+ + "300: \u03c4\u03c1\u03b9\u03b1\u03ba\u03cc\u03c3\u03b9\u03b1[ >>];\n"
+ + "400: \u03c4\u03b5\u03c4\u03c1\u03b1\u03ba\u03cc\u03c3\u03b9\u03b1[ >>];\n"
+ + "500: \u03c0\u03b5\u03bd\u03c4\u03b1\u03ba\u03cc\u03c3\u03b9\u03b1[ >>];\n"
+ + "600: \u03b5\u03be\u03b1\u03ba\u03cc\u03c3\u03b9\u03b1[ >>];\n"
+ + "700: \u03b5\u03c0\u03c4\u03b1\u03ba\u03cc\u03c3\u03b9\u03b1[ >>];\n"
+ + "800: \u03bf\u03ba\u03c4\u03b1\u03ba\u03cc\u03c3\u03b9\u03b1[ >>];\n"
+ + "900: \u03b5\u03bd\u03bd\u03b9\u03b1\u03ba\u03cc\u03c3\u03b9\u03b1[ >>];\n"
+ + "1000: \u03c7\u03af\u03bb\u03b9\u03b1[ >>];\n"
+ + "2000: << \u03c7\u03af\u03bb\u03b9\u03b1[ >>];\n"
+ + "1,000,000: << \u03b5\u03ba\u03b1\u03c4\u03bf\u03bc\u03bc\u03b9\u03cc\u03c1\u03b9\u03bf[ >>];\n"
+ + "1,000,000,000: << \u03b4\u03b9\u03c3\u03b5\u03ba\u03b1\u03c4\u03bf\u03bc\u03bc\u03b9\u03cc\u03c1\u03b9\u03bf[ >>];\n"
+ + "1,000,000,000,000: =#,##0=";
+ // Can someone supply me with information on negatives and decimals?
+ // I'm also missing the word for zero. Can someone clue me in?
+
+ /**
+ * Spellout rules for Russian.
+ */
+ public static final String russian =
+ "\u043d\u043e\u043b\u044c; \u043e\u0434\u0438\u043d; \u0434\u0432\u0430; \u0442\u0440\u0438; "
+ + "\u0447\u0435\u0442\u044b\u0440\u0435; \u043f\u044f\u0442; \u0448\u0435\u0441\u0442; "
+ + "\u0441\u0435\u043c\u044c; \u0432\u043e\u0441\u0435\u043c\u044c; \u0434\u0435\u0432\u044f\u0442;\n"
+ + "10: \u0434\u0435\u0441\u044f\u0442; "
+ + "\u043e\u0434\u0438\u043d\u043d\u0430\u0434\u0446\u0430\u0442\u044c;\n"
+ + "\u0434\u0432\u0435\u043d\u043d\u0430\u0434\u0446\u0430\u0442\u044c; "
+ + "\u0442\u0440\u0438\u043d\u0430\u0434\u0446\u0430\u0442\u044c; "
+ + "\u0447\u0435\u0442\u044b\u0440\u043d\u0430\u0434\u0446\u0430\u0442\u044c;\n"
+ + "15: \u043f\u044f\u0442\u043d\u0430\u0434\u0446\u0430\u0442\u044c; "
+ + "\u0448\u0435\u0441\u0442\u043d\u0430\u0434\u0446\u0430\u0442\u044c; "
+ + "\u0441\u0435\u043c\u043d\u0430\u0434\u0446\u0430\u0442\u044c; "
+ + "\u0432\u043e\u0441\u0435\u043c\u043d\u0430\u0434\u0446\u0430\u0442\u044c; "
+ + "\u0434\u0435\u0432\u044f\u0442\u043d\u0430\u0434\u0446\u0430\u0442\u044c;\n"
+ + "20: \u0434\u0432\u0430\u0434\u0446\u0430\u0442\u044c[ >>];\n"
+ + "30: \u0442\u0440\u043b\u0434\u0446\u0430\u0442\u044c[ >>];\n"
+ + "40: \u0441\u043e\u0440\u043e\u043a[ >>];\n"
+ + "50: \u043f\u044f\u0442\u044c\u0434\u0435\u0441\u044f\u0442[ >>];\n"
+ + "60: \u0448\u0435\u0441\u0442\u044c\u0434\u0435\u0441\u044f\u0442[ >>];\n"
+ + "70: \u0441\u0435\u043c\u044c\u0434\u0435\u0441\u044f\u0442[ >>];\n"
+ + "80: \u0432\u043e\u0441\u0435\u043c\u044c\u0434\u0435\u0441\u044f\u0442[ >>];\n"
+ + "90: \u0434\u0435\u0432\u044f\u043d\u043e\u0441\u0442\u043e[ >>];\n"
+ + "100: \u0441\u0442\u043e[ >>];\n"
+ + "200: << \u0441\u0442\u043e[ >>];\n"
+ + "1000: \u0442\u044b\u0441\u044f\u0447\u0430[ >>];\n"
+ + "2000: << \u0442\u044b\u0441\u044f\u0447\u0430[ >>];\n"
+ + "1,000,000: \u043c\u0438\u043b\u043b\u0438\u043e\u043d[ >>];\n"
+ + "2,000,000: << \u043c\u0438\u043b\u043b\u0438\u043e\u043d[ >>];\n"
+ + "1,000,000,000: =#,##0=;";
+ // Can someone supply me with information on negatives and decimals?
+ // How about words for billions and trillions?
+
+ /**
+ * Spellout rules for Hebrew. Hebrew actually has inflected forms for
+ * most of the lower-order numbers. The masculine forms are shown
+ * here.
+ */
+ public static final String hebrew =
+ "zero (incomplete data); \u05d0\u05d4\u05d3; \u05e9\u05d2\u05d9\u05d9\u05dd; \u05e9\u05dc\u05d5\u05e9\u05d4;\n"
+ + "4: \u05d0\u05d3\u05d1\u05e6\u05d4; \u05d7\u05d2\u05d5\u05d9\u05e9\u05d4; \u05e9\u05e9\u05d4;\n"
+ + "7: \u05e9\u05d1\u05e6\u05d4; \u05e9\u05de\u05d5\u05d2\u05d4; \u05ea\u05e9\u05e6\u05d4;\n"
+ + "10: \u05e6\u05e9\u05d3\u05d4[ >>];\n"
+ + "20: \u05e6\u05e9\u05d3\u05d9\u05dd[ >>];\n"
+ + "30: \u05e9\u05dc\u05d5\u05e9\u05d9\u05dd[ >>];\n"
+ + "40: \u05d0\u05d3\u05d1\u05e6\u05d9\u05dd[ >>];\n"
+ + "50: \u05d7\u05de\u05d9\u05e9\u05d9\u05dd[ >>];\n"
+ + "60: \u05e9\u05e9\u05d9\u05dd[ >>];\n"
+ + "70: \u05e9\u05d1\u05e6\u05d9\u05dd[ >>];\n"
+ + "80: \u05e9\u05de\u05d5\u05d2\u05d9\u05dd[ >>];\n"
+ + "90: \u05ea\u05e9\u05e6\u05d9\u05dd[ >>];\n"
+ + "100: \u05de\u05d0\u05d4[ >>];\n"
+ + "200: << \u05de\u05d0\u05d4[ >>];\n"
+ + "1000: \u05d0\u05dc\u05e3[ >>];\n"
+ + "2000: << \u05d0\u05dc\u05e3[ >>];\n"
+ + "1,000,000: =#,##0= (incomplete data);";
+ // This data is woefully incomplete. Can someone fill me in on the
+ // various inflected forms of the numbers, which seem to be necessary
+ // to do Hebrew correctly? Can somone supply me with data for values
+ // from 1,000,000 on up? What about the word for zero? What about
+ // information on negatives and decimals?
+
+ //========================================================================
+ // Simple examples
+ //========================================================================
+
+ /**
+ * This rule set adds an English ordinal abbreviation to the end of a
+ * number. For example, 2 is formatted as "2nd". Parsing doesn't work with
+ * this rule set. To parse, use DecimalFormat on the numeral.
+ */
+ public static final String ordinal =
+ // this rule set formats the numeral and calls %%abbrev to
+ // supply the abbreviation
+ "%main:\n"
+ + " =#,##0==%%abbrev=;\n"
+ // this rule set supplies the abbreviation
+ + "%%abbrev:\n"
+ // the abbreviations. Everything from 4 to 19 ends in "th"
+ + " th; st; nd; rd; th;\n"
+ // at 20, we begin repeating the cycle every 10 (13 is "13th",
+ // but 23 and 33 are "23rd" and "33rd") We do this by
+ // ignoring all bug the ones digit in selecting the abbreviation
+ + " 20: >>;\n"
+ // at 100, we repeat the whole cycle by considering only the
+ // tens and ones digits in picking an abbreviation
+ + " 100: >>;\n";
+
+ /**
+ * This is a simple message-formatting example. Normally one would
+ * use ChoiceFormat and MessageFormat to do something this simple,
+ * but this shows it could be done with RuleBasedNumberFormat too.
+ * A message-formatting example that might work better with
+ * RuleBasedNumberFormat appears later.
+ */
+ public static final String message1 =
+ // this rule surrounds whatever the other rules produce with the
+ // rest of the sentence
+ "x.0: The search found <<.;\n"
+ // use words for values below 10 (and change to "file" for 1)
+ + "no files; one file; two files; three files; four files; five files;\n"
+ + " six files; seven files; eight files; nine files;\n"
+ // use numerals for values higher than 10
+ + "=#,##0= files;";
+
+ //========================================================================
+ // Fraction handling
+ //
+ // The next few examples show how RuleBasedNumberFormat can be used for
+ // more flexible handling of fractions
+ //========================================================================
+
+ /**
+ * This example formats a number in one of the two styles often used
+ * on checks. %dollars-and-hundredths formats cents as hundredths of
+ * a dollar (23.40 comes out as "twenty-three and 40/100 dollars").
+ * %dollars-and-cents formats in dollars and cents (23.40 comes out as
+ * "twenty-three dollars and forty cents")
+ */
+ public static final String dollarsAndCents =
+ // this rule set formats numbers as dollars and cents
+ "%dollars-and-cents:\n"
+ // if the value is 1 or more, put "xx dollars and yy cents".
+ // the "and y cents" part is suppressed if the value is an
+ // even number of dollars
+ + " x.0: << [and >%%cents>];\n"
+ // if the value is between 0 and 1, put "xx cents"
+ + " 0.x: >%%cents>;\n"
+ // these three rules take care of the singular and plural
+ // forms of "dollar" and use %%main to format the number
+ + " 0: zero dollars; one dollar; =%%main= dollars;\n"
+ // these are the regular U.S. English number spellout rules
+ + "%%main:\n"
+ + " zero; one; two; three; four; five; six; seven; eight; nine;\n"
+ + " ten; eleven; twelve; thirteen; fourteen; fifteen; sixteen;\n"
+ + " seventeen; eighteen; nineteen;\n"
+ + " 20: twenty[->>];\n"
+ + " 30: thirty[->>];\n"
+ + " 40: forty[->>];\n"
+ + " 50: fifty[->>];\n"
+ + " 60: sixty[->>];\n"
+ + " 70: seventy[->>];\n"
+ + " 80: eighty[->>];\n"
+ + " 90: ninety[->>];\n"
+ + " 100: << hundred[ >>];\n"
+ + " 1000: << thousand[ >>];\n"
+ + " 1,000,000: << million[ >>];\n"
+ + " 1,000,000,000: << billion[ >>];\n"
+ + " 1,000,000,000,000: << trillion[ >>];\n"
+ + " 1,000,000,000,000,000: =#,##0=;\n"
+ // this rule takes care of the fractional part of the value. It
+ // multiplies the fractional part of the number being formatted by
+ // 100, formats it with %%main, and then addes the word "cent" or
+ // "cents" to the end. (The text in brackets is omitted if the
+ // numerator of the fraction is 1.)
+ + "%%cents:\n"
+ + " 100: <%%main< cent[s];\n"
+
+ // this rule set formats numbers as dollars and hundredths of dollars
+ + "%dollars-and-hundredths:\n"
+ // this rule takes care of the general shell of the output
+ // string. We always show the cents, even when there aren't
+ // any. Because of this, the word is always "dollars"--
+ // we don't have to worry about the singular form. We use
+ // %%main to format the number of dollars and %%hundredths to
+ // format the number of cents
+ + " x.0: <%%main< and >%%hundredths>/100 dollars;\n"
+ // this rule set formats the cents for %dollars-and-hundredths.
+ // It multiplies the fractional part of the number by 100 and formats
+ // the result using a DecimalFormat ("00" tells the DecimalFormat to
+ // always use two digits, even for numbers under 10)
+ + "%%hundredths:\n"
+ + " 100: <00<;\n";
+
+ /**
+ * This rule set shows the fractional part of the number as a fraction
+ * with a power of 10 as the denominator. Some languages don't spell
+ * out the fractional part of a number as "point one two three," but
+ * always render it as a fraction. If we still want to treat the fractional
+ * part of the number as a decimal, then the fraction's denominator
+ * is always a power of 10. This example does that: 23.125 is formatted
+ * as "twenty-three and one hundred twenty-five thousandths" (as opposed
+ * to "twenty-three point one two five" or "twenty-three and one eighth").
+ */
+ public static final String decimalAsFraction =
+ // the regular U.S. English spellout rules, with one difference
+ "%main:\n"
+ + " -x: minus >>;\n"
+ // the difference. This rule uses %%frac to show the fractional
+ // part of the number. Text in brackets is omitted when the
+ // value is between 0 and 1 (causing 0.3 to come out as "three
+ // tenths" instead of "zero and three tenths").
+ + " x.x: [<< and ]>%%frac>;\n"
+ + " zero; one; two; three; four; five; six; seven; eight; nine;\n"
+ + " ten; eleven; twelve; thirteen; fourteen; fifteen; sixteen;\n"
+ + " seventeen; eighteen; nineteen;\n"
+ + " twenty[->>];\n"
+ + " 30: thirty[->>];\n"
+ + " 40: forty[->>];\n"
+ + " 50: fifty[->>];\n"
+ + " 60: sixty[->>];\n"
+ + " 70: seventy[->>];\n"
+ + " 80: eighty[->>];\n"
+ + " 90: ninety[->>];\n"
+ + " 100: << hundred[ >>];\n"
+ + " 1000: << thousand[ >>];\n"
+ + " 1,000,000: << million[ >>];\n"
+ + " 1,000,000,000: << billion[ >>];\n"
+ + " 1,000,000,000,000: << trillion[ >>];\n"
+ + " 1,000,000,000,000,000: =#,##0=;\n"
+ // the rule set that formats the fractional part of the number.
+ // The rule that is used is the one that, when its baase value is
+ // multiplied by the fractional part of the number being formatted,
+ // produces the result closest to zero. Thus, the base values are
+ // prospective denominators of the fraction. The << marks the place
+ // where the numerator of the fraction (the result of multiplying the
+ // fractional part of the number by the rule's base value) is
+ // placed. Text in brackets is omitted when the numerator is 1, giving
+ // us the singular and plural forms of the words.
+ // [In languages where the singular and plural are completely different
+ // words, the rule can just be stated twice: the second time with
+ // the plural form.]
+ + "%%frac:\n"
+ + " 10: << tenth[s];\n"
+ + " 100: << hundredth[s];\n"
+ + " 1000: << thousandth[s];\n"
+ + " 10,000: << ten-thousandth[s];\n"
+ + " 100,000: << hundred-thousandth[s];\n"
+ + " 1,000,000: << millionth[s];";
+
+ /**
+ * Number with closest fraction. This example formats a value using
+ * numerals, but shows the fractional part as a ratio (fraction) rather
+ * than a decimal. The fraction always has a denominator between 2 and 10.
+ */
+ public static final String closestFraction =
+ "%main:\n"
+ // this rule formats the number if it's 1 or more. It formats
+ // the integral part using a DecimalFormat ("#,##0" puts
+ // thousands separators in the right places) and the fractional
+ // part using %%frac. If there is no fractional part, it
+ // just shows the integral part.
+ + " x.0: <#,##0<[ >%%frac>];\n"
+ // this rule formats the number if it's between 0 and 1. It
+ // shows only the fractional part (0.5 shows up as "1/2," not
+ // "0 1/2")
+ + " 0.x: >%%frac>;\n"
+ // the fraction rule set. This works the same way as the one in the
+ // preceding example: We multiply the fractional part of the number
+ // being formatted by each rule's base value and use the rule that
+ // produces the result closest to 0 (or the first rule that produces 0).
+ // Since we only provide rules for the numbers from 2 to 10, we know
+ // we'll get a fraction with a denominator between 2 and 10.
+ // "<0<" causes the numerator of the fraction to be formatted
+ // using numerals
+ + "%%frac:\n"
+ + " 2: 1/2;\n"
+ + " 3: <0</3;\n"
+ + " 4: <0</4;\n"
+ + " 5: <0</5;\n"
+ + " 6: <0</6;\n"
+ + " 7: <0</7;\n"
+ + " 8: <0</8;\n"
+ + " 9: <0</9;\n"
+ + " 10: <0</10;\n";
+
+ /**
+ * American stock-price formatting. Non-integral stock prices are still
+ * generally shown in eighths or sixteenths of dollars instead of dollars
+ * and cents. This example formats stock prices in this way if possible,
+ * and in dollars and cents if not.
+ */
+ public static final String stock =
+ "%main:\n"
+ // this rule formats the integral part of the number in numerals
+ // and (if necessary) the fractional part using %%frac1
+ + " x.0: <#,##0<[>%%frac1>];\n"
+ // this rule is used for values between 0 and 1 and omits the
+ // integral part
+ + " 0.x: >%%frac2>;\n"
+ // this rule set is used to format the fractional part of the number when
+ // there's an integral part before it (again, we try all denominators
+ // and use the "best" one)
+ + "%%frac1:\n"
+ // for even multiples of 1/4, format the fraction using the
+ // typographer's fractions
+ + " 4: <%%quarters<;\n"
+ // format the value as a number of eighths, sixteenths, or
+ // thirty-seconds, whichever produces the most accurate value.
+ // The apostrophe at the front of these rules is ignored, but
+ // it makes the space that follows it significant. This puts a
+ // space between the value's integral and fractional parts so
+ // you can read it
+ + " 8: ' <0</8;\n"
+ + " 16: ' <0</16;\n"
+ + " 32: ' <0</32;\n"
+ // if we can't reasonably format the number in powers of 2,
+ // then show it as dollars and cents
+ + " 100: .<00<;\n"
+ // this rule set is used when the fractional part of the value stands
+ // alone
+ + "%%frac2:\n"
+ + " 4: <%%quarters<;\n"
+ // for fractions that we can't show using typographer's fractions,
+ // we don't have to put a space before the fraction
+ + " 8: <0</8;\n"
+ + " 16: <0</16;\n"
+ + " 32: <0</32;\n"
+ // but dollars and cents look better with a leading 0
+ + " 100: 0.<00<;\n"
+ // this rule set formats 1/4, 1/2, and 3/4 using typographer's fractions
+ + "%%quarters:\n"
+ + " ; \u00bc; \u00bd; \u00be;\n"
+ // there are the lenient-parse rules. These allow the user to type
+ // "1/4," "1/2," and "3/4" instead of their typographical counterparts
+ // and still have them be understood by the formatter
+ + "%%lenient-parse:\n"
+ + " & '1/4' , \u00bc\n"
+ + " & '1/2' , \u00bd\n"
+ + " & '3/4' , \u00be\n;";
+
+ //========================================================================
+ // Changing dimensions
+ //
+ // The next few examples demonstrate using a RuleBasedNumberFormat to
+ // change the units a value is denominated in depending on its magnitude
+ //========================================================================
+
+ /**
+ * The example shows large numbers the way they often appear is nwespapers:
+ * 1,200,000 is formatted as "1.2 million".
+ */
+ public static final String abbEnglish =
+ "=#,##0=;\n"
+ // this is fairly self-explanatory, but note that the << substitution
+ // can show the fractional part of the substitution value if the user
+ // wants it
+ + "1,000,000: <##0.###< million;\n"
+ + "1,000,000,000: <##0.###< billion;\n"
+ + "1,000,000,000,000: <##0.###< trillion;\n";
+
+ /**
+ * This example takes a number of meters and formats it in whatever unit
+ * will produce a number with from one to three digits before the decimal
+ * point. For example, 230,000 is formatted as "230 km".
+ */
+ public static final String units =
+ "%main:\n"
+ // for values between 0 and 1, delegate to %%small
+ + " 0.x: >%%small>;\n"
+ // otherwise, show between 3 and 6 significant digits of the value
+ // along with the most appropriate unit
+ + " 0: =##0.###= m;\n"
+ + " 1,000: <##0.###< km;\n"
+ + " 1,000,000: <##0.###< Mm;\n"
+ + " 1,000,000,000: <##0.###< Gm;\n"
+ + " 1,000,000,000,000: <#,##0.###< Tm;\n"
+ // %%small formats the number when it's less then 1. It multiplies the
+ // value by one billion, and then uses %%small2 to actually do the
+ // formatting.
+ + "%%small:\n"
+ + " 1,000,000,000,000: <%%small2<;\n"
+ // this rule set actually formats small values. %%small passes this
+ // rule set a number of picometers, and it takes care of scaling up as
+ // appropriate in exactly the same way %main does (we can't normally
+ // handle fractional values this way: here, we're concerned about
+ // magnitude; most of the time, we're concerned about precsion)
+ + "%%small2:\n"
+ + " 0: =##0= pm;\n"
+ + " 1,000: <##0.###< nm;\n"
+ + " 1,000,000: <##0.###< \u00b5m;\n"
+ + " 1,000,000,000: <##0.###< mm;\n";
+
+ /**
+ * A more complicated message-formatting example. Here, in addition to
+ * handling the singular and plural versions of the word, the value is
+ * denominated in bytes, kilobytes, or megabytes depending on its magnitude.
+ * Also notice that it correctly treats a kilobyte as 1,024 bytes (not 1,000),
+ * and a megabyte as 1,024 kilobytes (not 1,000).
+ */
+ public static final String message2 =
+ // this rule supplies the shell of the sentence
+ "x.0: There << free space on the disk.;\n"
+ // handle singular and plural forms of "byte" (and format 0 as
+ // "There is no free space...")
+ + "0: is no;\n"
+ + "is one byte of;\n"
+ + "are =0= bytes of;\n"
+ // for values above 1,024, format the number in K (since "K" is usually
+ // promounced "K" regardless of whether it's singular or plural, we
+ // don't worry about the plural form). The "/1024" here causes us to
+ // treat a K as 1,024 bytes rather than 1,000 bytes.
+ + "1024/1024: is <0<K of;\n"
+ // for values about 1,048,576, format the number in Mb. Since "Mb" is
+ // usually promounced "meg" in singular and "megs" in plural, we do have
+ // both singular and plural forms. Again, notice we treat a megabyte
+ // as 1,024 kilobytes.
+ + "1,048,576/1024: is 1 Mb of;\n"
+ + "2,097,152/1024: are <0< Mb of;";
+
+ //========================================================================
+ // Alternate radices
+ //========================================================================
+
+ /**
+ * This example formats a number in dozens and gross. This is intended to
+ * demonstrate how this rule set can be used to format numbers in systems
+ * other than base 10. The "/12" after the rules' base values controls this.
+ * Also notice that the base doesn't have to be consistent throughout the
+ * whole rule set: we go back to base 10 for values over 1,000.
+ */
+ public static final String dozens =
+ // words for numbers...
+ "zero; one; two; three; four; five; six;\n"
+ + "seven; eight; nine; ten; eleven;\n"
+ // format values over 12 in dozens
+ + "12/12: << dozen[ and >>];\n"
+ // format values over 144 in gross
+ + "144/12: << gross[, >>];\n"
+ // format values over 1,000 in thousands
+ + "1000: << thousand[, >>];\n"
+ // overflow rule. Format values over 10,000 in numerals
+ + "10,000: =#,##0=;\n";
+
+ //========================================================================
+ // Major and minor units
+ //
+ // These examples show how a single value can be divided up into major
+ // and minor units that don't relate to each other by a factor of 10.
+ //========================================================================
+
+ /**
+ * This example formats a number of seconds in sexagesimal notation
+ * (i.e., hours, minutes, and seconds). %with-words formats it with
+ * words (3740 is "1 hour, 2 minutes, 20 seconds") and %in-numerals
+ * formats it entirely in numerals (3740 is "1:02:20").
+ */
+ public static final String durationInSeconds =
+ // main rule set for formatting with words
+ "%with-words:\n"
+ // take care of singular and plural forms of "second"
+ + " 0 seconds; 1 second; =0= seconds;\n"
+ // use %%min to format values greater than 60 seconds
+ + " 60/60: <%%min<[, >>];\n"
+ // use %%hr to format values greater than 3,600 seconds
+ // (the ">>>" below causes us to see the number of minutes
+ // when when there are zero minutes)
+ + " 3600/60: <%%hr<[, >>>];\n"
+ // this rule set takes care of the singular and plural forms
+ // of "minute"
+ + "%%min:\n"
+ + " 0 minutes; 1 minute; =0= minutes;\n"
+ // this rule set takes care of the singular and plural forms
+ // of "hour"
+ + "%%hr:\n"
+ + " 0 hours; 1 hour; =0= hours;\n"
+
+ // main rule set for formatting in numerals
+ + "%in-numerals:\n"
+ // values below 60 seconds are shown with "sec."
+ + " =0= sec.;\n"
+ // higher values are shown with colons: %%min-sec is used for
+ // values below 3,600 seconds...
+ + " 60: =%%min-sec=;\n"
+ // ...and %%hr-min-sec is used for values of 3,600 seconds
+ // and above
+ + " 3600: =%%hr-min-sec=;\n"
+ // this rule causes values of less than 10 minutes to show without
+ // a leading zero
+ + "%%min-sec:\n"
+ + " 0: :=00=;\n"
+ + " 60/60: <0<>>;\n"
+ // this rule set is used for values of 3,600 or more. Minutes are always
+ // shown, and always shown with two digits
+ + "%%hr-min-sec:\n"
+ + " 0: :=00=;\n"
+ + " 60/60: <00<>>;\n"
+ + " 3600/60: <#,##0<:>>>;\n"
+ // the lenient-parse rules allow several different characters to be used
+ // as delimiters between hours, minutes, and seconds
+ + "%%lenient-parse:\n"
+ + " & : = . = ' ' = -;\n";
+
+ /**
+ * This example formats a number of hours in sexagesimal notation (i.e.,
+ * hours, minutes, and seconds). %with-words formats the value using
+ * words for the units, and %in-numerals formats the value using only
+ * numerals.
+ */
+ public static final String durationInHours =
+ // main entry point for formatting with words
+ "%with-words:\n"
+ // this rule omits minutes and seconds when the value is
+ // an even number of hours
+ + " x.0: <<[, >%%min-sec>];\n"
+ // these rules take care of the singular and plural forms
+ // of hours
+ + " 0 hours; 1 hour; =#,##0= hours;\n"
+ // this rule set takes the fractional part of the number and multiplies
+ // it by 3,600 (turning it into a number of seconds). Then it delegates
+ // to %%min-sec-implementation to format the resulting value
+ + "%%min-sec:\n"
+ + " 3600: =%%min-sec-implementation=;\n"
+ // this rule set formats the seconds as either seconds or minutes and
+ // seconds, and takes care of the singular and plural forms of
+ // "minute" and "second"
+ + "%%min-sec-implementation:\n"
+ + " 0 seconds; 1 second; =0= seconds;\n"
+ + " 60/60: 1 minute[, >>];\n"
+ + " 120/60: <0< minutes[, >>];\n"
+
+ // main entry point for formatting in numerals
+ + "%in-numerals:\n"
+ // show minutes even for even numbers of hours
+ + " x.0: <#,##0<:00;\n"
+ // delegate to %%min-sec2 to format minutes and seconds
+ + " x.x: <#,##0<:>%%min-sec2>;\n"
+ // this rule set formats minutes when there is an even number of
+ // minutes, and delegates to %%min-sec2-implementation when there
+ // are seconds
+ + "%%min-sec2:\n"
+ + " 60: <00<;\n"
+ + " 3600: <%%min-sec2-implementation<;\n"
+ // these two rule sets are used to format the minutes and seconds
+ + "%%min-sec2-implementation:\n"
+ // if there are fewer than 60 seconds, show the minutes anyway
+ + " 0: 00:=00=;\n"
+ // if there are minutes, format them too, and always use 2 digits
+ // for both minutes and seconds
+ + " 60: =%%min-sec3=;\n"
+ + "%%min-sec3:\n"
+ + " 0: :=00=;\n"
+ + " 60/60: <00<>>;\n"
+ // the lenient-parse rules allow the user to use any of several
+ // characters as delimiters between hours, minutes, and seconds
+ + "%%lenient-parse:\n"
+ + " & : = . = ' ' = -;\n";
+
+ /**
+ * This rule set formats a number of pounds as pounds, shillings, and
+ * pence in the old English system of currency.
+ */
+ public static final String poundsShillingsAndPence =
+ // for values of 1 or more, format the integral part with a pound
+ // sign in front, and show shillings and pence if necessary
+ "%main:\n"
+ + " x.0: \u00a3<#,##0<[ >%%shillings-and-pence>];\n"
+ // for values between 0 and 1, omit the number of pounds
+ + " 0.x: >%%pence-alone>;\n"
+ // this rule set is used to show shillings and pence. It multiplies
+ // the fractional part of the number by 240 (the number of pence in a
+ // pound) and uses %%shillings-and-pence-implementation to format
+ // the result
+ + "%%shillings-and-pence:\n"
+ + " 240: <%%shillings-and-pence-implementation<;\n"
+ // this rule set is used to show shillings and pence when there are
+ // no pounds. It also multiplies the value by 240, and then it uses
+ // %%pence-alone-implementation to format the result.
+ + "%%pence-alone:\n"
+ + " 240: <%%pence-alone-implementation<;\n"
+ // this rule set formats a number of pence when we know we also
+ // have pounds. We always show shillings (with a 0 if necessary),
+ // but only show pence if the value isn't an even number of shillings
+ + "%%shillings-and-pence-implementation:\n"
+ + " 0/; 0/=0=;\n"
+ + " 12/12: <0</[>0>];\n"
+ // this rule set formats a number of pence when we know there are
+ // no pounds. Values less than a shilling are shown with "d." (the
+ // abbreviation for pence), and values greater than a shilling are
+ // shown with a shilling bar (and without pence when the value is
+ // an even number of shillings)
+ + "%%pence-alone-implementation:\n"
+ + " =0= d.;\n"
+ + " 12/12: <0</[>0>];\n";
+
+ //========================================================================
+ // Alternate numeration systems
+ //
+ // These examples show how RuleBasedNumberFormat can be used to format
+ // numbers using non-positional numeration systems.
+ //========================================================================
+
+ /**
+ * Arabic digits. This example formats numbers in Arabic numerals.
+ * Normally, you'd do this with DecimalFormat, but this shows that
+ * RuleBasedNumberFormat can handle it too.
+ */
+ public static final String arabicNumerals =
+ "0; 1; 2; 3; 4; 5; 6; 7; 8; 9;\n"
+ + "10: <<>>;\n"
+ + "100: <<>>>;\n"
+ + "1000: <<,>>>;\n"
+ + "1,000,000: <<,>>>;\n"
+ + "1,000,000,000: <<,>>>;\n"
+ + "1,000,000,000,000: <<,>>>;\n"
+ + "1,000,000,000,000,000: =#,##0=;\n"
+ + "-x: ->>;\n"
+ + "x.x: <<.>>;";
+
+ /**
+ * Words for digits. Follows the same pattern as the Arabic-numerals
+ * example above, but uses words for the various digits (e.g., 123 comes
+ * out as "one two three").
+ */
+ public static final String wordsForDigits =
+ "-x: minus >>;\n"
+ + "x.x: << point >>;\n"
+ + "zero; one; two; three; four; five; six;\n"
+ + " seven; eight; nine;\n"
+ + "10: << >>;\n"
+ + "100: << >>>;\n"
+ + "1000: <<, >>>;\n"
+ + "1,000,000: <<, >>>;\n"
+ + "1,000,000,000: <<, >>>;\n"
+ + "1,000,000,000,000: <<, >>>;\n"
+ + "1,000,000,000,000,000: =#,##0=;\n";
+
+ /**
+ * This example formats numbers using Chinese characters in the Arabic
+ * place-value method. This was used historically in China for a while.
+ */
+ public static final String chinesePlaceValue =
+ "\u3007; \u4e00; \u4e8c; \u4e09; \u56db; \u4e94; \u516d; \u4e03; \u516b; \u4e5d;\n"
+ + "10: <<>>;\n"
+ + "100: <<>>>;\n"
+ + "1000: <<>>>;\n"
+ + "1,000,000: <<>>>;\n"
+ + "1,000,000,000: <<>>>;\n"
+ + "1,000,000,000,000: <<>>>;\n"
+ + "1,000,000,000,000,000: =#,##0=;\n";
+
+ /**
+ * Roman numerals. This example has two variants: %modern shows how large
+ * numbers are usually handled today; %historical ses the older symbols for
+ * thousands.
+ */
+ public static final String romanNumerals =
+ "%historical:\n"
+ + " =%modern=;\n"
+ // in early Roman numerals, 1,000 was shown with a circle
+ // bisected by a vertical line. Additional thousands were
+ // shown by adding more concentric circles, and fives were
+ // shown by cutting the symbol for next-higher power of 10
+ // in half (the letter D for 500 evolved from this).
+ // We could go beyond 40,000, but Unicode doesn't encode
+ // the symbols for higher numbers/
+ + " 1000: \u2180[>>]; 2000: \u2180\u2180[>>]; 3000: \u2180\u2180\u2180[>>]; 4000: \u2180\u2181[>>];\n"
+ + " 5000: \u2181[>>]; 6000: \u2181\u2180[>>]; 7000: \u2181\u2180\u2180[>>];\n"
+ + " 8000: \u2181\u2180\u2180\u2180[>>]; 9000: \u2180\u2182[>>];\n"
+ + " 10,000: \u2182[>>]; 20,000: \u2182\u2182[>>]; 30,000: \u2182\u2182\u2182[>>];\n"
+ + " 40,000: =#,##0=;\n"
+ + "%modern:\n"
+ + " ; I; II; III; IV; V; VI; VII; VIII; IX;\n"
+ + " 10: X[>>]; 20: XX[>>]; 30: XXX[>>]; 40: XL[>>]; 50: L[>>];\n"
+ + " 60: LX[>>]; 70: LXX[>>]; 80: LXXX[>>]; 90: XC[>>];\n"
+ + " 100: C[>>]; 200: CC[>>]; 300: CCC[>>]; 400: CD[>>]; 500: D[>>];\n"
+ + " 600: DC[>>]; 700: DCC[>>]; 800: DCCC[>>]; 900: CM[>>];\n"
+ // in modern Roman numerals, high numbers are generally shown
+ // by placing a bar over the letters for the lower numbers:
+ // the bar multiplied a letter's value by 1,000
+ + " 1000: M[>>]; 2000: MM[>>]; 3000: MMM[>>]; 4000: MV\u0306[>>];\n"
+ + " 5000: V\u0306[>>]; 6000: V\u0306M[>>]; 7000: V\u0306MM[>>];\n"
+ + " 8000: V\u0306MMM[>>]; 9000: MX\u0306[>>];\n"
+ + " 10,000: X\u0306[>>]; 20,000: X\u0306X\u0306[>>]; 30,000: X\u0306X\u0306X\u0306[>>];\n"
+ + " 40,000: X\u0306L\u0306[>>]; 50,000: L\u0306[>>]; 60,000: L\u0306X\u0306[>>];\n"
+ + " 70,000: L\u0306X\u0306X\u0306[>>]; 80,000: L\u0306X\u0306X\u0306X\u0306[>>];\n"
+ + " 90,000: X\u0306C\u0306[>>];\n"
+ + " 100,000: C\u0306[>>]; 200,000: C\u0306C\u0306[>>]; 300,000: C\u0306C\u0306[>>];\n"
+ + " 400,000: C\u0306D\u0306[>>]; 500,000: D\u0306[>>]; 600,000: D\u0306C\u0306[>>];\n"
+ + " 700,000: D\u0306C\u0306C\u0306[>>]; 800,000: D\u0306C\u0306C\u0306C\u0306[>>];\n"
+ + " 900,000: =#,##0=;\n";
+
+ /**
+ * Hebrew alphabetic numerals. Before adoption of Arabic numerals, Hebrew speakers
+ * used the letter of their alphabet as numerals. The first nine letters of
+ * the alphabet repesented the values from 1 to 9, the second nine letters the
+ * multiples of 10, and the remaining letters the multiples of 100. Since they
+ * ran out of letters at 400, the remaining multiples of 100 were represented
+ * using combinations of the existing letters for the hundreds. Numbers were
+ * distinguished from words in a number of different ways: the way shown here
+ * uses a single mark after a number consisting of one letter, and a double
+ * mark between the last two letters of a number consisting of two or more
+ * letters. Two dots over a letter multiplied its value by 1,000. Also, since
+ * the letter for 10 is the first letter of God's name and the letters for 5 and 6
+ * are letters in God's name, which wasn't supposed to be written or spoken, 15 and
+ * 16 were usually written as 9 + 6 and 9 + 7 instead of 10 + 5 and 10 + 6.
+ */
+ public static final String hebrewAlphabetic =
+ // letters for the ones
+ "%%ones:\n"
+ + " (no zero); \u05d0; \u05d1; \u05d2; \u05d3; \u05d4; \u05d5; \u05d6; \u05d7; \u05d8;\n"
+ // letters for the tens
+ + "%%tens:\n"
+ + " ; \u05d9; \u05db; \u05dc; \u05de; \u05e0; \u05e1; \u05e2; \u05e4; \u05e6;\n"
+ // letters for the first four hundreds
+ + "%%hundreds:\n"
+ + " ; \u05e7; \u05e8; \u05e9; \u05ea;\n"
+ // this rule set is used to write the combination of the tens and ones digits
+ // when we know that no other digits precede them: they put the numeral marks
+ // in the right place and properly handle 15 and 16 (I'm using the mathematical
+ // prime characters for the numeral marks because my Unicode font doesn't
+ // include the real Hebrew characters, which look just like the prime marks)
+ + "%%tens-and-ones:\n"
+ // for values less than 10, just use %%ones and put the numeral mark
+ // afterward
+ + " =%%ones=\u2032;\n"
+ // put the numeral mark at the end for 10, but in the middle for
+ // 11 through 14
+ + " 10: <%%tens<\u2032; <%%tens<\u2033>%%ones>;\n"
+ // special-case 15 and 16
+ + " 15: \u05d8\u2033\u05d5; 16: \u05d8\u2033\u05d6;\n"
+ // go back to the normal method at 17
+ + " 17: <%%tens<\u2033>%%ones>;\n"
+ // repeat the rules for 10 and 11 to cover the values from 20 to 99
+ + " 20: <%%tens<\u2032; <%%tens<\u2033>%%ones>;\n"
+ // this rule set is used to format numbers below 1,000. It relies on
+ // %%tens-and-ones to format the tens and ones places, and adds logic
+ // to handle the high hundreds and the numeral marks when there is no
+ // tens digit. Notice how the rules are paired: all of these pairs of
+ // rules take advantage of the rollback rule: if the value (between 100
+ // and 499) is an even multiple of 100, the rule for 100 is used; otherwise,
+ // the rule for 101 (the following rule) is used. The first rule in each
+ // pair (the one for the even multiple) places the numeral mark in a different
+ // spot than the second rule in each pair (which knows there are more digits
+ // and relies on the rule supplying them to also supply the numeral mark).
+ // The call to %%null in line 10 is there simply to invoke the rollback
+ // rule.
+ + "%%low-order:\n"
+ // this rule is only called when there are other characters before.
+ // It places the numeral mark before the last digit
+ + " \u2033=%%ones=;\n"
+ // the rule for 10 places the numeral mark before the 10 character
+ // (because we know it's the last character); the rule for 11 relies
+ // on %%tens-and-ones to place the numeral mark
+ + " 10: \u2033<%%tens<; =%%tens-and-ones=>%%null>;\n"
+ // the rule for 100 places the numeral mark before the 100 character
+ // (we know it's the last character); the rule for 101 recurses to
+ // fill in the remaining digits and the numeral mark
+ + " 100: <%%hundreds<\u2032; <%%hundreds<>>;\n"
+ // special-case the hundreds from 500 to 900 because they consist of
+ // more than one character
+ + " 500: \u05ea\u2033\u05e7; \u05ea\u05e7>>;\n"
+ + " 600: \u05ea\u2033\u05e8; \u05ea\u05e8>>;\n"
+ + " 700: \u05ea\u2033\u05e9; \u05ea\u05e9>>;\n"
+ + " 800: \u05ea\u2033\u05ea; \u05ea\u05ea>>;\n"
+ + " 900: \u05ea\u05ea\u2033\u05e7; \u05ea\u05ea\u05e7>>;\n"
+ // this rule set is used to format values of 1,000 or more. Here, we don't
+ // worry about the numeral mark, and we add two dots (the Unicode combining
+ // diaeresis character) to ever letter
+ + "%%high-order:\n"
+ // put the ones digit, followed by the diaeresis
+ + " =%%ones=\u0308;\n"
+ // the tens can be handled with recursion
+ + " 10: <%%tens<\u0308[>>];\n"
+ // still have to special-case 15 and 16
+ + " 15: \u05d8\u0308\u05d5\u0308; 16: \u05d8\u003078\u05d6\u0308;\n"
+ // back to the regular rules at 17
+ + " 17: <%%tens<\u0308[>>];\n"
+ // the hundreds with the dots added (and without worrying about
+ // placing the numeral mark)
+ + " 100: <%%hundreds<\u0308[>>];\n"
+ + " 500: \u05ea\u0308\u05e7\u0308[>>];\n"
+ + " 600: \u05ea\u0308\u05e8\u0308[>>];\n"
+ + " 700: \u05ea\u0308\u05e9\u0308[>>];\n"
+ + " 800: \u05ea\u0308\u05ea\u0308[>>];\n"
+ + " 900: \u05ea\u0308\u05ea\u0308\u05e7\u0308[>>];\n"
+ // this rule set doesn't do anything; it's used by some other rules to
+ // invoke the rollback rule
+ + " %%null:\n"
+ + " ;\n"
+ // the main rule set.
+ + "%main:\n"
+ // for values below 10, just output the letter and the numeral mark
+ + " =%%ones=\u2032;\n"
+ // for values from 10 to 99, use %%tens-and-ones to do the formatting
+ + " 10: =%%tens-and-ones=;\n"
+ // for values from 100 to 999, use %%low-order to do the formatting
+ + " 100: =%%low-order=;\n"
+ // for values of 1,000 and over, use %%high-order to do the formatting
+ + " 1000: <%%high-order<[>%%low-order>];\n";
+
+ /**
+ * Greek alphabetic numerals. The Greeks, before adopting the Arabic numerals,
+ * also used the letters of their alphabet as numerals. There are three now-
+ * obsolete Greek letters that are used as numerals; many fonts don't have them.
+ * Large numbers were handled many different ways; the way shown here divides
+ * large numbers into groups of four letters (factors of 10,000), and separates
+ * the groups with the capital letter mu (for myriad). Capital letters are used
+ * for values below 10,000; small letters for higher numbers (to make the capital
+ * mu stand out).
+ */
+ public static final String greekAlphabetic =
+ // this rule set is used for formatting numbers below 10,000. It uses
+ // capital letters.
+ "%%low-order:\n"
+ + " (no zero); \u0391; \u0392; \u0393; \u0394; \u0395; \u03dc; \u0396; \u0397; \u0398;\n"
+ + " 10: \u0399[>>]; 20: \u039a[>>]; 30: \u039b[>>]; 40: \u039c[>>]; 50: \u039d[>>];\n"
+ + " 60: \u039e[>>]; 70: \u039f[>>]; 80: \u03a0[>>]; 90: \u03de[>>];\n"
+ + " 100: \u03a1[>>]; 200: \u03a3[>>]; 300: \u03a4[>>]; 400: \u03a5[>>];\n"
+ + " 500: \u03a6[>>]; 600: \u03a7[>>]; 700: \u03a8[>>]; 800: \u03a9[>>];\n"
+ + " 900: \u03e0[>>];\n"
+ // the thousands are represented by the same numbers as the ones, but
+ // with a comma-like mark added to their left shoulder
+ + " 1000: \u0391\u0313[>>]; 2000: \u0392\u0313[>>]; 3000: \u0393\u0313[>>];\n"
+ + " 4000: \u0394\u0313[>>]; 5000: \u0395\u0313[>>]; 6000: \u03dc\u0313[>>];\n"
+ + " 7000: \u0396\u0313[>>]; 8000: \u0397\u0313[>>]; 9000: \u0398\u0313[>>];\n"
+ // this rule set is the same as above, but uses lowercase letters. It is used
+ // for formatting the groups in numbers above 10,000.
+ + "%%high-order:\n"
+ + " (no zero); \u03b1; \u03b2; \u03b3; \u03b4; \u03b5; \u03dc; \u03b6; \u03b7; \u03b8;\n"
+ + " 10: \u03b9[>>]; 20: \u03ba[>>]; 30: \u03bb[>>]; 40: \u03bc[>>]; 50: \u03bd[>>];\n"
+ + " 60: \u03be[>>]; 70: \u03bf[>>]; 80: \u03c0[>>]; 90: \u03de[>>];\n"
+ + " 100: \u03c1[>>]; 200: \u03c3[>>]; 300: \u03c4[>>]; 400: \u03c5[>>];\n"
+ + " 500: \u03c6[>>]; 600: \u03c7[>>]; 700: \u03c8[>>]; 800: \u03c9[>>];\n"
+ + " 900: \u03c0[>>];\n"
+ + " 1000: \u03b1\u0313[>>]; 2000: \u03b2\u0313[>>]; 3000: \u03b3\u0313[>>];\n"
+ + " 4000: \u03b4\u0313[>>]; 5000: \u03b5\u0313[>>]; 6000: \u03dc\u0313[>>];\n"
+ + " 7000: \u03b6\u0313[>>]; 8000: \u03b7\u0313[>>]; 9000: \u03b8\u0313[>>];\n"
+ // the main rule set
+ + "%main:\n"
+ // for values below 10,000, just use %%low-order
+ + " =%%low-order=;\n"
+ // for values above 10,000, split into two groups of four digits
+ // and format each with %%high-order (putting an M in betwen)
+ + " 10,000: <%%high-order<\u039c>%%high-order>;\n"
+ // for values above 100,000,000, add another group onto the front
+ // and another M
+ + " 100,000,000: <%%high-order<\u039c>>\n";
+
+ /**
+ * A list of all the sample rule sets, used by the demo program.
+ */
+ public static final String[] sampleRuleSets =
+ { usEnglish,
+ ukEnglish,
+ spanish,
+ french,
+ swissFrench,
+ german,
+ italian,
+ swedish,
+ dutch,
+ japanese,
+ greek,
+ russian,
+ hebrew,
+ ordinal,
+ message1,
+ dollarsAndCents,
+ decimalAsFraction,
+ closestFraction,
+ stock,
+ abbEnglish,
+ units,
+ message2,
+ dozens,
+ durationInSeconds,
+ durationInHours,
+ poundsShillingsAndPence,
+ arabicNumerals,
+ wordsForDigits,
+ chinesePlaceValue,
+ romanNumerals,
+ hebrewAlphabetic,
+ greekAlphabetic };
+
+ /**
+ * The displayable names for all the sample rule sets, in the same order as
+ * the preceding array.
+ */
+ public static final String[] sampleRuleSetNames =
+ { "English (US)",
+ "English (UK)",
+ "Spanish",
+ "French (France)",
+ "French (Switzerland)",
+ "German",
+ "Italian",
+ "Swedish",
+ "Dutch",
+ "Japanese",
+ "Greek",
+ "Russian",
+ "Hebrew",
+ "English ordinal abbreviations",
+ "Simple message formatting",
+ "Dollars and cents",
+ "Decimals as fractions",
+ "Closest fraction",
+ "Stock prices",
+ "Abbreviated US English",
+ "Changing dimensions",
+ "Complex message formatting",
+ "Dozens",
+ "Duration (value in seconds)",
+ "Duration (value in hours)",
+ "Pounds, shillings, and pence",
+ "Arabic numerals",
+ "Words for digits",
+ "Chinese place-value notation",
+ "Roman numerals",
+ "Hebrew ahlphabetic numerals",
+ "Greek alphabetic numerals" };
+
+ /**
+ * The base locale for each of the sample rule sets. The locale is used to
+ * determine DecimalFormat behavior, lenient-parse behavior, and text-display
+ * selection (we have a hack in here to allow display of non-Latin scripts).
+ * Null means the locale setting is irrelevant and the default can be used.
+ */
+ public static final Locale[] sampleRuleSetLocales =
+ { Locale.US,
+ Locale.UK,
+ new Locale("es", "", ""),
+ Locale.FRANCE,
+ new Locale("fr", "CH", ""),
+ Locale.GERMAN,
+ Locale.ITALIAN,
+ new Locale("sv", "", ""),
+ new Locale("nl", "", ""),
+ Locale.JAPANESE,
+ new Locale("el", "", ""),
+ new Locale("ru", "", ""),
+ new Locale("iw", "", ""),
+ Locale.ENGLISH,
+ Locale.ENGLISH,
+ Locale.US,
+ Locale.ENGLISH,
+ null,
+ null,
+ Locale.ENGLISH,
+ null,
+ Locale.ENGLISH,
+ Locale.ENGLISH,
+ null,
+ null,
+ Locale.UK,
+ null,
+ Locale.ENGLISH,
+ new Locale("zh", "", ""),
+ null,
+ new Locale("iw", "", ""),
+ new Locale("el", "", ""),
+ null };
+
+ public static final String[] sampleRuleSetCommentary = {
+ "This demonstration version of the "
+ + "U.S. English spellout rules has four variants: 1) %simplified is a "
+ + "set of rules showing the simple method of spelling out numbers in "
+ + "English: 289 is formatted as \"two hundred eighty-nine\". 2) %alt-teens "
+ + "is the same as %simplified, except that values between 1,000 and 9,999 "
+ + "whose hundreds place isn't zero are formatted in hundreds. For example, "
+ + "1,983 is formatted as \"nineteen hundred eighty-three,\" and 2,183 is "
+ + "formatted as \"twenty-one hundred eighty-three,\" but 2,083 is still "
+ + "formatted as \"two thousand eighty-three.\" 3) %ordinal formats the "
+ + "values as ordinal numbers in English (e.g., 289 is \"two hundred eighty-"
+ + "ninth\"). 4) %default uses a more complicated algorithm to format "
+ + "numbers in a more natural way: 289 is formatted as \"two hundred AND "
+ + "eighty-nine\" and commas are inserted between the thousands groups for "
+ + "values above 100,000.",
+
+ "U.K. English has one significant "
+ + "difference from U.S. English: the names for values of 1,000,000,000 "
+ + "and higher. In American English, each successive \"-illion\" is 1,000 "
+ + "times greater than the preceding one: 1,000,000,000 is \"one billion\" "
+ + "and 1,000,000,000,000 is \"one trillion.\" In British English, each "
+ + "successive \"-illion\" is one million times greater than the one before: "
+ + "\"one billion\" is 1,000,000,000,000 (or what Americans would call a "
+ + "\"trillion\"), and \"one trillion\" is 1,000,000,000,000,000,000. "
+ + "1,000,000,000 in British English is \"one thousand million.\" (This "
+ + "value is sometimes called a \"milliard,\" but this word seems to have "
+ + "fallen into disuse.)",
+
+ "The Spanish rules are quite similar to "
+ + "the English rules, but there are some important differences: "
+ + "First, we have to provide separate rules for most of the twenties "
+ + "because the ones digit frequently picks up an accent mark that it "
+ + "doesn't have when standing alone. Second, each multiple of 100 has "
+ + "to be specified separately because the multiplier on 100 very often "
+ + "changes form in the contraction: 500 is \"quinientos,\" not "
+ + "\"cincocientos.\" In addition, the word for 100 is \"cien\" when "
+ + "standing alone, but changes to \"ciento\" when followed by more digits. "
+ + "There also some other differences.",
+
+ "French adds some interesting quirks of its "
+ + "own: 1) The word \"et\" is interposed between the tens and ones digits, "
+ + "but only if the ones digit if 1: 20 is \"vingt,\" and 2 is \"vingt-deux,\" "
+ + "but 21 is \"vingt-et-un.\" 2) There are no words for 70, 80, or 90. "
+ + "\"quatre-vingts\" (\"four twenties\") is used for 80, and values proceed "
+ + "by score from 60 to 99 (e.g., 73 is \"soixante-treize\" [\"sixty-thirteen\"]). "
+ + "Numbers from 1,100 to 1,199 are rendered as hundreds rather than "
+ + "thousands: 1,100 is \"onze cents\" (\"eleven hundred\"), rather than "
+ + "\"mille cent\" (\"one thousand one hundred\")",
+
+ "Swiss French differs from French French "
+ + "in that it does have words for 70, 80, and 90. This rule set shows them, "
+ + "and is simpler as a result.",
+
+ "German also adds some interesting "
+ + "characteristics. For values below 1,000,000, numbers are customarily "
+ + "written out as a single word. And the ones digit PRECEDES the tens "
+ + "digit (e.g., 23 is \"dreiundzwanzig,\" not \"zwanzigunddrei\").",
+
+ "Like German, most Italian numbers are "
+ + "written as single words. What makes these rules complicated is the rule "
+ + "that says that when a word ending in a vowel and a word beginning with "
+ + "a vowel are combined into a compound, the vowel is dropped from the "
+ + "end of the first word: 180 is \"centottanta,\" not \"centoottanta.\" "
+ + "The complexity of this rule set is to produce this behavior.",
+
+ "Spellout rules for Swedish.",
+
+ "Spellout rules for Dutch. Notice that in Dutch, as in German,"
+ + "the ones digit precedes the tens digit.",
+
+ "In Japanese, there really isn't any "
+ + "distinction between a number written out in digits and a number "
+ + "written out in words: the ideographic characters are both digits "
+ + "and words. This rule set provides two variants: %traditional "
+ + "uses the traditional CJK numerals (which are also used in China "
+ + "and Korea). %financial uses alternate ideographs for many numbers "
+ + "that are harder to alter than the traditional numerals (one could "
+ + "fairly easily change a one to "
+ + "a three just by adding two strokes, for example). This is also done in "
+ + "the other countries using Chinese idographs, but different ideographs "
+ + "are used in those places.",
+
+ "Again in Greek we have to supply the words "
+ + "for the multiples of 100 because they can't be derived algorithmically. "
+ + "Also, the tens dgit changes form when followed by a ones digit: an "
+ + "accent mark disappears from the tens digit and moves to the ones digit. "
+ + "Therefore, instead of using the [] notation, we actually have to use "
+ + "two separate rules for each multiple of 10 to show the two forms of "
+ + "the word.",
+
+ "Spellout rules for Russian.",
+
+ "Spellout rules for Hebrew. Hebrew actually has inflected forms for "
+ + "most of the lower-order numbers. The masculine forms are shown "
+ + "here.",
+
+ "This rule set adds an English ordinal abbreviation to the end of a "
+ + "number. For example, 2 is formatted as \"2nd\". Parsing doesn't work with "
+ + "this rule set. To parse, use DecimalFormat on the numeral.",
+
+ "This is a simple message-formatting example. Normally one would "
+ + "use ChoiceFormat and MessageFormat to do something this simple, "
+ + "but this shows it could be done with RuleBasedNumberFormat too. "
+ + "A message-formatting example that might work better with "
+ + "RuleBasedNumberFormat appears later.",
+
+ "The next few examples demonstrate fraction handling. "
+ + "This example formats a number in one of the two styles often used "
+ + "on checks. %dollars-and-hundredths formats cents as hundredths of "
+ + "a dollar (23.40 comes out as \"twenty-three and 40/100 dollars\"). "
+ + "%dollars-and-cents formats in dollars and cents (23.40 comes out as "
+ + "\"twenty-three dollars and forty cents\")",
+
+ "This rule set shows the fractional part of the number as a fraction "
+ + "with a power of 10 as the denominator. Some languages don't spell "
+ + "out the fractional part of a number as \"point one two three,\" but "
+ + "always render it as a fraction. If we still want to treat the fractional "
+ + "part of the number as a decimal, then the fraction's denominator "
+ + "is always a power of 10. This example does that: 23.125 is formatted "
+ + "as \"twenty-three and one hundred twenty-five thousandths\" (as opposed "
+ + "to \"twenty-three point one two five\" or \"twenty-three and one eighth\").",
+
+ "Number with closest fraction. This example formats a value using "
+ + "numerals, but shows the fractional part as a ratio (fraction) rather "
+ + "than a decimal. The fraction always has a denominator between 2 and 10.",
+
+ "American stock-price formatting. Non-integral stock prices are still "
+ + "generally shown in eighths or sixteenths of dollars instead of dollars "
+ + "and cents. This example formats stock prices in this way if possible, "
+ + "and in dollars and cents if not.",
+
+ "The next few examples demonstrate using a RuleBasedNumberFormat to "
+ + "change the units a value is denominated in depending on its magnitude. "
+ + "The example shows large numbers the way they often appear is nwespapers: "
+ + "1,200,000 is formatted as \"1.2 million\".",
+
+ "This example takes a number of meters and formats it in whatever unit "
+ + "will produce a number with from one to three digits before the decimal "
+ + "point. For example, 230,000 is formatted as \"230 km\".",
+
+ "A more complicated message-formatting example. Here, in addition to "
+ + "handling the singular and plural versions of the word, the value is "
+ + "denominated in bytes, kilobytes, or megabytes depending on its magnitude. "
+ + "Also notice that it correctly treats a kilobyte as 1,024 bytes (not 1,000), "
+ + "and a megabyte as 1,024 kilobytes (not 1,000).",
+
+ "This example formats a number in dozens and gross. This is intended to "
+ + "demonstrate how this rule set can be used to format numbers in systems "
+ + "other than base 10. The \"/12\" after the rules' base values controls this. "
+ + "Also notice that the base doesn't have to be consistent throughout the "
+ + "whole rule set: we go back to base 10 for values over 1,000.",
+
+ "The next few examples show how a single value can be divided up into major "
+ + "and minor units that don't relate to each other by a factor of 10. "
+ + "This example formats a number of seconds in sexagesimal notation "
+ + "(i.e., hours, minutes, and seconds). %with-words formats it with "
+ + "words (3740 is \"1 hour, 2 minutes, 20 seconds\") and %in-numerals "
+ + "formats it entirely in numerals (3740 is \"1:02:20\").",
+
+ "This example formats a number of hours in sexagesimal notation (i.e., "
+ + "hours, minutes, and seconds). %with-words formats the value using "
+ + "words for the units, and %in-numerals formats the value using only "
+ + "numerals.",
+
+ "This rule set formats a number of pounds as pounds, shillings, and "
+ + "pence in the old English system of currency.",
+
+ "These examples show how RuleBasedNumberFormat can be used to format "
+ + "numbers using non-positional numeration systems. "
+ + "This example formats numbers in Arabic numerals. "
+ + "Normally, you'd do this with DecimalFormat, but this shows that "
+ + "RuleBasedNumberFormat can handle it too.",
+
+ "This example follows the same pattern as the Arabic-numerals "
+ + "example, but uses words for the various digits (e.g., 123 comes "
+ + "out as \"one two three\").",
+
+ "This example formats numbers using Chinese characters in the Arabic "
+ + "place-value method. This was used historically in China for a while.",
+
+ "Roman numerals. This example has two variants: %modern shows how large "
+ + "numbers are usually handled today; %historical ses the older symbols for "
+ + "thousands. Not all of the characters are displayable with most fonts.",
+
+ "Hebrew alphabetic numerals. Before adoption of Arabic numerals, Hebrew speakers "
+ + "used the letter of their alphabet as numerals. The first nine letters of "
+ + "the alphabet repesented the values from 1 to 9, the second nine letters the "
+ + "multiples of 10, and the remaining letters the multiples of 100. Since they "
+ + "ran out of letters at 400, the remaining multiples of 100 were represented "
+ + "using combinations of the existing letters for the hundreds. Numbers were "
+ + "distinguished from words in a number of different ways: the way shown here "
+ + "uses a single mark after a number consisting of one letter, and a double "
+ + "mark between the last two letters of a number consisting of two or more "
+ + "letters. Two dots over a letter multiplied its value by 1,000. Also, since "
+ + "the letter for 10 is the first letter of God's name and the letters for 5 and 6 "
+ + "are letters in God's name, which wasn't supposed to be written or spoken, 15 and "
+ + "16 were usually written as 9 + 6 and 9 + 7 instead of 10 + 5 and 10 + 6.",
+
+ "Greek alphabetic numerals. The Greeks, before adopting the Arabic numerals, "
+ + "also used the letters of their alphabet as numerals. There are three now-"
+ + "obsolete Greek letters that are used as numerals; many fonts don't have them. "
+ + "Large numbers were handled many different ways; the way shown here divides "
+ + "large numbers into groups of four letters (factors of 10,000), and separates "
+ + "the groups with the capital letter mu (for myriad). Capital letters are used "
+ + "for values below 10,000; small letters for higher numbers (to make the capital "
+ + "mu stand out).",
+
+ "This is a custom (user-defined) rule set."
+ };
+}
diff --git a/demos/src/com/ibm/icu/dev/demo/rbnf/package.html b/demos/src/com/ibm/icu/dev/demo/rbnf/package.html
new file mode 100644
index 0000000..8a0507f
--- /dev/null
+++ b/demos/src/com/ibm/icu/dev/demo/rbnf/package.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!-- Copyright (C) 2000-2004, International Business Machines Corporation and
+ others. All Rights Reserved.
+
+-->
+</head>
+<body bgcolor="white">
+RuleBasedNumberFormat demo appliation.
+</body>
+</html>
\ No newline at end of file
diff --git a/demos/src/com/ibm/icu/dev/demo/translit/AnyTransliterator.java b/demos/src/com/ibm/icu/dev/demo/translit/AnyTransliterator.java
new file mode 100644
index 0000000..3f458d8
--- /dev/null
+++ b/demos/src/com/ibm/icu/dev/demo/translit/AnyTransliterator.java
@@ -0,0 +1,308 @@
+/**
+ *******************************************************************************
+ * Copyright (C) 2001-2010, International Business Machines Corporation and *
+ * others. All Rights Reserved. *
+ *******************************************************************************
+ */
+package com.ibm.icu.dev.demo.translit;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.TreeSet;
+
+import com.ibm.icu.lang.UScript;
+import com.ibm.icu.text.Replaceable;
+import com.ibm.icu.text.Transliterator;
+import com.ibm.icu.text.UTF16;
+import com.ibm.icu.text.UnicodeFilter;
+
+public class AnyTransliterator extends Transliterator {
+
+ static final boolean DEBUG = false;
+ private String targetName;
+ private RunIterator it;
+ private Position run;
+
+
+ public AnyTransliterator(String targetName, UnicodeFilter filter, RunIterator it){
+ super("Any-" + targetName, filter);
+ this.targetName = targetName;
+ this.it = it;
+ run = new Position();
+ }
+
+ public AnyTransliterator(String targetName, UnicodeFilter filter){
+ this(targetName, filter, new ScriptRunIterator());
+ }
+
+ static private Transliterator hex = Transliterator.getInstance("[^\\u0020-\\u007E] hex");
+
+ protected void handleTransliterate(Replaceable text,
+ Position offsets, boolean isIncremental) {
+ if (DEBUG) {
+ System.out.println("- handleTransliterate " + hex.transliterate(text.toString())
+ + ", " + toString(offsets));
+ }
+ it.reset(text, offsets);
+
+ while (it.next(run)) {
+ if (targetName.equalsIgnoreCase(it.getName())) {
+ if (DEBUG) System.out.println("Skipping identical: " + targetName);
+ run.start = run.limit; // show we processed
+ continue; // skip if same
+ }
+
+ Transliterator t;
+ String id = it.getName() + '-' + targetName;
+ try {
+ t = Transliterator.getInstance(id);
+ } catch (IllegalArgumentException ex) {
+ if (DEBUG) System.out.println("Couldn't find: " + id + ", Trying Latin as Pivot");
+ id = it.getName() + "-Latin; Latin-" + targetName;
+ try {
+ t = Transliterator.getInstance(id);
+ } catch (IllegalArgumentException ex2) {
+ if (DEBUG) System.out.println("Couldn't find: " + id);
+ continue;
+ }
+ }
+ // TODO catch error later!!
+
+ if (DEBUG) {
+ System.out.println(t.getID());
+ System.out.println("input: " + hex.transliterate(text.toString())
+ + ", " + toString(run));
+ }
+
+ if (isIncremental && it.atEnd()) {
+ t.transliterate(text, run);
+ } else {
+ t.finishTransliteration(text, run);
+ }
+ // adjust the offsets in line with the changes
+ it.adjust(run.limit);
+
+ if (DEBUG) {
+ System.out.println("output: " + hex.transliterate(text.toString())
+ + ", " + toString(run));
+ }
+ }
+
+ // show how far we got!
+ it.getExpanse(offsets);
+ if (run.start == run.limit) offsets.start = offsets.limit;
+ else offsets.start = run.start;
+ if (DEBUG) {
+ System.out.println("+ handleTransliterate: " + ", " + toString(offsets));
+ System.out.println();
+ }
+ }
+
+ // should be method on Position
+ public static String toString(Position offsets) {
+ return "[cs: " + offsets.contextStart
+ + ", s: " + offsets.start
+ + ", l: " + offsets.limit
+ + ", cl: " + offsets.contextLimit
+ + "]";
+ }
+
+ public interface RunIterator {
+ public void reset(Replaceable text, Position expanse);
+ public void getExpanse(Position run);
+ public void reset();
+ public boolean next(Position run);
+ public void getCurrent(Position run);
+ public String getName();
+ public void adjust(int newCurrentLimit);
+ public boolean atEnd();
+ }
+
+ /**
+ * Returns a series of ranges corresponding to scripts. They will be of the form:
+ * ccccSScSSccccTTcTcccc - where c is common, S is the first script and T is the second
+ *| | - first run
+ * | | - second run
+ * That is, the runs will overlap. The reason for this is so that a transliterator can
+ * consider common characters both before and after the scripts.
+ * The only time that contextStart != start is for the first run
+ * (the context is the start context of the entire expanse)
+ * The only time that contextLimit != limit is for the last run
+ * (the context is the end context of the entire expanse)
+ */
+ public static class ScriptRunIterator implements RunIterator {
+ private Replaceable text;
+ private Position expanse = new Position();
+ private Position current = new Position();
+ private int script;
+ private boolean done = true;
+
+
+ public void reset(Replaceable repText, Position expansePos) {
+ set(this.expanse, expansePos);
+ this.text = repText;
+ reset();
+ }
+
+ public void reset() {
+ done = false;
+ //this.expanse = expanse;
+ script = UScript.INVALID_CODE;
+ // set up first range to be empty, at beginning
+ current.contextStart = expanse.contextStart;
+ current.start = current.limit = current.contextLimit = expanse.start;
+ }
+
+ public boolean next(Position run) {
+ if (done) return false;
+ if (DEBUG) {
+ System.out.println("+cs: " + current.contextStart
+ + ", s: " + current.start
+ + ", l: " + current.limit
+ + ", cl: " + current.contextLimit);
+ }
+ // reset start context run to the last end
+ current.start = current.limit;
+
+ // Phase 1. Backup the START value through COMMON until we get to expanse.start or a real script.
+ int i, cp;
+ int limit = expanse.start;
+ for (i = current.start; i > limit; i -= UTF16.getCharCount(cp)) {
+ cp = text.char32At(i);
+ int scrpt = UScript.getScript(cp);
+ if (scrpt != UScript.COMMON && scrpt != UScript.INHERITED) break;
+ }
+ current.start = i;
+ current.contextStart = (i == limit) ? expanse.contextStart : i; // extend at start
+
+ // PHASE 2. Move up the LIMIT value through COMMON or single script until we get to expanse.limit
+ int lastScript = UScript.COMMON;
+ //int veryLastScript = UScript.COMMON;
+ limit = expanse.limit;
+ for (i = current.limit; i < limit; i += UTF16.getCharCount(cp)) {
+ cp = text.char32At(i);
+ int scrpt = UScript.getScript(cp);
+ if (scrpt == UScript.INHERITED) scrpt = UScript.COMMON;
+ if (scrpt != UScript.COMMON) {
+ // if we find a real script:
+ // if we already had a script, bail
+ // otherwise set our script
+ if (lastScript == UScript.COMMON) lastScript = scrpt;
+ else if (lastScript != scrpt) break;
+ }
+ }
+ current.limit = i;
+ current.contextLimit = (i == limit) ? expanse.contextLimit : i; // extend at end
+ done = (i == limit);
+ script = lastScript;
+
+ if (DEBUG) {
+ System.out.println("-cs: " + current.contextStart
+ + ", s: " + current.start
+ + ", l: " + current.limit
+ + ", cl: " + current.contextLimit);
+ }
+
+ set(run, current);
+ return true;
+ }
+
+ // SHOULD BE METHOD ON POSITION
+ public static void set(Position run, Position current) {
+ run.contextStart = current.contextStart;
+ run.start = current.start;
+ run.limit = current.limit;
+ run.contextLimit = current.contextLimit;
+ }
+
+ public boolean atEnd() {
+ return current.limit == expanse.limit;
+ }
+
+ public void getCurrent(Position run) {
+ set(run, current);
+ }
+
+ public void getExpanse(Position run) {
+ set(run, expanse);
+ }
+
+ public String getName() {
+ return UScript.getName(script);
+ }
+
+ public void adjust(int newCurrentLimit) {
+ if (expanse == null) {
+ throw new IllegalArgumentException("Must reset() before calling");
+ }
+ int delta = newCurrentLimit - current.limit;
+ current.limit += delta;
+ current.contextLimit += delta;
+ expanse.limit += delta;
+ expanse.contextLimit += delta;
+ }
+
+ // register Any-Script for every script.
+
+ private static Set scriptList = new HashSet();
+
+ public static void registerAnyToScript() {
+ synchronized (scriptList) {
+ Enumeration sources = Transliterator.getAvailableSources();
+ while(sources.hasMoreElements()) {
+ String source = (String) sources.nextElement();
+ if (source.equals("Any")) continue; // to keep from looping
+
+ Enumeration targets = Transliterator.getAvailableTargets(source);
+ while(targets.hasMoreElements()) {
+ String target = (String) targets.nextElement();
+ if (UScript.getCode(target) == null) continue; // SKIP unless we have a script (or locale)
+ if (scriptList.contains(target)) continue; // already encountered
+ scriptList.add(target); // otherwise add for later testing
+
+ Set variantSet = add(new TreeSet(), Transliterator.getAvailableVariants(source, target));
+ if (variantSet.size() < 2) {
+ AnyTransliterator at = new AnyTransliterator(target, null);
+ DummyFactory.add(at.getID(), at);
+ } else {
+ Iterator variants = variantSet.iterator();
+ while(variants.hasNext()) {
+ String variant = (String) variants.next();
+ AnyTransliterator at = new AnyTransliterator(
+ (variant.length() > 0) ? target + "/" + variant : target, null);
+ DummyFactory.add(at.getID(), at);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ static class DummyFactory implements Transliterator.Factory {
+ static DummyFactory singleton = new DummyFactory();
+ static HashMap m = new HashMap();
+
+ // Since Transliterators are immutable, we don't have to clone on set & get
+ static void add(String ID, Transliterator t) {
+ m.put(ID, t);
+ System.out.println("Registering: " + ID + ", " + t.toRules(true));
+ Transliterator.registerFactory(ID, singleton);
+ }
+ public Transliterator getInstance(String ID) {
+ return (Transliterator) m.get(ID);
+ }
+ }
+
+ // Nice little Utility for converting Enumeration to collection
+ static Set add(Set s, Enumeration enumeration) {
+ while(enumeration.hasMoreElements()) {
+ s.add(enumeration.nextElement());
+ }
+ return s;
+ }
+
+
+ }
+}
diff --git a/demos/src/com/ibm/icu/dev/demo/translit/CaseIterator.java b/demos/src/com/ibm/icu/dev/demo/translit/CaseIterator.java
new file mode 100644
index 0000000..b2b477a
--- /dev/null
+++ b/demos/src/com/ibm/icu/dev/demo/translit/CaseIterator.java
@@ -0,0 +1,560 @@
+/**
+*******************************************************************************
+* Copyright (C) 1996-2010, International Business Machines Corporation and *
+* others. All Rights Reserved. *
+*******************************************************************************
+*/
+
+package com.ibm.icu.dev.demo.translit;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+import com.ibm.icu.lang.UCharacter;
+import com.ibm.icu.text.Transliterator;
+import com.ibm.icu.text.UTF16;
+import com.ibm.icu.text.UnicodeSet;
+
+/**
+ * Incrementally returns the set of all strings that case-fold to the same value.
+ */
+public class CaseIterator {
+
+ // testing stuff
+ static Transliterator toName = Transliterator.getInstance("[:^ascii:] Any-Name");
+ static Transliterator toHex = Transliterator.getInstance("[:^ascii:] Any-Hex");
+ static Transliterator toHex2 = Transliterator.getInstance("[[^\u0021-\u007F]-[,]] Any-Hex");
+
+ // global tables (could be precompiled)
+ private static Map fromCaseFold = new HashMap();
+ private static Map toCaseFold = new HashMap();
+ private static int maxLength = 0;
+
+ // This exception list is generated on the console by turning on the GENERATED flag,
+ // which MUST be false for normal operation.
+ // Once the list is generated, it is pasted in here.
+ // A bit of a cludge, but this bootstrapping is the easiest way
+ // to get around certain complications in the data.
+
+ private static final boolean GENERATE = false;
+
+ private static final boolean DUMP = false;
+
+ private static String[][] exceptionList = {
+ // a\N{MODIFIER LETTER RIGHT HALF RING}
+ {"a\u02BE","A\u02BE","a\u02BE",},
+ // ff
+ {"ff","FF","Ff","fF","ff",},
+ // ffi
+ {"ffi","FFI","FFi","FfI","Ffi","F\uFB01","fFI","fFi","ffI","ffi","f\uFB01","\uFB00I","\uFB00i",},
+ // ffl
+ {"ffl","FFL","FFl","FfL","Ffl","F\uFB02","fFL","fFl","ffL","ffl","f\uFB02","\uFB00L","\uFB00l",},
+ // fi
+ {"fi","FI","Fi","fI","fi",},
+ // fl
+ {"fl","FL","Fl","fL","fl",},
+ // h\N{COMBINING MACRON BELOW}
+ {"h\u0331","H\u0331","h\u0331",},
+ // i\N{COMBINING DOT ABOVE}
+ {"i\u0307","I\u0307","i\u0307",},
+ // j\N{COMBINING CARON}
+ {"j\u030C","J\u030C","j\u030C",},
+ // ss
+ {"ss","SS","Ss","S\u017F","sS","ss","s\u017F","\u017FS","\u017Fs","\u017F\u017F",},
+ // st
+ {"st","ST","St","sT","st","\u017FT","\u017Ft",},
+ // t\N{COMBINING DIAERESIS}
+ {"t\u0308","T\u0308","t\u0308",},
+ // w\N{COMBINING RING ABOVE}
+ {"w\u030A","W\u030A","w\u030A",},
+ // y\N{COMBINING RING ABOVE}
+ {"y\u030A","Y\u030A","y\u030A",},
+ // \N{MODIFIER LETTER APOSTROPHE}n
+ {"\u02BCn","\u02BCN","\u02BCn",},
+ // \N{GREEK SMALL LETTER ALPHA WITH TONOS}\N{GREEK SMALL LETTER IOTA}
+ {"\u03AC\u03B9","\u0386\u0345","\u0386\u0399","\u0386\u03B9","\u0386\u1FBE","\u03AC\u0345","\u03AC\u0399","\u03AC\u03B9","\u03AC\u1FBE",},
+ // \N{GREEK SMALL LETTER ETA WITH TONOS}\N{GREEK SMALL LETTER IOTA}
+ {"\u03AE\u03B9","\u0389\u0345","\u0389\u0399","\u0389\u03B9","\u0389\u1FBE","\u03AE\u0345","\u03AE\u0399","\u03AE\u03B9","\u03AE\u1FBE",},
+ // \N{GREEK SMALL LETTER ALPHA}\N{COMBINING GREEK PERISPOMENI}
+ {"\u03B1\u0342","\u0391\u0342","\u03B1\u0342",},
+ // \N{GREEK SMALL LETTER ALPHA}\N{COMBINING GREEK PERISPOMENI}\N{GREEK SMALL LETTER IOTA}
+ {"\u03B1\u0342\u03B9","\u0391\u0342\u0345","\u0391\u0342\u0399","\u0391\u0342\u03B9","\u0391\u0342\u1FBE",
+ "\u03B1\u0342\u0345","\u03B1\u0342\u0399","\u03B1\u0342\u03B9","\u03B1\u0342\u1FBE","\u1FB6\u0345",
+ "\u1FB6\u0399","\u1FB6\u03B9","\u1FB6\u1FBE",},
+ // \N{GREEK SMALL LETTER ALPHA}\N{GREEK SMALL LETTER IOTA}
+ {"\u03B1\u03B9","\u0391\u0345","\u0391\u0399","\u0391\u03B9","\u0391\u1FBE","\u03B1\u0345","\u03B1\u0399","\u03B1\u03B9","\u03B1\u1FBE",},
+ // \N{GREEK SMALL LETTER ETA}\N{COMBINING GREEK PERISPOMENI}
+ {"\u03B7\u0342","\u0397\u0342","\u03B7\u0342",},
+ // \N{GREEK SMALL LETTER ETA}\N{COMBINING GREEK PERISPOMENI}\N{GREEK SMALL LETTER IOTA}
+ {"\u03B7\u0342\u03B9","\u0397\u0342\u0345","\u0397\u0342\u0399","\u0397\u0342\u03B9","\u0397\u0342\u1FBE",
+ "\u03B7\u0342\u0345","\u03B7\u0342\u0399","\u03B7\u0342\u03B9","\u03B7\u0342\u1FBE","\u1FC6\u0345","\u1FC6\u0399",
+ "\u1FC6\u03B9","\u1FC6\u1FBE",},
+ // \N{GREEK SMALL LETTER ETA}\N{GREEK SMALL LETTER IOTA}
+ {"\u03B7\u03B9","\u0397\u0345","\u0397\u0399","\u0397\u03B9","\u0397\u1FBE","\u03B7\u0345","\u03B7\u0399","\u03B7\u03B9","\u03B7\u1FBE",},
+ // \N{GREEK SMALL LETTER IOTA}\N{COMBINING DIAERESIS}\N{COMBINING GRAVE ACCENT}
+ {"\u03B9\u0308\u0300","\u0345\u0308\u0300","\u0399\u0308\u0300","\u03B9\u0308\u0300","\u1FBE\u0308\u0300",},
+ // \N{GREEK SMALL LETTER IOTA}\N{COMBINING DIAERESIS}\N{COMBINING ACUTE ACCENT}
+ {"\u03B9\u0308\u0301","\u0345\u0308\u0301","\u0399\u0308\u0301","\u03B9\u0308\u0301","\u1FBE\u0308\u0301",},
+ // \N{GREEK SMALL LETTER IOTA}\N{COMBINING DIAERESIS}\N{COMBINING GREEK PERISPOMENI}
+ {"\u03B9\u0308\u0342","\u0345\u0308\u0342","\u0399\u0308\u0342","\u03B9\u0308\u0342","\u1FBE\u0308\u0342",},
+ // \N{GREEK SMALL LETTER IOTA}\N{COMBINING GREEK PERISPOMENI}
+ {"\u03B9\u0342","\u0345\u0342","\u0399\u0342","\u03B9\u0342","\u1FBE\u0342",},
+ // \N{GREEK SMALL LETTER RHO}\N{COMBINING COMMA ABOVE}
+ {"\u03C1\u0313","\u03A1\u0313","\u03C1\u0313","\u03F1\u0313",},
+ // \N{GREEK SMALL LETTER UPSILON}\N{COMBINING DIAERESIS}\N{COMBINING GRAVE ACCENT}
+ {"\u03C5\u0308\u0300","\u03A5\u0308\u0300","\u03C5\u0308\u0300",},
+ // \N{GREEK SMALL LETTER UPSILON}\N{COMBINING DIAERESIS}\N{COMBINING ACUTE ACCENT}
+ {"\u03C5\u0308\u0301","\u03A5\u0308\u0301","\u03C5\u0308\u0301",},
+ // \N{GREEK SMALL LETTER UPSILON}\N{COMBINING DIAERESIS}\N{COMBINING GREEK PERISPOMENI}
+ {"\u03C5\u0308\u0342","\u03A5\u0308\u0342","\u03C5\u0308\u0342",},
+ // \N{GREEK SMALL LETTER UPSILON}\N{COMBINING COMMA ABOVE}
+ {"\u03C5\u0313","\u03A5\u0313","\u03C5\u0313",},
+ // \N{GREEK SMALL LETTER UPSILON}\N{COMBINING COMMA ABOVE}\N{COMBINING GRAVE ACCENT}
+ {"\u03C5\u0313\u0300","\u03A5\u0313\u0300","\u03C5\u0313\u0300","\u1F50\u0300",},
+ // \N{GREEK SMALL LETTER UPSILON}\N{COMBINING COMMA ABOVE}\N{COMBINING ACUTE ACCENT}
+ {"\u03C5\u0313\u0301","\u03A5\u0313\u0301","\u03C5\u0313\u0301","\u1F50\u0301",},
+ // \N{GREEK SMALL LETTER UPSILON}\N{COMBINING COMMA ABOVE}\N{COMBINING GREEK PERISPOMENI}
+ {"\u03C5\u0313\u0342","\u03A5\u0313\u0342","\u03C5\u0313\u0342","\u1F50\u0342",},
+ // \N{GREEK SMALL LETTER UPSILON}\N{COMBINING GREEK PERISPOMENI}
+ {"\u03C5\u0342","\u03A5\u0342","\u03C5\u0342",},
+ // \N{GREEK SMALL LETTER OMEGA}\N{COMBINING GREEK PERISPOMENI}
+ {"\u03C9\u0342","\u03A9\u0342","\u03C9\u0342","\u2126\u0342",},
+ // \N{GREEK SMALL LETTER OMEGA}\N{COMBINING GREEK PERISPOMENI}\N{GREEK SMALL LETTER IOTA}
+ {"\u03C9\u0342\u03B9","\u03A9\u0342\u0345","\u03A9\u0342\u0399","\u03A9\u0342\u03B9","\u03A9\u0342\u1FBE","\u03C9\u0342\u0345","\u03C9\u0342\u0399","\u03C9\u0342\u03B9","\u03C9\u0342\u1FBE","\u1FF6\u0345",
+ "\u1FF6\u0399","\u1FF6\u03B9","\u1FF6\u1FBE","\u2126\u0342\u0345","\u2126\u0342\u0399","\u2126\u0342\u03B9","\u2126\u0342\u1FBE",},
+ // \N{GREEK SMALL LETTER OMEGA}\N{GREEK SMALL LETTER IOTA}
+ {"\u03C9\u03B9","\u03A9\u0345","\u03A9\u0399","\u03A9\u03B9","\u03A9\u1FBE","\u03C9\u0345","\u03C9\u0399","\u03C9\u03B9","\u03C9\u1FBE","\u2126\u0345","\u2126\u0399","\u2126\u03B9","\u2126\u1FBE",},
+ // \N{GREEK SMALL LETTER OMEGA WITH TONOS}\N{GREEK SMALL LETTER IOTA}
+ {"\u03CE\u03B9","\u038F\u0345","\u038F\u0399","\u038F\u03B9","\u038F\u1FBE","\u03CE\u0345","\u03CE\u0399","\u03CE\u03B9","\u03CE\u1FBE",},
+ // \N{ARMENIAN SMALL LETTER ECH}\N{ARMENIAN SMALL LETTER YIWN}
+ {"\u0565\u0582","\u0535\u0552","\u0535\u0582","\u0565\u0552","\u0565\u0582",},
+ // \N{ARMENIAN SMALL LETTER MEN}\N{ARMENIAN SMALL LETTER ECH}
+ {"\u0574\u0565","\u0544\u0535","\u0544\u0565","\u0574\u0535","\u0574\u0565",},
+ // \N{ARMENIAN SMALL LETTER MEN}\N{ARMENIAN SMALL LETTER INI}
+ {"\u0574\u056B","\u0544\u053B","\u0544\u056B","\u0574\u053B","\u0574\u056B",},
+ // \N{ARMENIAN SMALL LETTER MEN}\N{ARMENIAN SMALL LETTER XEH}
+ {"\u0574\u056D","\u0544\u053D","\u0544\u056D","\u0574\u053D","\u0574\u056D",},
+ // \N{ARMENIAN SMALL LETTER MEN}\N{ARMENIAN SMALL LETTER NOW}
+ {"\u0574\u0576","\u0544\u0546","\u0544\u0576","\u0574\u0546","\u0574\u0576",},
+ // \N{ARMENIAN SMALL LETTER VEW}\N{ARMENIAN SMALL LETTER NOW}
+ {"\u057E\u0576","\u054E\u0546","\u054E\u0576","\u057E\u0546","\u057E\u0576",},
+ // \N{GREEK SMALL LETTER ALPHA WITH PSILI}\N{GREEK SMALL LETTER IOTA}
+ {"\u1F00\u03B9","\u1F00\u0345","\u1F00\u0399","\u1F00\u03B9","\u1F00\u1FBE","\u1F08\u0345","\u1F08\u0399","\u1F08\u03B9","\u1F08\u1FBE",},
+ // \N{GREEK SMALL LETTER ALPHA WITH DASIA}\N{GREEK SMALL LETTER IOTA}
+ {"\u1F01\u03B9","\u1F01\u0345","\u1F01\u0399","\u1F01\u03B9","\u1F01\u1FBE","\u1F09\u0345","\u1F09\u0399","\u1F09\u03B9","\u1F09\u1FBE",},
+ // \N{GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA}\N{GREEK SMALL LETTER IOTA}
+ {"\u1F02\u03B9","\u1F02\u0345","\u1F02\u0399","\u1F02\u03B9","\u1F02\u1FBE","\u1F0A\u0345","\u1F0A\u0399","\u1F0A\u03B9","\u1F0A\u1FBE",},
+ // \N{GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA}\N{GREEK SMALL LETTER IOTA}
+ {"\u1F03\u03B9","\u1F03\u0345","\u1F03\u0399","\u1F03\u03B9","\u1F03\u1FBE","\u1F0B\u0345","\u1F0B\u0399","\u1F0B\u03B9","\u1F0B\u1FBE",},
+ // \N{GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA}\N{GREEK SMALL LETTER IOTA}
+ {"\u1F04\u03B9","\u1F04\u0345","\u1F04\u0399","\u1F04\u03B9","\u1F04\u1FBE","\u1F0C\u0345","\u1F0C\u0399","\u1F0C\u03B9","\u1F0C\u1FBE",},
+ // \N{GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA}\N{GREEK SMALL LETTER IOTA}
+ {"\u1F05\u03B9","\u1F05\u0345","\u1F05\u0399","\u1F05\u03B9","\u1F05\u1FBE","\u1F0D\u0345","\u1F0D\u0399","\u1F0D\u03B9","\u1F0D\u1FBE",},
+ // \N{GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI}\N{GREEK SMALL LETTER IOTA}
+ {"\u1F06\u03B9","\u1F06\u0345","\u1F06\u0399","\u1F06\u03B9","\u1F06\u1FBE","\u1F0E\u0345","\u1F0E\u0399","\u1F0E\u03B9","\u1F0E\u1FBE",},
+ // \N{GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI}\N{GREEK SMALL LETTER IOTA}
+ {"\u1F07\u03B9","\u1F07\u0345","\u1F07\u0399","\u1F07\u03B9","\u1F07\u1FBE","\u1F0F\u0345","\u1F0F\u0399","\u1F0F\u03B9","\u1F0F\u1FBE",},
+ // \N{GREEK SMALL LETTER ETA WITH PSILI}\N{GREEK SMALL LETTER IOTA}
+ {"\u1F20\u03B9","\u1F20\u0345","\u1F20\u0399","\u1F20\u03B9","\u1F20\u1FBE","\u1F28\u0345","\u1F28\u0399","\u1F28\u03B9","\u1F28\u1FBE",},
+ // \N{GREEK SMALL LETTER ETA WITH DASIA}\N{GREEK SMALL LETTER IOTA}
+ {"\u1F21\u03B9","\u1F21\u0345","\u1F21\u0399","\u1F21\u03B9","\u1F21\u1FBE","\u1F29\u0345","\u1F29\u0399","\u1F29\u03B9","\u1F29\u1FBE",},
+ // \N{GREEK SMALL LETTER ETA WITH PSILI AND VARIA}\N{GREEK SMALL LETTER IOTA}
+ {"\u1F22\u03B9","\u1F22\u0345","\u1F22\u0399","\u1F22\u03B9","\u1F22\u1FBE","\u1F2A\u0345","\u1F2A\u0399","\u1F2A\u03B9","\u1F2A\u1FBE",},
+ // \N{GREEK SMALL LETTER ETA WITH DASIA AND VARIA}\N{GREEK SMALL LETTER IOTA}
+ {"\u1F23\u03B9","\u1F23\u0345","\u1F23\u0399","\u1F23\u03B9","\u1F23\u1FBE","\u1F2B\u0345","\u1F2B\u0399","\u1F2B\u03B9","\u1F2B\u1FBE",},
+ // \N{GREEK SMALL LETTER ETA WITH PSILI AND OXIA}\N{GREEK SMALL LETTER IOTA}
+ {"\u1F24\u03B9","\u1F24\u0345","\u1F24\u0399","\u1F24\u03B9","\u1F24\u1FBE","\u1F2C\u0345","\u1F2C\u0399","\u1F2C\u03B9","\u1F2C\u1FBE",},
+ // \N{GREEK SMALL LETTER ETA WITH DASIA AND OXIA}\N{GREEK SMALL LETTER IOTA}
+ {"\u1F25\u03B9","\u1F25\u0345","\u1F25\u0399","\u1F25\u03B9","\u1F25\u1FBE","\u1F2D\u0345","\u1F2D\u0399","\u1F2D\u03B9","\u1F2D\u1FBE",},
+ // \N{GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI}\N{GREEK SMALL LETTER IOTA}
+ {"\u1F26\u03B9","\u1F26\u0345","\u1F26\u0399","\u1F26\u03B9","\u1F26\u1FBE","\u1F2E\u0345","\u1F2E\u0399","\u1F2E\u03B9","\u1F2E\u1FBE",},
+ // \N{GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI}\N{GREEK SMALL LETTER IOTA}
+ {"\u1F27\u03B9","\u1F27\u0345","\u1F27\u0399","\u1F27\u03B9","\u1F27\u1FBE","\u1F2F\u0345","\u1F2F\u0399","\u1F2F\u03B9","\u1F2F\u1FBE",},
+ // \N{GREEK SMALL LETTER OMEGA WITH PSILI}\N{GREEK SMALL LETTER IOTA}
+ {"\u1F60\u03B9","\u1F60\u0345","\u1F60\u0399","\u1F60\u03B9","\u1F60\u1FBE","\u1F68\u0345","\u1F68\u0399","\u1F68\u03B9","\u1F68\u1FBE",},
+ // \N{GREEK SMALL LETTER OMEGA WITH DASIA}\N{GREEK SMALL LETTER IOTA}
+ {"\u1F61\u03B9","\u1F61\u0345","\u1F61\u0399","\u1F61\u03B9","\u1F61\u1FBE","\u1F69\u0345","\u1F69\u0399","\u1F69\u03B9","\u1F69\u1FBE",},
+ // \N{GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA}\N{GREEK SMALL LETTER IOTA}
+ {"\u1F62\u03B9","\u1F62\u0345","\u1F62\u0399","\u1F62\u03B9","\u1F62\u1FBE","\u1F6A\u0345","\u1F6A\u0399","\u1F6A\u03B9","\u1F6A\u1FBE",},
+ // \N{GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA}\N{GREEK SMALL LETTER IOTA}
+ {"\u1F63\u03B9","\u1F63\u0345","\u1F63\u0399","\u1F63\u03B9","\u1F63\u1FBE","\u1F6B\u0345","\u1F6B\u0399","\u1F6B\u03B9","\u1F6B\u1FBE",},
+ // \N{GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA}\N{GREEK SMALL LETTER IOTA}
+ {"\u1F64\u03B9","\u1F64\u0345","\u1F64\u0399","\u1F64\u03B9","\u1F64\u1FBE","\u1F6C\u0345","\u1F6C\u0399","\u1F6C\u03B9","\u1F6C\u1FBE",},
+ // \N{GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA}\N{GREEK SMALL LETTER IOTA}
+ {"\u1F65\u03B9","\u1F65\u0345","\u1F65\u0399","\u1F65\u03B9","\u1F65\u1FBE","\u1F6D\u0345","\u1F6D\u0399","\u1F6D\u03B9","\u1F6D\u1FBE",},
+ // \N{GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI}\N{GREEK SMALL LETTER IOTA}
+ {"\u1F66\u03B9","\u1F66\u0345","\u1F66\u0399","\u1F66\u03B9","\u1F66\u1FBE","\u1F6E\u0345","\u1F6E\u0399","\u1F6E\u03B9","\u1F6E\u1FBE",},
+ // \N{GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI}\N{GREEK SMALL LETTER IOTA}
+ {"\u1F67\u03B9","\u1F67\u0345","\u1F67\u0399","\u1F67\u03B9","\u1F67\u1FBE","\u1F6F\u0345","\u1F6F\u0399","\u1F6F\u03B9","\u1F6F\u1FBE",},
+ // \N{GREEK SMALL LETTER ALPHA WITH VARIA}\N{GREEK SMALL LETTER IOTA}
+ {"\u1F70\u03B9","\u1F70\u0345","\u1F70\u0399","\u1F70\u03B9","\u1F70\u1FBE","\u1FBA\u0345","\u1FBA\u0399","\u1FBA\u03B9","\u1FBA\u1FBE",},
+ // \N{GREEK SMALL LETTER ETA WITH VARIA}\N{GREEK SMALL LETTER IOTA}
+ {"\u1F74\u03B9","\u1F74\u0345","\u1F74\u0399","\u1F74\u03B9","\u1F74\u1FBE","\u1FCA\u0345","\u1FCA\u0399","\u1FCA\u03B9","\u1FCA\u1FBE",},
+ // \N{GREEK SMALL LETTER OMEGA WITH VARIA}\N{GREEK SMALL LETTER IOTA}
+ {"\u1F7C\u03B9","\u1F7C\u0345","\u1F7C\u0399","\u1F7C\u03B9","\u1F7C\u1FBE","\u1FFA\u0345","\u1FFA\u0399","\u1FFA\u03B9","\u1FFA\u1FBE",},
+ };
+
+ // this initializes the data used to generated the case-equivalents
+
+ static {
+
+ // Gather up the exceptions in a form we can use
+
+ if (!GENERATE) {
+ for (int i = 0; i < exceptionList.length; ++i) {
+ String[] exception = exceptionList[i];
+ Set s = new HashSet();
+ // there has to be some method to do the following, but I can't find it in the collections
+ for (int j = 0; j < exception.length; ++j) {
+ s.add(exception[j]);
+ }
+ fromCaseFold.put(exception[0], s);
+ }
+ }
+
+ // walk through all the characters, and at every case fold result,
+ // put a set of all the characters that map to that result
+
+ boolean defaultmapping = true; // false for turkish
+ for (int i = 0; i <= 0x10FFFF; ++i) {
+ int cat = UCharacter.getType(i);
+ if (cat == Character.UNASSIGNED || cat == Character.PRIVATE_USE) continue;
+
+ String cp = UTF16.valueOf(i);
+ String mapped = UCharacter.foldCase(cp, defaultmapping);
+ if (mapped.equals(cp)) continue;
+
+ if (maxLength < mapped.length()) maxLength = mapped.length();
+
+ // at this point, have different case folding
+
+ Set s = (Set) fromCaseFold.get(mapped);
+ if (s == null) {
+ s = new HashSet();
+ s.add(mapped); // add the case fold result itself
+ fromCaseFold.put(mapped, s);
+ }
+ s.add(cp);
+ toCaseFold.put(cp, mapped);
+ toCaseFold.put(mapped, mapped); // add mapping to self
+ }
+
+ // Emit the final data
+
+ if (DUMP) {
+ System.out.println("maxLength = " + maxLength);
+
+ System.out.println("\nfromCaseFold:");
+ Iterator it = fromCaseFold.keySet().iterator();
+ while (it.hasNext()) {
+ Object key = it.next();
+ System.out.print(" " + toHex2.transliterate((String)key) + ": ");
+ Set s = (Set) fromCaseFold.get(key);
+ Iterator it2 = s.iterator();
+ boolean first = true;
+ while (it2.hasNext()) {
+ if (first) {
+ first = false;
+ } else {
+ System.out.print(", ");
+ }
+ System.out.print(toHex2.transliterate((String)it2.next()));
+ }
+ System.out.println("");
+ }
+
+ System.out.println("\ntoCaseFold:");
+ it = toCaseFold.keySet().iterator();
+ while (it.hasNext()) {
+ String key = (String) it.next();
+ String value = (String) toCaseFold.get(key);
+ System.out.println(" " + toHex2.transliterate(key) + ": " + toHex2.transliterate(value));
+ }
+ }
+
+ // Now convert all those sets into linear arrays
+ // We can't do this in place in Java, so make a temporary target array
+
+ // Note: This could be transformed into a single array, with offsets into it.
+ // Might be best choice in C.
+
+
+ Map fromCaseFold2 = new HashMap();
+ Iterator it = fromCaseFold.keySet().iterator();
+ while (it.hasNext()) {
+ Object key = it.next();
+ Set s = (Set) fromCaseFold.get(key);
+ String[] temp = new String[s.size()];
+ s.toArray(temp);
+ fromCaseFold2.put(key, temp);
+ }
+ fromCaseFold = fromCaseFold2;
+
+ // We have processed everything, so the iterator will now work
+ // The following is normally OFF.
+ // It is here to generate (under the GENERATE flag) the static exception list.
+ // It must be at the very end of initialization, so that the iterator is functional.
+ // (easiest to do it that way)
+
+ if (GENERATE) {
+
+ // first get small set of items that have multiple characters
+
+ Set multichars = new TreeSet();
+ it = fromCaseFold.keySet().iterator();
+ while (it.hasNext()) {
+ String key = (String) it.next();
+ if (UTF16.countCodePoint(key) < 2) continue;
+ multichars.add(key);
+ }
+
+ // now we will go through each of them.
+
+ CaseIterator ci = new CaseIterator();
+ it = multichars.iterator();
+
+ while (it.hasNext()) {
+ String key = (String) it.next();
+
+ // here is a nasty complication. Take 'ffi' ligature. We
+ // can't just close it, since we would miss the combination
+ // that includes the 'fi' => "fi" ligature
+ // so first do a pass through, and add substring combinations
+ // we call this a 'partial closure'
+
+ Set partialClosure = new TreeSet();
+ partialClosure.add(key);
+
+ if (UTF16.countCodePoint(key) > 2) {
+ Iterator multiIt2 = multichars.iterator();
+ while (multiIt2.hasNext()) {
+ String otherKey = (String) multiIt2.next();
+ if (otherKey.length() >= key.length()) continue;
+ int pos = -1;
+ while (true) {
+ // The following is not completely general
+ // but works for the actual cased stuff,
+ // and should work for future characters, since we won't have
+ // more ligatures & other oddities.
+ pos = key.indexOf(otherKey, pos+1);
+ if (pos < 0) break;
+ int endPos = pos + otherKey.length();
+ // we know we have a proper substring,
+ // so get the combinations
+ String[] choices = (String[]) fromCaseFold.get(otherKey);
+ for (int ii = 0; ii < choices.length; ++ii) {
+ String patchwork = key.substring(0, pos)
+ + choices[ii]
+ + key.substring(endPos);
+ partialClosure.add(patchwork);
+ }
+ }
+ }
+ }
+
+ // now, for each thing in the partial closure, get its
+ // case closure and add it to the final result.
+
+ Set closure = new TreeSet(); // this will be the real closure
+ Iterator partialIt = partialClosure.iterator();
+ while (partialIt.hasNext()) {
+ String key2 = (String) partialIt.next();
+ ci.reset(key2);
+ for (String temp = ci.next(); temp != null; temp = ci.next()) {
+ closure.add(temp);
+ }
+ // form closure
+ /*String[] choices = (String[]) fromCaseFold.get(key2);
+ for (int i = 0; i < choices.length; ++i) {
+ ci.reset(choices[i]);
+ String temp;
+ while (null != (temp = ci.next())) {
+ closure.add(temp);
+ }
+ }
+ */
+ }
+
+ // print it out, so that it can be cut and pasted back into this document.
+
+ Iterator it2 = closure.iterator();
+ System.out.println("\t// " + toName.transliterate(key));
+ System.out.print("\t{\"" + toHex.transliterate(key) + "\",");
+ while (it2.hasNext()) {
+ String item = (String)it2.next();
+ System.out.print("\"" + toHex.transliterate(item) + "\",");
+ }
+ System.out.println("},");
+ }
+ }
+ }
+
+ // ============ PRIVATE CLASS DATA ============
+
+ // pieces that we will put together
+ // is not changed during iteration
+ private int count = 0;
+ private String[][] variants;
+
+ // state information, changes during iteration
+ private boolean done = false;
+ private int[] counts;
+
+ // internal buffer for efficiency
+ private StringBuffer nextBuffer = new StringBuffer();
+
+ // ========================
+
+ /**
+ * Reset to different source. Once reset, the iteration starts from the beginning.
+ * @param source The string to get case variants for
+ */
+ public void reset(String source) {
+
+ // allocate arrays to store pieces
+ // using length might be slightly too long, but we don't care much
+
+ counts = new int[source.length()];
+ variants = new String[source.length()][];
+
+ // walk through the source, and break up into pieces
+ // each piece becomes an array of equivalent values
+ // TODO: could optimized this later to coalesce all single string pieces
+
+ String piece = null;
+ count = 0;
+ for (int i = 0; i < source.length(); i += piece.length()) {
+
+ // find *longest* matching piece
+ String caseFold = null;
+
+ if (GENERATE) {
+ // do exactly one CP
+ piece = UTF16.valueOf(source, i);
+ caseFold = (String) toCaseFold.get(piece);
+ } else {
+ int max = i + maxLength;
+ if (max > source.length()) max = source.length();
+ for (int j = max; j > i; --j) {
+ piece = source.substring(i, j);
+ caseFold = (String) toCaseFold.get(piece);
+ if (caseFold != null) break;
+ }
+ }
+
+ // if we fail, pick one code point
+ if (caseFold == null) {
+ piece = UTF16.valueOf(source, i);
+ variants[count++] = new String[] {piece}; // single item string
+ } else {
+ variants[count++] = (String[])fromCaseFold.get(caseFold);
+ }
+ }
+ reset();
+ }
+
+ /**
+ * Restart the iteration from the beginning, but with same source
+ */
+ public void reset() {
+ done = false;
+ for (int i = 0; i < count; ++i) {
+ counts[i] = 0;
+ }
+ }
+
+ /**
+ * Iterates through the case variants.
+ * @return next case variant. Each variant will case-fold to the same value as the source will.
+ * When the iteration is done, null is returned.
+ */
+ public String next() {
+
+ if (done) return null;
+ int i;
+
+ // TODO Optimize so we keep the piece before and after the current position
+ // so we don't have so much concatenation
+
+ // get the result, a concatenation
+
+ nextBuffer.setLength(0);
+ for (i = 0; i < count; ++i) {
+ nextBuffer.append(variants[i][counts[i]]);
+ }
+
+ // find the next right set of pieces to concatenate
+
+ for (i = count-1; i >= 0; --i) {
+ counts[i]++;
+ if (counts[i] < variants[i].length) break;
+ counts[i] = 0;
+ }
+
+ // if we go too far, bail
+
+ if (i < 0) {
+ done = true;
+ }
+
+ return nextBuffer.toString();
+ }
+
+
+ /**
+ * Temporary test, just to see how the stuff works.
+ */
+ static public void main(String[] args) {
+ String[] testCases = {"fiss", "h\u03a3"};
+ CaseIterator ci = new CaseIterator();
+
+ for (int i = 0; i < testCases.length; ++i) {
+ String item = testCases[i];
+ System.out.println();
+ System.out.println("Testing: " + toName.transliterate(item));
+ System.out.println();
+ ci.reset(item);
+ int count = 0;
+ for (String temp = ci.next(); temp != null; temp = ci.next()) {
+ System.out.println(toName.transliterate(temp));
+ count++;
+ }
+ System.out.println("Total: " + count);
+ }
+
+ // generate a list of all caseless characters -- characters whose
+ // case closure is themselves.
+
+ UnicodeSet caseless = new UnicodeSet();
+
+ for (int i = 0; i <= 0x10FFFF; ++i) {
+ String cp = UTF16.valueOf(i);
+ ci.reset(cp);
+ int count = 0;
+ String fold = null;
+ for (String temp = ci.next(); temp != null; temp = ci.next()) {
+ fold = temp;
+ if (++count > 1) break;
+ }
+ if (count==1 && fold.equals(cp)) {
+ caseless.add(i);
+ }
+ }
+
+ System.out.println("caseless = " + caseless.toPattern(true));
+
+ UnicodeSet not_lc = new UnicodeSet("[:^lc:]");
+
+ UnicodeSet a = new UnicodeSet();
+ a.set(not_lc);
+ a.removeAll(caseless);
+ System.out.println("[:^lc:] - caseless = " + a.toPattern(true));
+
+ a.set(caseless);
+ a.removeAll(not_lc);
+ System.out.println("caseless - [:^lc:] = " + a.toPattern(true));
+ }
+}
diff --git a/demos/src/com/ibm/icu/dev/demo/translit/Demo.java b/demos/src/com/ibm/icu/dev/demo/translit/Demo.java
new file mode 100644
index 0000000..70d5e9c
--- /dev/null
+++ b/demos/src/com/ibm/icu/dev/demo/translit/Demo.java
@@ -0,0 +1,1426 @@
+/*
+ *******************************************************************************
+ * Copyright (C) 1996-2012, International Business Machines Corporation and *
+ * others. All Rights Reserved. *
+ *******************************************************************************
+ */
+package com.ibm.icu.dev.demo.translit;
+
+import java.awt.Button;
+import java.awt.CheckboxMenuItem;
+import java.awt.FileDialog;
+import java.awt.Font;
+import java.awt.Frame;
+import java.awt.GraphicsEnvironment;
+import java.awt.Label;
+import java.awt.Menu;
+import java.awt.MenuBar;
+import java.awt.MenuItem;
+import java.awt.MenuShortcut;
+import java.awt.TextField;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.awt.event.KeyEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.text.CharacterIterator;
+import java.util.Comparator;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+import com.ibm.icu.impl.Differ;
+import com.ibm.icu.lang.UCharacter;
+import com.ibm.icu.text.BreakIterator;
+import com.ibm.icu.text.CanonicalIterator;
+import com.ibm.icu.text.Normalizer;
+import com.ibm.icu.text.ReplaceableString;
+import com.ibm.icu.text.Transliterator;
+import com.ibm.icu.text.UTF16;
+import com.ibm.icu.text.UnicodeSet;
+import com.ibm.icu.text.UnicodeSetIterator;
+
+/**
+ * A frame that allows the user to experiment with keyboard
+ * transliteration. This class has a main() method so it can be run
+ * as an application. The frame contains an editable text component
+ * and uses keyboard transliteration to process keyboard events.
+ *
+ * <p>Copyright (c) IBM Corporation 1999. All rights reserved.
+ *
+ * @author Alan Liu
+ */
+public class Demo extends Frame {
+
+ /**
+ * For serialization
+ */
+ private static final long serialVersionUID = 1L;
+ static final boolean DEBUG = false;
+ static final String START_TEXT = "(cut,\u03BA\u03C5\u03C4,\u05D0,\u30AF\u30C8,\u4E80,\u091A\u0941\u0924\u094D)";
+
+ Transliterator translit = null;
+ String fontName = "Arial Unicode MS";
+ int fontSize = 18;
+
+
+
+ /*
+ boolean compound = false;
+ Transliterator[] compoundTranslit = new Transliterator[MAX_COMPOUND];
+ static final int MAX_COMPOUND = 128;
+ int compoundCount = 0;
+ */
+
+ TransliteratingTextComponent text = null;
+
+ Menu translitMenu;
+ CheckboxMenuItem translitItem;
+ CheckboxMenuItem noTranslitItem;
+
+ static final String NO_TRANSLITERATOR = "None";
+
+ //private static final String COPYRIGHT =
+ // "\u00A9 IBM Corporation 1999. All rights reserved.";
+
+ public static void main(String[] args) {
+ Frame f = new Demo(600, 200);
+ f.addWindowListener(new WindowAdapter() {
+ public void windowClosing(WindowEvent e) {
+ com.ibm.icu.dev.demo.impl.DemoApplet.demoFrameClosed();
+// System.exit(0);
+ }
+ });
+ f.setVisible(true);
+ com.ibm.icu.dev.demo.impl.DemoApplet.demoFrameOpened();
+ }
+
+ public Demo(int width, int height) {
+ super("Transliteration Demo");
+
+ initMenus();
+
+ addWindowListener(new WindowAdapter() {
+ public void windowClosing(WindowEvent e) {
+ handleClose();
+ }
+ });
+
+ text = new TransliteratingTextComponent();
+ Font font = new Font(fontName, Font.PLAIN, fontSize);
+ text.setFont(font);
+ text.setSize(width, height);
+ text.setVisible(true);
+ text.setText(START_TEXT);
+ add(text);
+
+ setSize(width, height);
+ setTransliterator("Latin-Greek", null);
+ }
+
+ private void initMenus() {
+ MenuBar mbar;
+ Menu menu;
+ MenuItem mitem;
+ //CheckboxMenuItem citem;
+
+ setMenuBar(mbar = new MenuBar());
+ mbar.add(menu = new Menu("File"));
+ menu.add(mitem = new MenuItem("Quit"));
+ mitem.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ handleClose();
+ }
+ });
+/*
+ final ItemListener setTransliteratorListener = new ItemListener() {
+ public void itemStateChanged(ItemEvent e) {
+ CheckboxMenuItem item = (CheckboxMenuItem) e.getSource();
+ if (e.getStateChange() == ItemEvent.DESELECTED) {
+ // Don't let the current transliterator be deselected.
+ // Just reselect it.
+ item.setState(true);
+ } else if (compound) {
+ // Adding an item to a compound transliterator
+ handleAddToCompound(item.getLabel());
+ } else if (item != translitItem) {
+ // Deselect previous choice. Don't need to call
+ // setState(true) on new choice.
+ translitItem.setState(false);
+ translitItem = item;
+ handleSetTransliterator(item.getLabel());
+ }
+ }
+ };
+*/
+ /*
+ translitMenu.add(translitItem = noTranslitItem =
+ new CheckboxMenuItem(NO_TRANSLITERATOR, true));
+ noTranslitItem.addItemListener(new ItemListener() {
+ public void itemStateChanged(ItemEvent e) {
+ // Can't uncheck None -- any action here sets None to true
+ setNoTransliterator();
+ }
+ });
+
+ translitMenu.addSeparator();
+ */
+
+/*
+ translitMenu.add(citem = new CheckboxMenuItem("Compound"));