summaryrefslogtreecommitdiff
path: root/icu4j/samples/src/main/java/com/ibm/icu
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2024-03-28 17:54:57 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2024-03-28 17:54:57 +0000
commiteb3451793aaf42870e44281708ccac51c010e837 (patch)
tree51c5f3646653b5153a74a2828b2af20c41cbd8d1 /icu4j/samples/src/main/java/com/ibm/icu
parente710c4fbd23e1b7d97da0a88a8499326861ad250 (diff)
parent8144ba71b4efcfe46cd0e76e85d371bcc7d55567 (diff)
downloadicu-eb3451793aaf42870e44281708ccac51c010e837.tar.gz
Snap for 11641499 from 8144ba71b4efcfe46cd0e76e85d371bcc7d55567 to build-tools-release
Change-Id: Ic926bb7ff166e37b678ae2768581ebec18fcea4a
Diffstat (limited to 'icu4j/samples/src/main/java/com/ibm/icu')
-rw-r--r--icu4j/samples/src/main/java/com/ibm/icu/samples/iuc/PopulationData.java79
-rw-r--r--icu4j/samples/src/main/java/com/ibm/icu/samples/iuc/Sample13_Hello.java24
-rw-r--r--icu4j/samples/src/main/java/com/ibm/icu/samples/iuc/Sample30_ResHello.java29
-rw-r--r--icu4j/samples/src/main/java/com/ibm/icu/samples/iuc/Sample40_PopMsg.java64
-rw-r--r--icu4j/samples/src/main/java/com/ibm/icu/samples/iuc/Sample50_PopSort.java76
-rw-r--r--icu4j/samples/src/main/java/com/ibm/icu/samples/iuc/SupplementalUtilities.java84
-rw-r--r--icu4j/samples/src/main/java/com/ibm/icu/samples/iuc/package-info.java15
-rw-r--r--icu4j/samples/src/main/java/com/ibm/icu/samples/shaping/ArabicShapingSample.java288
-rw-r--r--icu4j/samples/src/main/java/com/ibm/icu/samples/text/dateintervalformat/DateIntervalFormatSample.java126
-rw-r--r--icu4j/samples/src/main/java/com/ibm/icu/samples/text/datetimepatterngenerator/DateTimePatternGeneratorSample.java185
-rw-r--r--icu4j/samples/src/main/java/com/ibm/icu/samples/text/messagepattern/MessagePatternDemo.java125
-rw-r--r--icu4j/samples/src/main/java/com/ibm/icu/samples/text/messagepattern/MessagePatternUtilDemo.java409
-rw-r--r--icu4j/samples/src/main/java/com/ibm/icu/samples/text/messagepattern/MiniMessageFormatter.java188
-rw-r--r--icu4j/samples/src/main/java/com/ibm/icu/samples/text/pluralformat/PluralFormatSample.java97
-rw-r--r--icu4j/samples/src/main/java/com/ibm/icu/samples/util/timescale/PivotDemo.java80
-rw-r--r--icu4j/samples/src/main/java/com/ibm/icu/samples/util/timezone/BasicTimeZoneExample.java131
16 files changed, 2000 insertions, 0 deletions
diff --git a/icu4j/samples/src/main/java/com/ibm/icu/samples/iuc/PopulationData.java b/icu4j/samples/src/main/java/com/ibm/icu/samples/iuc/PopulationData.java
new file mode 100644
index 000000000..07109667f
--- /dev/null
+++ b/icu4j/samples/src/main/java/com/ibm/icu/samples/iuc/PopulationData.java
@@ -0,0 +1,79 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+/*
+ *******************************************************************************
+ * Copyright (C) 2013-2014, International Business Machines Corporation and *
+ * others. All Rights Reserved. *
+ *******************************************************************************
+ */
+package com.ibm.icu.samples.iuc;
+
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Set;
+
+import com.ibm.icu.text.NumberFormat;
+import com.ibm.icu.util.ULocale;
+import com.ibm.icu.util.UResourceBundle;
+import com.ibm.icu.util.UResourceBundleIterator;
+
+/**
+ * @author srl
+ *
+ */
+public class PopulationData {
+ /**
+ * Entry in the population list
+ */
+ public static class TerritoryEntry implements Comparable<TerritoryEntry> {
+ private String territoryName;
+ private double population;
+ public TerritoryEntry(String displayCountry, double population) {
+ this.territoryName = displayCountry;
+ this.population = population;
+ }
+ public String territoryName() {
+ return territoryName;
+ }
+ public double population() {
+ return population;
+ }
+ /* (non-Javadoc)
+ * @see java.lang.Comparable#compareTo(java.lang.Object)
+ */
+ public int compareTo(TerritoryEntry o) {
+ int rc = 0;
+ if (rc==0) rc = territoryName.compareTo(o.territoryName());
+ if (rc==0) rc = ((Double)population).compareTo(o.population());
+ return rc;
+ }
+ };
+ public static Set<TerritoryEntry> getTerritoryEntries(Locale loc, Set<TerritoryEntry> entries) {
+ // Note: format of supplementalData is NOT STATIC and may change. It is internal to ICU!
+ UResourceBundle suppData = SupplementalUtilities.getICUSupplementalData();
+ UResourceBundle territoryInfo = suppData.get("territoryInfo");
+// int nTerr = territoryInfo.getSize();
+ for(UResourceBundleIterator iter = territoryInfo.getIterator();iter.hasNext();) {
+ UResourceBundle rawEntry= iter.next();
+ UResourceBundle territoryF = rawEntry.get("territoryF");
+ int vec[] = territoryF.getIntVector();
+
+ // now we have the entry
+ // territoryF = { gdp, literacy, population }
+ String terrID = rawEntry.getKey();
+ ULocale territory = new ULocale("und", terrID);
+ entries.add(new TerritoryEntry(territory.getDisplayCountry(ULocale.forLocale(loc)), SupplementalUtilities.ldml2d(vec[2])));
+ }
+ return entries;
+ }
+
+ public static void main(String... args) {
+ NumberFormat nf = NumberFormat.getInstance();
+ System.out.println("Loading population/territory data from CLDR");
+ Set<TerritoryEntry> territoryEntries = getTerritoryEntries(Locale.getDefault(), new HashSet<TerritoryEntry>());
+ System.out.println(".. count="+ nf.format(territoryEntries.size()));
+ for(TerritoryEntry te : territoryEntries) {
+ System.out.println(" "+ te.territoryName() + " = " + nf.format(te.population()));
+ }
+ }
+}
diff --git a/icu4j/samples/src/main/java/com/ibm/icu/samples/iuc/Sample13_Hello.java b/icu4j/samples/src/main/java/com/ibm/icu/samples/iuc/Sample13_Hello.java
new file mode 100644
index 000000000..dfb7509c5
--- /dev/null
+++ b/icu4j/samples/src/main/java/com/ibm/icu/samples/iuc/Sample13_Hello.java
@@ -0,0 +1,24 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+/*
+ *******************************************************************************
+ * Copyright (C) 2013-2014, International Business Machines Corporation and *
+ * others. All Rights Reserved. *
+ *******************************************************************************
+ */
+package com.ibm.icu.samples.iuc;
+
+import java.util.Locale;
+
+import com.ibm.icu.text.LocaleDisplayNames;
+import com.ibm.icu.util.ULocale;
+
+public class Sample13_Hello {
+ public static void main(String... args) {
+ Locale locale = Locale.getDefault();
+ String world = LocaleDisplayNames
+ .getInstance(ULocale.forLocale(locale))
+ .regionDisplayName("001");
+ System.out.println("Hello, " + world + "\u2603");
+ }
+}
diff --git a/icu4j/samples/src/main/java/com/ibm/icu/samples/iuc/Sample30_ResHello.java b/icu4j/samples/src/main/java/com/ibm/icu/samples/iuc/Sample30_ResHello.java
new file mode 100644
index 000000000..8d91a94eb
--- /dev/null
+++ b/icu4j/samples/src/main/java/com/ibm/icu/samples/iuc/Sample30_ResHello.java
@@ -0,0 +1,29 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+/*
+ *******************************************************************************
+ * Copyright (C) 2013-2014, International Business Machines Corporation and *
+ * others. All Rights Reserved. *
+ *******************************************************************************
+ */
+package com.ibm.icu.samples.iuc;
+
+import java.util.Locale;
+
+import com.ibm.icu.util.UResourceBundle;
+
+/**
+ * @author srl
+ *
+ */
+public class Sample30_ResHello {
+ public static void main(String... args) {
+ Locale locale = Locale.getDefault();
+ UResourceBundle bundle =
+ UResourceBundle.getBundleInstance(
+ Sample30_ResHello.class.getPackage().getName().replace('.', '/')+"/data/reshello",
+ locale,
+ Sample30_ResHello.class.getClassLoader());
+ System.out.println(bundle.getString("hello"));
+ }
+}
diff --git a/icu4j/samples/src/main/java/com/ibm/icu/samples/iuc/Sample40_PopMsg.java b/icu4j/samples/src/main/java/com/ibm/icu/samples/iuc/Sample40_PopMsg.java
new file mode 100644
index 000000000..2de898920
--- /dev/null
+++ b/icu4j/samples/src/main/java/com/ibm/icu/samples/iuc/Sample40_PopMsg.java
@@ -0,0 +1,64 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+/*
+ *******************************************************************************
+ * Copyright (C) 2013-2014, International Business Machines Corporation and *
+ * others. All Rights Reserved. *
+ *******************************************************************************
+ */
+package com.ibm.icu.samples.iuc;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+import com.ibm.icu.samples.iuc.PopulationData.TerritoryEntry;
+import com.ibm.icu.text.LocaleDisplayNames;
+import com.ibm.icu.text.LocaleDisplayNames.DialectHandling;
+import com.ibm.icu.text.MessageFormat;
+import com.ibm.icu.util.ULocale;
+import com.ibm.icu.util.UResourceBundle;
+
+/**
+ * @author srl
+ *
+ */
+public class Sample40_PopMsg {
+ public static void main(String... args) {
+ // setup
+ Locale defaultLocaleID = Locale.getDefault();
+ LocaleDisplayNames ldn = LocaleDisplayNames.getInstance(ULocale.forLocale(defaultLocaleID),
+ DialectHandling.DIALECT_NAMES);
+ String defaultLocaleName = ldn.localeDisplayName(defaultLocaleID);
+
+ Set<PopulationData.TerritoryEntry> territoryList;
+ territoryList = PopulationData.getTerritoryEntries(defaultLocaleID,
+ new HashSet<TerritoryEntry>());
+ int territoryCount = territoryList.size();
+ UResourceBundle resourceBundle =
+ UResourceBundle.getBundleInstance(
+ Sample40_PopMsg.class.getPackage().getName().replace('.', '/')+"/data/popmsg",
+ defaultLocaleID,
+ Sample40_PopMsg.class.getClassLoader());
+
+ // say hello
+ String pattern = resourceBundle.getString("welcome");
+ MessageFormat fmt = new MessageFormat(pattern,defaultLocaleID);
+ Map<String, Object> msgargs = new HashMap<String, Object>();
+ msgargs.put("territoryCount", territoryCount);
+ msgargs.put("myLanguage", defaultLocaleName);
+ msgargs.put("today", System.currentTimeMillis());
+ System.out.println(fmt.format(msgargs, new StringBuffer(), null));
+
+ // Population roll call
+ String info = resourceBundle.getString("info");
+ Map<String, Object> infoArgs = new HashMap<String, Object>();
+ for(PopulationData.TerritoryEntry entry : territoryList) {
+ infoArgs.put("territory", entry.territoryName());
+ infoArgs.put("population", entry.population());
+ System.out.println(MessageFormat.format(info, infoArgs));
+ }
+ }
+}
diff --git a/icu4j/samples/src/main/java/com/ibm/icu/samples/iuc/Sample50_PopSort.java b/icu4j/samples/src/main/java/com/ibm/icu/samples/iuc/Sample50_PopSort.java
new file mode 100644
index 000000000..97a14a138
--- /dev/null
+++ b/icu4j/samples/src/main/java/com/ibm/icu/samples/iuc/Sample50_PopSort.java
@@ -0,0 +1,76 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+/*
+ *******************************************************************************
+ * Copyright (C) 2013-2014, International Business Machines Corporation and *
+ * others. All Rights Reserved. *
+ *******************************************************************************
+ */
+package com.ibm.icu.samples.iuc;
+
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+import com.ibm.icu.samples.iuc.PopulationData.TerritoryEntry;
+import com.ibm.icu.text.Collator;
+import com.ibm.icu.text.LocaleDisplayNames;
+import com.ibm.icu.text.LocaleDisplayNames.DialectHandling;
+import com.ibm.icu.text.MessageFormat;
+import com.ibm.icu.util.ULocale;
+import com.ibm.icu.util.UResourceBundle;
+
+/**
+ * @author srl
+ *
+ */
+public class Sample50_PopSort {
+ public static void main(String... args) {
+ // setup
+ // setup
+ Locale defaultLocaleID = Locale.getDefault();
+ LocaleDisplayNames ldn = LocaleDisplayNames.getInstance(ULocale.forLocale(defaultLocaleID),
+ DialectHandling.DIALECT_NAMES);
+ String defaultLocaleName = ldn.localeDisplayName(defaultLocaleID);
+
+ Set<PopulationData.TerritoryEntry> territoryList;
+ territoryList = PopulationData.getTerritoryEntries(defaultLocaleID,
+ new HashSet<TerritoryEntry>());
+ int territoryCount = territoryList.size();
+
+ // sort it
+ final Collator collator = Collator.getInstance(defaultLocaleID);
+ territoryList = PopulationData.getTerritoryEntries(defaultLocaleID,
+ new TreeSet<TerritoryEntry>(new Comparator<TerritoryEntry>(){
+ public int compare(TerritoryEntry o1, TerritoryEntry o2) {
+ return collator.compare(o1.territoryName(), o2.territoryName());
+ }}));
+ UResourceBundle resourceBundle =
+ UResourceBundle.getBundleInstance(
+ Sample40_PopMsg.class.getPackage().getName().replace('.', '/')+"/data/popmsg",
+ defaultLocaleID,
+ Sample40_PopMsg.class.getClassLoader());
+
+ // say hello
+ String pattern = resourceBundle.getString("welcome");
+ MessageFormat fmt = new MessageFormat(pattern,defaultLocaleID);
+ Map<String, Object> msgargs = new HashMap<String, Object>();
+ msgargs.put("territoryCount", territoryCount);
+ msgargs.put("myLanguage", defaultLocaleName);
+ msgargs.put("today", System.currentTimeMillis());
+ System.out.println(fmt.format(msgargs, new StringBuffer(), null));
+
+ // Population roll call
+ String info = resourceBundle.getString("info");
+ Map<String, Object> infoArgs = new HashMap<String, Object>();
+ for(PopulationData.TerritoryEntry entry : territoryList) {
+ infoArgs.put("territory", entry.territoryName());
+ infoArgs.put("population", entry.population());
+ System.out.println(MessageFormat.format(info, infoArgs));
+ }
+ }
+}
diff --git a/icu4j/samples/src/main/java/com/ibm/icu/samples/iuc/SupplementalUtilities.java b/icu4j/samples/src/main/java/com/ibm/icu/samples/iuc/SupplementalUtilities.java
new file mode 100644
index 000000000..f6674b853
--- /dev/null
+++ b/icu4j/samples/src/main/java/com/ibm/icu/samples/iuc/SupplementalUtilities.java
@@ -0,0 +1,84 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+/*
+ *******************************************************************************
+ * Copyright (C) 2013-2016, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ *******************************************************************************
+ */
+package com.ibm.icu.samples.iuc;
+
+import com.ibm.icu.impl.ICUData;
+import com.ibm.icu.impl.ICUResourceBundle;
+import com.ibm.icu.util.UResourceBundle;
+
+/**
+ * @author srl
+ *
+ */
+public class SupplementalUtilities {
+ /**
+ * Convert LDML2ICUConverter format floating point (territoryF, etc)
+ * into double.
+ * See: SupplementalMapper.java
+ * @param n input number, such as -48123456
+ * @return double value, such as -123.456
+ * @internal
+ */
+ public static double ldml2d(int n) {
+ if(n == 0) {
+ return 0.;
+ }
+ boolean neg = false;
+ if(n < 0) {
+ n = -n;
+ neg = true;
+ }
+ int exp = (n/1000000);
+ n -= (exp * 1000000);
+ int sexp = exp - 50; // signed exponent
+ double d = n;
+ d = d * Math.pow(10, (sexp-5)); // -5 because 50 isn't quite right..
+ if(neg) {
+ d = -d;
+ }
+ return d;
+ }
+
+ /** Test function */
+ public static void main(String... args) {
+
+ System.out.println("Testingldml2d");
+ int junk[] = {
+ 49990000, // 99%
+ 48680000, // 6.8%
+ 57344400, // ?
+ 52940000, // ?
+ 0,
+ -48123456, // gets -0.012346 not -123.456
+ -52123456, // this one gets -123.456
+ 46100000,
+ 63146600
+ };
+
+ for(int i=0;i<junk.length;i++) {
+ System.out.println(Integer.toString(junk[i]) + " -> " + Double.toString(ldml2d(junk[i])));
+ }
+
+ System.out.println();
+ System.out.println("Testing getICUSupplementalData");
+ System.out.println("SupplementalData has " + getICUSupplementalData().getSize() + " size. (nonzero is good!)" );
+ }
+
+ /**
+ * Open ICU supplemental data
+ * @return the bundle
+ */
+ public static UResourceBundle getICUSupplementalData() {
+ UResourceBundle suppData = UResourceBundle.getBundleInstance(
+ ICUData.ICU_BASE_NAME,
+ "supplementalData",
+ ICUResourceBundle.ICU_DATA_CLASS_LOADER);
+ return suppData;
+ }
+}
diff --git a/icu4j/samples/src/main/java/com/ibm/icu/samples/iuc/package-info.java b/icu4j/samples/src/main/java/com/ibm/icu/samples/iuc/package-info.java
new file mode 100644
index 000000000..6fc3b446b
--- /dev/null
+++ b/icu4j/samples/src/main/java/com/ibm/icu/samples/iuc/package-info.java
@@ -0,0 +1,15 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+/*
+ *******************************************************************************
+ * Copyright (C) 2013, International Business Machines Corporation and *
+ * others. All Rights Reserved. *
+ *******************************************************************************
+ */
+/**
+ * @author srl
+ *
+ * This package contains samples for the IUC ICU workshops.
+ *
+ */
+package com.ibm.icu.samples.iuc;
diff --git a/icu4j/samples/src/main/java/com/ibm/icu/samples/shaping/ArabicShapingSample.java b/icu4j/samples/src/main/java/com/ibm/icu/samples/shaping/ArabicShapingSample.java
new file mode 100644
index 000000000..4dff694a4
--- /dev/null
+++ b/icu4j/samples/src/main/java/com/ibm/icu/samples/shaping/ArabicShapingSample.java
@@ -0,0 +1,288 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+/*
+*******************************************************************************
+* Copyright (C) 2001-2009, International Business Machines
+* Corporation and others. All Rights Reserved.
+*******************************************************************************
+*/
+
+package com.ibm.icu.samples.shaping;
+
+import com.ibm.icu.text.ArabicShaping;
+import com.ibm.icu.text.ArabicShapingException;
+
+/**
+ * Interactive test for Arabic shaping.
+ * Invoke from a command line passing args and strings. Use '-help' to see description of arguments.
+ */
+public class ArabicShapingSample{
+ private static final int COPY = 0;
+ private static final int INPLACE = 1;
+ private static final int STRING = 2;
+
+ public static final void main(String[] args) {
+ int testtype = COPY;
+ int options = 0;
+ int ss = 0;
+ int sl = -1;
+ int ds = 0;
+ int dl = -1;
+ String text = "$22.4 test 123 \ufef6\u0644\u0622 456 \u0664\u0665\u0666!";
+
+ for (int i = 0; i < args.length; ++i) {
+ String arg = args[i];
+ if (arg.charAt(0) == '-') {
+ String opt = arg.substring(1);
+ String val = opt;
+ int index = arg.indexOf(':');
+ if (index != -1) {
+ opt = opt.substring(0, Math.min(index, 3));
+ val = arg.substring(index + 1);
+ }
+
+ if (opt.equalsIgnoreCase("len")) {
+ options &= ~ArabicShaping.LENGTH_MASK;
+ if (val.equalsIgnoreCase("gs")) {
+ options |= ArabicShaping.LENGTH_GROW_SHRINK;
+ } else if (val.equalsIgnoreCase("sn")) {
+ options |= ArabicShaping.LENGTH_FIXED_SPACES_NEAR;
+ } else if (val.equalsIgnoreCase("se")) {
+ options |= ArabicShaping.LENGTH_FIXED_SPACES_AT_END;
+ } else if (val.equalsIgnoreCase("sb")) {
+ options |= ArabicShaping.LENGTH_FIXED_SPACES_AT_BEGINNING;
+ } else {
+ throwValError(opt, val);
+ }
+ } else if (opt.equalsIgnoreCase("dir")) {
+ options &= ~ArabicShaping.TEXT_DIRECTION_MASK;
+ if (val.equalsIgnoreCase("log")) {
+ options |= ArabicShaping.TEXT_DIRECTION_LOGICAL;
+ } else if (val.equalsIgnoreCase("vis")) {
+ options |= ArabicShaping.TEXT_DIRECTION_VISUAL_LTR;
+ } else {
+ throwValError(opt, val);
+ }
+ } else if (opt.equalsIgnoreCase("let")) {
+ options &= ~ArabicShaping.LETTERS_MASK;
+ if (val.equalsIgnoreCase("no")) {
+ options |= ArabicShaping.LETTERS_NOOP;
+ } else if (val.equalsIgnoreCase("sh")) {
+ options |= ArabicShaping.LETTERS_SHAPE;
+ } else if (val.equalsIgnoreCase("un")) {
+ options |= ArabicShaping.LETTERS_UNSHAPE;
+ } else if (val.equalsIgnoreCase("ta")) {
+ options |= ArabicShaping.LETTERS_SHAPE_TASHKEEL_ISOLATED;
+ } else {
+ throwValError(opt, val);
+ }
+ } else if (opt.equalsIgnoreCase("dig")) {
+ options &= ~ArabicShaping.DIGITS_MASK;
+ if (val.equalsIgnoreCase("no")) {
+ options |= ArabicShaping.DIGITS_NOOP;
+ } else if (val.equalsIgnoreCase("ea")) {
+ options |= ArabicShaping.DIGITS_EN2AN;
+ } else if (val.equalsIgnoreCase("ae")) {
+ options |= ArabicShaping.DIGITS_AN2EN;
+ } else if (val.equalsIgnoreCase("lr")) {
+ options |= ArabicShaping.DIGITS_EN2AN_INIT_LR;
+ } else if (val.equalsIgnoreCase("al")) {
+ options |= ArabicShaping.DIGITS_EN2AN_INIT_AL;
+ } else {
+ throwValError(opt, val);
+ }
+ } else if (opt.equalsIgnoreCase("typ")) {
+ options &= ~ArabicShaping.DIGIT_TYPE_MASK;
+ if (val.equalsIgnoreCase("an")) {
+ options |= ArabicShaping.DIGIT_TYPE_AN;
+ } else if (val.equalsIgnoreCase("ex")) {
+ options |= ArabicShaping.DIGIT_TYPE_AN_EXTENDED;
+ } else {
+ throwValError(opt, val);
+ }
+ } else if (opt.equalsIgnoreCase("dst")) {
+ try {
+ ds = Integer.parseInt(val);
+ }
+ catch (Exception e) {
+ throwValError(opt, val);
+ }
+ } else if (opt.equalsIgnoreCase("dln")) {
+ try {
+ dl = Integer.parseInt(val);
+ }
+ catch (Exception e) {
+ throwValError(opt, val);
+ }
+ } else if (opt.equalsIgnoreCase("sst")) {
+ try {
+ ss = Integer.parseInt(val);
+ }
+ catch (Exception e) {
+ throwValError(opt, val);
+ }
+ } else if (opt.equalsIgnoreCase("sln")) {
+ try {
+ sl = Integer.parseInt(val);
+ }
+ catch (Exception e) {
+ throwValError(opt, val);
+ }
+ } else if (opt.equalsIgnoreCase("tes")) {
+ if (val.equalsIgnoreCase("cp")) {
+ testtype = COPY;
+ } else if (val.equalsIgnoreCase("ip")) {
+ testtype = INPLACE;
+ } else if (val.equalsIgnoreCase("st")) {
+ testtype = STRING;
+ } else {
+ throwValError(opt, val);
+ }
+ } else if (opt.equalsIgnoreCase("help")) {
+ System.out.println(usage);
+ } else {
+ throwOptError(opt);
+ }
+ } else {
+ // assume text
+ text = parseText(arg);
+ }
+ }
+
+ if (sl < 0) {
+ sl = text.length() - ss;
+ System.out.println("sl defaulting to " + sl);
+ }
+ if (dl < 0) {
+ dl = 2 * sl;
+ System.out.println("dl defaulting to " + dl);
+ }
+
+ ArabicShaping shaper = new ArabicShaping(options);
+ System.out.println("shaper: " + shaper);
+
+ char[] src = text.toCharArray();
+ System.out.println(" input: '" + escapedText(src, ss, sl) + "'");
+ if (testtype != STRING) {
+ System.out.println("start: " + ss + " length: " + sl + " total length: " + src.length);
+ }
+
+ int result = -1;
+ char[] dest = null;
+
+ try {
+ switch (testtype) {
+ case COPY:
+ dest = new char[ds + dl];
+ result = shaper.shape(src, ss, sl, dest, ds, dl);
+ break;
+
+ case INPLACE:
+ shaper.shape(src, ss, sl);
+ ds = ss;
+ result = sl;
+ dest = src;
+ break;
+
+ case STRING:
+ dest = shaper.shape(text).toCharArray();
+ ds = 0;
+ result = dest.length;
+ break;
+ }
+
+ System.out.println("output: '" + escapedText(dest, ds, result) + "'");
+ System.out.println("length: " + result);
+ if (ds != 0 || result != dest.length) {
+ System.out.println("full output: '" + escapedText(dest, 0, dest.length) + "'");
+ }
+ }
+ catch (ArabicShapingException e) {
+ System.out.println("Caught ArabicShapingException");
+ System.out.println(e);
+ }
+ catch (Exception e) {
+ System.out.println("Caught Exception");
+ System.out.println(e);
+ }
+ }
+
+ private static void throwOptError(String opt) {
+ throwUsageError("unknown option: " + opt);
+ }
+
+ private static void throwValError(String opt, String val) {
+ throwUsageError("unknown value: " + val + " for option: " + opt);
+ }
+
+ private static void throwUsageError(String message) {
+ StringBuffer buf = new StringBuffer("*** usage error ***\n");
+ buf.append(message);
+ buf.append("\n");
+ buf.append(usage);
+ throw new Error(buf.toString());
+ }
+
+ private static final String usage =
+ "Usage: [option]* [text]\n" +
+ " where option is in the format '-opt[:val]'\n" +
+ " options are:\n" +
+ " -len:[gs|sn|se|sb] (length: grow/shrink, spaces near, spaces end, spaces beginning)\n" +
+ " -dir:[log|vis] (direction: logical, visual)\n" +
+ " -let:[no|sh|un|ta] (letters: noop, shape, unshape, tashkeel)\n" +
+ // " -let:[no|sh|un] (letters: noop, shape, unshape)\n" +
+ " -dig:[no|ea|ae|lr|al] (digits: noop, en2an, an2en, en2an_lr, en2an_al)\n" +
+ " -typ:[an|ex] (digit type: arabic, arabic extended)\n" +
+ " -dst:# (dest start: [integer])\n" +
+ " -dln:# (dest length (max size): [integer])\n" +
+ " -sst:# (source start: [integer])\n" +
+ " -sln:# (source length: [integer])\n" +
+ " -tes:[cp|ip|st] (test type: copy, in place, string)\n" +
+ " -help (print this help message)\n" +
+ " text can contain unicode escape values in the format '\\uXXXX' only\n";
+
+ private static String escapedText(char[] text, int start, int length) {
+ StringBuffer buf = new StringBuffer();
+ for (int i = start, e = start + length; i < e; ++i) {
+ char ch = text[i];
+ if (ch < 0x20 || ch > 0x7e) {
+ buf.append("\\u");
+ if (ch < 0x1000) {
+ buf.append('0');
+ }
+ if (ch < 0x100) {
+ buf.append('0');
+ }
+ if (ch < 0x10) {
+ buf.append('0');
+ }
+ buf.append(Integer.toHexString(ch));
+ } else {
+ buf.append(ch);
+ }
+ }
+ return buf.toString();
+ }
+
+ private static String parseText(String text) {
+ // process unicode escapes (only)
+ StringBuffer buf = new StringBuffer();
+ char[] chars = text.toCharArray();
+ for (int i = 0; i < chars.length; ++i) {
+ char ch = chars[i];
+ if (ch == '\\') {
+ if ((i < chars.length - 1) &&
+ (chars[i+1] == 'u')) {
+ int val = Integer.parseInt(text.substring(i+2, i+6), 16);
+ buf.append((char)val);
+ i += 5;
+ } else {
+ buf.append('\\');
+ }
+ } else {
+ buf.append(ch);
+ }
+ }
+ return buf.toString();
+ }
+}
diff --git a/icu4j/samples/src/main/java/com/ibm/icu/samples/text/dateintervalformat/DateIntervalFormatSample.java b/icu4j/samples/src/main/java/com/ibm/icu/samples/text/dateintervalformat/DateIntervalFormatSample.java
new file mode 100644
index 000000000..0778d7e6d
--- /dev/null
+++ b/icu4j/samples/src/main/java/com/ibm/icu/samples/text/dateintervalformat/DateIntervalFormatSample.java
@@ -0,0 +1,126 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+/*
+ *******************************************************************************
+ * Copyright (C) 2013, International Business Machines Corporation and *
+ * others. All Rights Reserved. *
+ *******************************************************************************
+ */
+package com.ibm.icu.samples.text.dateintervalformat;
+
+
+// ---dtitvfmtPreDefinedExample
+import java.util.Date;
+
+import com.ibm.icu.text.DateFormat;
+import com.ibm.icu.text.DateIntervalFormat;
+import com.ibm.icu.text.DateIntervalInfo;
+import com.ibm.icu.util.Calendar;
+import com.ibm.icu.util.DateInterval;
+import com.ibm.icu.util.GregorianCalendar;
+import com.ibm.icu.util.ULocale;
+// ---dtitvfmtPreDefinedExample
+public class DateIntervalFormatSample{
+
+ public static void main (String[] args){
+
+ dtitvfmtPreDefined();
+ dtitvfmtCustomized();
+
+ }
+
+ public static void dtitvfmtPreDefined()
+ {
+ System.out.println("==============================================================================");
+ System.out.println(" dtitvfmtPreDefined()");
+ System.out.println();
+ System.out.println(" Use DateIntervalFormat to get Date interval format for pre-defined skeletons:");
+ System.out.println(" yMMMd, MMMd per locale");
+ System.out.println("==============================================================================");
+ // ---dtitvfmtPreDefinedExample
+ final Date date[] = {
+ new GregorianCalendar(2007,10,10,10,10,10).getTime(),
+ new GregorianCalendar(2008,10,10,10,10,10).getTime(),
+ new GregorianCalendar(2008,11,10,10,10,10).getTime(),
+ new GregorianCalendar(2008,11,10,15,10,10).getTime(),
+ };
+ final DateInterval dtitv[] = {
+ new DateInterval(date[0].getTime(),date[1].getTime()),
+ new DateInterval(date[1].getTime(),date[2].getTime()),
+ new DateInterval(date[2].getTime(),date[3].getTime()),
+ };
+ final String [] skeletons = {
+ DateFormat.YEAR_ABBR_MONTH_DAY,
+ DateFormat.MONTH_DAY,
+ DateFormat.HOUR_MINUTE,
+ };
+ System.out.printf("%-15s%-35s%-35s%-35s%-35s\n", "Skeleton", "from","to","Date Interval in en_US", "Date Interval in Ja");
+ int i=0;
+ for (String skeleton:skeletons) {
+ System.out.printf("%-15s%-35s%-35s", skeleton,date[i].toString(), date[i+1].toString());
+ DateIntervalFormat dtitvfmtEn = DateIntervalFormat.getInstance(skeleton, ULocale.ENGLISH);
+ DateIntervalFormat dtitvfmtJa = DateIntervalFormat.getInstance(skeleton, ULocale.JAPANESE);
+ System.out.printf("%-35s%-35s\n", dtitvfmtEn.format(dtitv[i]),dtitvfmtJa.format(dtitv[i]));
+ i++;
+ }
+ /** output of the sample code:
+ *********************************************************************************************************************************************************
+ Skeleton from to Date Interval in en_US Date Interval in Ja
+ yMMMd Sat Nov 10 10:10:10 EST 2007 Mon Nov 10 10:10:10 EST 2008 Nov 10, 2007 – Nov 10, 2008 2007年11月10日~2008年11月10日
+ MMMMd Mon Nov 10 10:10:10 EST 2008 Wed Dec 10 10:10:10 EST 2008 November 10 – December 10 11月10日~12月10日
+ jm Wed Dec 10 10:10:10 EST 2008 Wed Dec 10 15:10:10 EST 2008 10:10 AM – 3:10 PM 10:10~15:10
+
+ *********************************************************************************************************************************************************/
+ // ---dtitvfmtPreDefinedExample
+}
+ public static void dtitvfmtCustomized()
+ {
+ System.out.println("================================================================================");
+ System.out.println(" dtitvfmtCustomized()");
+ System.out.println();
+ System.out.println(" Use DateIntervalFormat to create customized date interval format for yMMMd, Hm");
+ System.out.println("================================================================================");
+ // ---dtitvfmtCustomizedExample
+ final Date date[] = {
+ new GregorianCalendar(2007,9,10,10,10,10).getTime(),
+ new GregorianCalendar(2007,10,10,10,10,10).getTime(),
+ new GregorianCalendar(2007,10,10,22,10,10).getTime(),
+ };
+ final DateInterval dtitv[] = {
+ new DateInterval(date[0].getTime(),date[1].getTime()),
+ new DateInterval(date[1].getTime(),date[2].getTime()),
+ };
+ final String [] skeletons = {
+ DateFormat.YEAR_ABBR_MONTH_DAY,
+ DateFormat.HOUR24_MINUTE,
+ };
+ System.out.printf("%-15s%-35s%-35s%-45s%-35s\n", "Skeleton", "from","to", "Date Interval in en_US", "Date Interval in Ja");
+ // Create an empty DateIntervalInfo object
+ DateIntervalInfo dtitvinf = new DateIntervalInfo(ULocale.ENGLISH);
+ // Set Date Time internal pattern for MONTH, DAY_OF_MONTH, HOUR_OF_DAY
+ dtitvinf.setIntervalPattern("yMMMd", Calendar.MONTH, "y 'Diff' MMM d --- MMM d");
+ dtitvinf.setIntervalPattern("Hm", Calendar.HOUR_OF_DAY, "yyyy MMM d HH:mm ~ HH:mm");
+ // Set fallback interval pattern
+ dtitvinf.setFallbackIntervalPattern("{0} ~~~ {1}");
+ // Get the DateIntervalFormat with the custom pattern
+ for (String skeleton:skeletons){
+ for (int i=0;i<2;i++) {
+ System.out.printf("%-15s%-35s%-35s", skeleton,date[i].toString(), date[i+1].toString());
+ DateIntervalFormat dtitvfmtEn = DateIntervalFormat.getInstance(skeleton,ULocale.ENGLISH,dtitvinf);
+ DateIntervalFormat dtitvfmtJa = DateIntervalFormat.getInstance(skeleton,ULocale.JAPANESE,dtitvinf);
+ System.out.printf("%-45s%-35s\n", dtitvfmtEn.format(dtitv[i]),dtitvfmtJa.format(dtitv[i]));
+ }
+ }
+ /** output of the sample code:
+ *************************************************************************************************************************************************************************
+ Skeleton from to Date Interval in en_US Date Interval in Ja
+ yMMMd Wed Oct 10 10:10:10 EDT 2007 Sat Nov 10 10:10:10 EST 2007 2007 Diff Oct 10 --- Nov 10 2007 Diff 10月 10 --- 11月 10
+ yMMMd Sat Nov 10 10:10:10 EST 2007 Sat Nov 10 22:10:10 EST 2007 Nov 10, 2007 2007年11月10日
+ Hm Wed Oct 10 10:10:10 EDT 2007 Sat Nov 10 10:10:10 EST 2007 10/10/2007, 10:10 ~~~ 11/10/2007, 10:10 2007/10/10 10:10 ~~~ 2007/11/10 10:10
+ Hm Sat Nov 10 10:10:10 EST 2007 Sat Nov 10 22:10:10 EST 2007 2007 Nov 10 10:10 ~ 22:10 2007 11月 10 10:10 ~ 22:10
+ *************************************************************************************************************************************************************************/
+ // ---dtitvfmtCustomizedExample
+
+ }
+}
+
diff --git a/icu4j/samples/src/main/java/com/ibm/icu/samples/text/datetimepatterngenerator/DateTimePatternGeneratorSample.java b/icu4j/samples/src/main/java/com/ibm/icu/samples/text/datetimepatterngenerator/DateTimePatternGeneratorSample.java
new file mode 100644
index 000000000..4066263da
--- /dev/null
+++ b/icu4j/samples/src/main/java/com/ibm/icu/samples/text/datetimepatterngenerator/DateTimePatternGeneratorSample.java
@@ -0,0 +1,185 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+/*
+ *******************************************************************************
+ * Copyright (C) 2013, International Business Machines Corporation and *
+ * others. All Rights Reserved. *
+ *******************************************************************************
+ */
+package com.ibm.icu.samples.text.datetimepatterngenerator;
+// ---getBestPatternExample
+import java.util.Date;
+
+import com.ibm.icu.text.DateFormat;
+import com.ibm.icu.text.DateTimePatternGenerator;
+import com.ibm.icu.text.SimpleDateFormat;
+import com.ibm.icu.util.GregorianCalendar;
+import com.ibm.icu.util.TimeZone;
+import com.ibm.icu.util.ULocale;
+// ---getBestPatternExample
+/**
+ * com.ibm.icu.text.DateTimePatternGenerator Sample Code
+ */
+public class DateTimePatternGeneratorSample {
+
+ public static void main (String[] args) {
+ getBestPatternExample();
+ addPatternExample();
+ replaceFieldTypesExample();
+ }
+
+ public static void getBestPatternExample() {
+ System.out.println("========================================================================");
+ System.out.println(" getBestPatternExample()");
+ System.out.println();
+ System.out.println(" Use DateTimePatternGenerator to create customized date/time pattern:");
+ System.out.println(" yQQQQ,yMMMM, MMMMd, hhmm, jjmm per locale");
+ System.out.println("========================================================================");
+ // ---getBestPatternExample
+ final String[] skeletons = {
+ "yQQQQ", // year + full name of quarter, i.e., 4th quarter 1999
+ "yMMMM", // year + full name of month, i.e., October 1999
+ "MMMMd", // full name of month + day of the month, i.e., October 25
+ "hhmm", // 12-hour-cycle format, i.e., 1:32 PM
+ "jjmm" // preferred hour format for the given locale, i.e., 24-hour-cycle format for fr_FR
+ };
+ final ULocale[] locales = {
+ new ULocale ("en_US"),
+ new ULocale ("fr_FR"),
+ new ULocale ("zh_CN"),
+ };
+ DateTimePatternGenerator dtfg = null;
+ Date date= new GregorianCalendar(1999,9,13,23,58,59).getTime();
+ System.out.printf("%-20s%-35s%-35s%-35s\n\n", "Skeleton", "en_US", "fr_FR","zh_CN");
+ for (String skeleton:skeletons) {
+ System.out.printf("%-20s", skeleton);
+ for (ULocale locale:locales) {
+ // create a DateTimePatternGenerator instance for given locale
+ dtfg = DateTimePatternGenerator.getInstance(locale);
+ // use getBestPattern method to get the best pattern for the given skeleton
+ String pattern = dtfg.getBestPattern(skeleton);
+ // Constructs a SimpleDateFormat with the best pattern generated above and the given locale
+ SimpleDateFormat sdf = new SimpleDateFormat(pattern, locale);
+ // Get the format of the given date
+ System.out.printf("%-35s",sdf.format(date));
+ }
+ System.out.println("\n");
+ }
+ /** output of the sample code:
+ *************************************************************************************************************
+ Skeleton en_US fr_FR zh_CN
+
+ yQQQQ 4th quarter 1999 4e trimestre 1999 1999年第四季度
+
+ yMMMM October 1999 octobre 1999 1999年10月
+
+ MMMMd October 13 13 octobre 10月13日
+
+ hhmm 11:58 PM 11:58 PM 下午11:58
+
+ jjmm 11:58 PM 23:58 下午11:58
+
+ **************************************************************************************************************/
+ // Use DateTime.getPatternInstance to produce the same Date/Time format with predefined constant field value
+ final String[] dtfskeleton = {
+ DateFormat.YEAR_QUARTER, // year + full name of quarter, i.e., 4th quarter 1999
+ DateFormat.YEAR_MONTH, // year + full name of month, i.e., October 1999
+ DateFormat.MONTH_DAY // full name of month + day of the month, i.e., October 25
+ };
+ System.out.printf("%-20s%-35s%-35s%-35s\n\n", "Skeleton", "en_US", "fr_FR","zh_CN");
+ for (String skeleton:dtfskeleton) {
+ System.out.printf("%-20s", skeleton);
+ for (ULocale locale:locales) {
+ // Use DateFormat.getPatternInstance to get the date/time format for the locale,
+ // and apply the format to the given date
+ String df=DateFormat.getPatternInstance(skeleton,locale).format(date);
+ System.out.printf("%-35s",df);
+ }
+ System.out.println("\n");
+ }
+
+ /** output of the sample code:
+ ************************************************************************************************************
+ Skeleton en_US fr_FR zh_CN
+
+ yQQQQ 4th quarter 1999 4e trimestre 1999 1999年第四季度
+
+ yMMMM October 1999 octobre 1999 1999年10月
+
+ MMMMd October 13 13 octobre 10月13日
+ ************************************************************************************************************/
+// ---getBestPatternExample
+}
+
+ public static void addPatternExample() {
+ System.out.println("========================================================================");
+ System.out.println(" addPatternExample()");
+ System.out.println();
+ System.out.println(" Use addPattern API to add new '. von' to existing pattern");
+ System.out.println("========================================================================");
+ // ---addPatternExample
+ Date date= new GregorianCalendar(1999,9,13,23,58,59).getTime();
+ ULocale locale = ULocale.FRANCE;
+ // Create an DateTimePatternGenerator instance for the given locale
+ DateTimePatternGenerator gen = DateTimePatternGenerator.getInstance(locale);
+ SimpleDateFormat format = new SimpleDateFormat(gen.getBestPattern("MMMMddHmm"), locale);
+ DateTimePatternGenerator.PatternInfo returnInfo = new DateTimePatternGenerator.PatternInfo();
+ // Add '. von' to the existing pattern
+ gen.addPattern("dd'. von' MMMM", true, returnInfo);
+ // Apply the new pattern
+ format.applyPattern(gen.getBestPattern("MMMMddHmm"));
+ System.out.println("New Pattern for FRENCH: "+format.toPattern());
+ System.out.println("Date Time in new Pattern: "+format.format(date));
+
+ /** output of the sample code:
+ **************************************************************************************************
+ New Pattern for FRENCH: dd. 'von' MMMM HH:mm
+ Date Time in new Pattern: 13. von octobre 23:58
+
+ *************************************************************************************************/
+ // ---addPatternExample
+}
+
+ public static void replaceFieldTypesExample() {
+ // Use repalceFieldTypes API to replace zone 'zzzz' with 'vvvv'
+ System.out.println("========================================================================");
+ System.out.println(" replaceFieldTypeExample()");
+ System.out.println();
+ System.out.println(" Use replaceFieldTypes API to replace zone 'zzzz' with 'vvvv");
+ System.out.println("========================================================================");
+ // ---replaceFieldTypesExample
+ Date date= new GregorianCalendar(1999,9,13,23,58,59).getTime();
+ TimeZone zone = TimeZone.getTimeZone("Europe/Paris");
+ ULocale locale = ULocale.FRANCE;
+ DateTimePatternGenerator gen = DateTimePatternGenerator.getInstance(locale);
+ SimpleDateFormat format = new SimpleDateFormat("EEEE d MMMM y HH:mm:ss zzzz",locale);
+ format.setTimeZone(zone);
+ String pattern = format.toPattern();
+ System.out.println("Pattern before replacement:");
+ System.out.println(pattern);
+ System.out.println("Date/Time format in fr_FR:");
+ System.out.println(format.format(date));
+ // Replace zone "zzzz" in the pattern with "vvvv"
+ String newPattern = gen.replaceFieldTypes(pattern, "vvvv");
+ // Apply the new pattern
+ format.applyPattern(newPattern);
+ System.out.println("Pattern after replacement:");
+ System.out.println(newPattern);
+ System.out.println("Date/Time format in fr_FR:");
+ System.out.println(format.format(date));
+
+ /** output of the sample code:
+ ***************************************************************************************************
+ Pattern before replacement:
+ EEEE d MMMM y HH:mm:ss zzzz
+ Date/Time format in fr_FR:
+ jeudi 14 octobre 1999 05:58:59 heure avancée d’Europe centrale
+ Pattern after replacement:
+ EEEE d MMMM y HH:mm:ss vvvv
+ Date/Time format in fr_FR:
+ jeudi 14 octobre 1999 05:58:59 heure de l’Europe centrale
+
+ **************************************************************************************************/
+ // ---replaceFieldTypesExample
+ }
+}
diff --git a/icu4j/samples/src/main/java/com/ibm/icu/samples/text/messagepattern/MessagePatternDemo.java b/icu4j/samples/src/main/java/com/ibm/icu/samples/text/messagepattern/MessagePatternDemo.java
new file mode 100644
index 000000000..16adb4564
--- /dev/null
+++ b/icu4j/samples/src/main/java/com/ibm/icu/samples/text/messagepattern/MessagePatternDemo.java
@@ -0,0 +1,125 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+/*
+*******************************************************************************
+* Copyright (C) 2010-2011, International Business Machines
+* Corporation and others. All Rights Reserved.
+*******************************************************************************
+* created on: 2010aug21
+* created by: Markus W. Scherer
+*/
+
+package com.ibm.icu.samples.text.messagepattern;
+
+import com.ibm.icu.text.MessagePattern;
+
+/**
+ * Demo code for MessagePattern class.
+ * Pretty-prints the list of MessagePattern Parts and uses the MiniMessageFormatter
+ * with a few patterns.
+ * @author Markus Scherer
+ * @since 2010-aug-21
+ */
+public final class MessagePatternDemo {
+ private static final String manySpaces=" ";
+
+ private static final void printParts(MessagePattern msg) {
+ String autoQA=msg.autoQuoteApostropheDeep();
+ if(!autoQA.equals(msg.getPatternString())) {
+ System.out.println("autoQA: "+autoQA);
+ }
+ String indent="";
+ StringBuilder explanation=new StringBuilder();
+ MessagePattern.Part prevPart=null;
+ int count=msg.countParts();
+ for(int i=0; i<count; ++i) {
+ explanation.delete(0, 0x7fffffff);
+ MessagePattern.Part part=msg.getPart(i);
+ assert prevPart==null || prevPart.getLimit()<=part.getIndex();
+ String partString=part.toString();
+ MessagePattern.Part.Type type=part.getType();
+ if(type==MessagePattern.Part.Type.MSG_START) {
+ indent=manySpaces.substring(0, part.getValue()*2);
+ }
+ if(part.getLength()>0) {
+ explanation.append("=\"").append(msg.getSubstring(part)).append('"');
+ }
+ if(type.hasNumericValue()) {
+ explanation.append('=').append(msg.getNumericValue(part));
+ }
+ System.out.format("%2d: %s%s%s\n", i, indent, partString, explanation);
+ if(type==MessagePattern.Part.Type.MSG_LIMIT) {
+ int nestingLevel=part.getValue();
+ if(nestingLevel>1) {
+ indent=manySpaces.substring(0, (nestingLevel-1)*2); // outdent
+ } else {
+ indent="";
+ }
+ }
+ prevPart=part;
+ }
+ }
+
+ private static final MessagePattern print(String s) {
+ System.out.println("message: "+s);
+ try {
+ MessagePattern msg=new MessagePattern(s);
+ printParts(msg);
+ return msg;
+ } catch(Exception e) {
+ System.out.println("Exception: "+e.getMessage());
+ return null;
+ }
+ }
+
+ private static final void printFormat(String s, Object... args) {
+ MessagePattern msg=print(s);
+ if(msg!=null) {
+ System.out.println(new MiniMessageFormatter(msg).format(new StringBuilder(), args));
+ }
+ }
+
+ private static final void printFormatWithNamedArgs(String s, Object... args) {
+ MessagePattern msg=print(s);
+ if(msg!=null) {
+ System.out.println(new MiniMessageFormatter(msg).format(
+ new StringBuilder(), MiniMessageFormatter.mapFromNameValuePairs(args)));
+ }
+ }
+
+ public static void main(String[] argv) {
+ print("Hello!");
+ print("Hel'lo!");
+ print("Hel'{o");
+ print("Hel'{'o");
+ // double apostrophe inside quoted literal text still encodes a single apostrophe
+ printFormat("a'{bc''de'f");
+ print("a'{bc''de'f{0,number,g'hi''jk'l#}");
+ print("abc{0}def");
+ print("abc{ arg }def");
+ print("abc{1}def{arg}ghi");
+ print("abc{2, number}ghi{3, select, xx {xxx} other {ooo}} xyz");
+ print("abc{gender,select,"+
+ "other{His name is {person,XML,<entry name=\"PERSON\">{$PERSON}</entry>}.}}xyz");
+ print("abc{num_people, plural, offset:17 few{fff} other {oooo}}xyz");
+ print("abc{ num , plural , offset: 2 =1 {1} =-1 {-1} =3.14 {3.14} other {oo} }xyz");
+ print("I don't {a,plural,other{w'{'on't #'#'}} and "+
+ "{b,select,other{shan't'}'}} '{'''know'''}' and "+
+ "{c,choice,0#can't'|'}"+
+ "{z,number,#'#'###.00'}'}.");
+ print("a_{0,choice,-∞ #-inf| 5≤ five | 99 # ninety'|'nine }_z");
+ print("a_{0,plural,other{num=#'#'=#'#'={1,number,##}!}}_z");
+ print("}}}{0}}"); // yes, unmatched '}' are ok in ICU MessageFormat
+ printFormat("Hello {0}!", "Alice");
+ String msg="++{0, select, female{{1} calls you her friend}"+
+ "other{{1} calls you '{their}' friend}"+
+ "male{{1} calls you his friend}}--";
+ printFormat(msg, "female", "Alice");
+ printFormat(msg, "male", "Bob");
+ printFormat(msg, "unknown", "sushifan3");
+ msg="_'__{gender, select, female{Her n'ame is {person_name}.}"+
+ "other{His n'ame is {person_name}.}}__'_";
+ printFormatWithNamedArgs(msg, "gender", "female", "person_name", "Alice");
+ printFormatWithNamedArgs(msg, "gender", "male", "person_name", "Bob");
+ }
+}
diff --git a/icu4j/samples/src/main/java/com/ibm/icu/samples/text/messagepattern/MessagePatternUtilDemo.java b/icu4j/samples/src/main/java/com/ibm/icu/samples/text/messagepattern/MessagePatternUtilDemo.java
new file mode 100644
index 000000000..da525ef1a
--- /dev/null
+++ b/icu4j/samples/src/main/java/com/ibm/icu/samples/text/messagepattern/MessagePatternUtilDemo.java
@@ -0,0 +1,409 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+/*
+*******************************************************************************
+* Copyright (C) 2011, International Business Machines
+* Corporation and others. All Rights Reserved.
+*******************************************************************************
+* created on: 2011jul14
+* created by: Markus W. Scherer
+*/
+
+package com.ibm.icu.samples.text.messagepattern;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.ibm.icu.text.MessagePattern;
+import com.ibm.icu.text.MessagePatternUtil;
+import com.ibm.icu.text.MessagePatternUtil.VariantNode;
+
+/**
+ * Demo code for MessagePattern class.
+ * @author Markus Scherer
+ * @since 2011-jul-14
+ */
+public class MessagePatternUtilDemo {
+ private static final String manySpaces=" ";
+
+ private static final void printMessage(MessagePatternUtil.MessageNode msg, int depth) {
+ String indent = manySpaces.substring(0, depth * 2);
+ for (MessagePatternUtil.MessageContentsNode contents : msg.getContents()) {
+ switch (contents.getType()) {
+ case TEXT:
+ System.out.println(indent + "text: «" +
+ ((MessagePatternUtil.TextNode)contents).getText() + "»");
+ break;
+ case ARG:
+ printArg((MessagePatternUtil.ArgNode)contents, depth);
+ break;
+ case REPLACE_NUMBER:
+ System.out.println(indent + "replace: number");
+ break;
+ }
+ }
+ }
+
+ private static final void printArg(MessagePatternUtil.ArgNode arg, int depth) {
+ System.out.print(manySpaces.substring(0, depth * 2) + "arg: «" + arg.getName() + "»");
+ MessagePattern.ArgType argType = arg.getArgType();
+ if (argType == MessagePattern.ArgType.NONE) {
+ System.out.println(" (no type)");
+ } else {
+ System.out.print(" (" + arg.getTypeName() + ")");
+ if (argType == MessagePattern.ArgType.SIMPLE) {
+ String styleString = arg.getSimpleStyle();
+ if (styleString == null) {
+ System.out.println(" (no style)");
+ } else {
+ System.out.println(" style: «" + styleString + "»");
+ }
+ } else {
+ System.out.println();
+ printComplexArgStyle(arg.getComplexStyle(), depth + 1);
+ }
+ }
+ }
+
+ private static final void printComplexArgStyle(MessagePatternUtil.ComplexArgStyleNode style,
+ int depth) {
+ if (style.hasExplicitOffset()) {
+ System.out.println(manySpaces.substring(0, depth * 2) + "offset: " + style.getOffset());
+ }
+ String indent = manySpaces.substring(0, depth * 2);
+ MessagePattern.ArgType argType = style.getArgType();
+ for (MessagePatternUtil.VariantNode variant : style.getVariants()) {
+ double value;
+ switch (argType) {
+ case CHOICE:
+ System.out.println(indent + variant.getSelectorValue() + " " +
+ variant.getSelector() + ":");
+ break;
+ case PLURAL:
+ value = variant.getSelectorValue();
+ if (value == MessagePattern.NO_NUMERIC_VALUE) {
+ System.out.println(indent + variant.getSelector() + ":");
+ } else {
+ System.out.println(indent + variant.getSelector() + " (" + value + "):");
+ }
+ break;
+ case SELECT:
+ System.out.println(indent + variant.getSelector() + ":");
+ break;
+ }
+ printMessage(variant.getMessage(), depth + 1);
+ }
+ }
+
+ /**
+ * This is a <em>prototype/demo/sample</em> for how we could use the MessagePatternUtil class
+ * for generating something like JavaScript code for evaluating some
+ * of the MessageFormat syntax.
+ *
+ * <p>This is not intended to be production code, nor to generate production code
+ * or even syntactically correct JavaScript.
+ * @param msg
+ */
+ private static final void genCode(MessagePatternUtil.MessageNode msg) {
+ List<String> args = new ArrayList<String>();
+ addArgs(msg, args);
+ System.out.print("def function(");
+ boolean firstArg = true;
+ for (String argName : args) {
+ if (firstArg) {
+ System.out.print(argName);
+ firstArg = false;
+ } else {
+ System.out.print(", " + argName);
+ }
+ }
+ System.out.println(") {");
+ genCode(msg, 1, true, "");
+ System.out.println(" return result");
+ System.out.println("}");
+ }
+
+ private static final void genCode(MessagePatternUtil.MessageNode msg,
+ int depth,
+ boolean firstResult,
+ String pluralNumber) {
+ String prefix = manySpaces.substring(0, depth * 2) + "result ";
+ for (MessagePatternUtil.MessageContentsNode contents : msg.getContents()) {
+ String operator = firstResult ? "=" : "+=";
+ switch (contents.getType()) {
+ case TEXT:
+ System.out.println(
+ prefix + operator + " \"" +
+ escapeString(((MessagePatternUtil.TextNode)contents).getText()) +
+ "\"");
+ break;
+ case ARG:
+ genCode((MessagePatternUtil.ArgNode)contents, depth, firstResult);
+ break;
+ case REPLACE_NUMBER:
+ System.out.println(prefix + operator + " formatNumber(" + pluralNumber + ")");
+ break;
+ }
+ firstResult = false;
+ }
+ }
+
+ private static final void genCode(MessagePatternUtil.ArgNode arg,
+ int depth,
+ boolean firstResult) {
+ String prefix = manySpaces.substring(0, depth * 2) + "result ";
+ String operator = firstResult ? "=" : "+=";
+ String argName = arg.getName();
+ if (arg.getNumber() >= 0) {
+ argName = "arg_" + argName; // Prefix for numbered argument.
+ }
+ switch (arg.getArgType()) {
+ case NONE:
+ System.out.println(prefix + operator + " " + argName);
+ break;
+ case SIMPLE:
+ case CHOICE:
+ System.out.println(prefix + operator + " \"(unsupported syntax)\"");
+ break;
+ case PLURAL:
+ genCodeForPlural(arg.getComplexStyle(), depth, firstResult, argName);
+ break;
+ case SELECT:
+ genCodeForSelect(arg.getComplexStyle(), depth, firstResult, argName);
+ break;
+ }
+ }
+
+ private static final void genCodeForPlural(MessagePatternUtil.ComplexArgStyleNode style,
+ int depth,
+ boolean firstResult,
+ String argName) {
+ List<MessagePatternUtil.VariantNode> numericVariants =
+ new ArrayList<MessagePatternUtil.VariantNode>();
+ List<MessagePatternUtil.VariantNode> keywordVariants =
+ new ArrayList<MessagePatternUtil.VariantNode>();
+ MessagePatternUtil.VariantNode otherVariant =
+ style.getVariantsByType(numericVariants, keywordVariants);
+ double offset = style.getOffset();
+ String pluralNumber = offset == 0. ? argName : argName + " - " + offset;
+ int origDepth = depth;
+ if (!numericVariants.isEmpty()) {
+ genCodeForNumericVariants(numericVariants, depth++, firstResult, argName, pluralNumber);
+ }
+ if (!keywordVariants.isEmpty()) {
+ System.out.println(manySpaces.substring(0, depth * 2) +
+ "_keyword = PluralRules.select(" + pluralNumber + ")");
+ genCodeForKeywordVariants(keywordVariants, depth++, firstResult,
+ "_keyword", pluralNumber);
+ }
+ genCode(otherVariant.getMessage(), depth, firstResult, pluralNumber);
+ if (origDepth < depth) {
+ System.out.println(manySpaces.substring(0, --depth * 2) + "}");
+ if (origDepth < depth) {
+ System.out.println(manySpaces.substring(0, --depth * 2) + "}");
+ }
+ }
+ }
+
+ private static final void genCodeForSelect(MessagePatternUtil.ComplexArgStyleNode style,
+ int depth,
+ boolean firstResult,
+ String argName) {
+ List<MessagePatternUtil.VariantNode> keywordVariants =
+ new ArrayList<MessagePatternUtil.VariantNode>();
+ MessagePatternUtil.VariantNode otherVariant = style.getVariantsByType(null, keywordVariants);
+ if (keywordVariants.isEmpty()) {
+ genCode(otherVariant.getMessage(), depth, firstResult, "");
+ } else {
+ genCodeForKeywordVariants(keywordVariants, depth, firstResult, argName, "");
+ genCode(otherVariant.getMessage(), depth + 1, firstResult, "");
+ System.out.println(manySpaces.substring(0, depth * 2) + "}");
+ }
+ }
+
+ private static final void genCodeForNumericVariants(List<VariantNode> variants,
+ int depth,
+ boolean firstResult,
+ String varName,
+ String pluralNumber) {
+ String indent = manySpaces.substring(0, depth++ * 2);
+ boolean firstVariant = true;
+ for (MessagePatternUtil.VariantNode variant : variants) {
+ System.out.println(
+ indent +
+ (firstVariant ? "if (" : "} else if (") +
+ varName + " == " + variant.getSelectorValue() + ") {");
+ genCode(variant.getMessage(), depth, firstResult, pluralNumber);
+ firstVariant = false;
+ }
+ System.out.println(indent + "} else {");
+ }
+
+ private static final void genCodeForKeywordVariants(List<VariantNode> variants,
+ int depth,
+ boolean firstResult,
+ String varName,
+ String pluralNumber) {
+ String indent = manySpaces.substring(0, depth++ * 2);
+ boolean firstVariant = true;
+ for (MessagePatternUtil.VariantNode variant : variants) {
+ System.out.println(
+ indent +
+ (firstVariant ? "if (" : "} else if (") +
+ varName + " == \"" + variant.getSelector() + "\") {");
+ genCode(variant.getMessage(), depth, firstResult, pluralNumber);
+ firstVariant = false;
+ }
+ System.out.println(indent + "} else {");
+ }
+
+ /**
+ * Adds the message's argument names to the args list.
+ * Adds each argument only once, in the order of first appearance.
+ * Numbered arguments get an "arg_" prefix prepended.
+ * @param msg
+ * @param args
+ */
+ private static final void addArgs(MessagePatternUtil.MessageNode msg, List<String> args) {
+ for (MessagePatternUtil.MessageContentsNode contents : msg.getContents()) {
+ if (contents.getType() == MessagePatternUtil.MessageContentsNode.Type.ARG) {
+ MessagePatternUtil.ArgNode arg = (MessagePatternUtil.ArgNode)contents;
+ String argName;
+ if (arg.getNumber() >= 0) {
+ argName = "arg_" + arg.getNumber(); // Prefix for numbered argument.
+ } else {
+ argName = arg.getName();
+ }
+ if (!args.contains(argName)) {
+ args.add(argName);
+ }
+ MessagePatternUtil.ComplexArgStyleNode complexStyle = arg.getComplexStyle();
+ if (complexStyle != null) {
+ for (MessagePatternUtil.VariantNode variant : complexStyle.getVariants()) {
+ addArgs(variant.getMessage(), args);
+ }
+ }
+ }
+ }
+ }
+
+ private static final String escapeString(String s) {
+ if (s.indexOf('"') < 0) {
+ return s;
+ } else {
+ return s.replace("\"", "\\\"");
+ }
+ }
+
+ private static final MessagePatternUtil.MessageNode print(String s) {
+ System.out.println("message: «" + s + "»");
+ try {
+ MessagePatternUtil.MessageNode msg = MessagePatternUtil.buildMessageNode(s);
+ printMessage(msg, 1);
+ genCode(msg);
+ return msg;
+ } catch(Exception e) {
+ System.out.println("Exception: "+e.getMessage());
+ return null;
+ }
+ }
+
+ public static void main(String[] argv) {
+ print("Hello!");
+ print("Hel'lo!");
+ print("Hel'{o");
+ print("Hel'{'o");
+ // double apostrophe inside quoted literal text still encodes a single apostrophe
+ print("a'{bc''de'f");
+ print("a'{bc''de'f{0,number,g'hi''jk'l#}");
+ print("abc{0}def");
+ print("abc{ arg }def");
+ print("abc{1}def{arg}ghi");
+ print("abc{2, number}ghi{3, select, xx {xxx} other {ooo}} xyz");
+ print("abc{gender,select,"+
+ "other{His name is {tc,XMB,<ph name=\"PERSON\">{$PERSON}</ph>}.}}xyz");
+ print("abc{num_people, plural, offset:17 few{fff} other {oooo}}xyz");
+ print("abc{ num , plural , offset: 2 =1 {1} =-1 {-1} =3.14 {3.14} other {oo} }xyz");
+ print("I don't {a,plural,other{w'{'on't #'#'}} and "+
+ "{b,select,other{shan't'}'}} '{'''know'''}' and "+
+ "{c,choice,0#can't'|'}"+
+ "{z,number,#'#'###.00'}'}.");
+ print("a_{0,choice,-∞ #-inf| 5≤ five | 99 # ninety'|'nine }_z");
+ print("a_{0,plural,other{num=#'#'=#'#'={1,number,##}!}}_z");
+ print("}}}{0}}"); // yes, unmatched '}' are ok in ICU MessageFormat
+ print("Hello {0}!");
+ String msg="++{0, select, female{{1} calls you her friend}"+
+ "other{{1} calls you '{their}' friend}"+
+ "male{{1} calls you his friend}}--";
+ print(msg);
+ msg="_'__{gender, select, female{Her n'ame is {person_name}.}"+
+ "other{His n'ame is {person_name}.}}__'_";
+ print(msg);
+ print("{num,plural,offset:1 " +
+ "=0{no one} =1{one, that is one and # others} " +
+ "one{one and # (probably 1) others} few{one and # others} " +
+ "other{lots & lots}}");
+ print(
+ "{p1_gender,select," +
+ "female{" +
+ "{p2_gender,select," +
+ "female{" +
+ "{num_people,plural,offset:1 "+
+ "=0{she alone}" +
+ "=1{she and her girlfriend {p2}}" +
+ "=2{she and her girlfriend {p2} and another}" +
+ "other{she, her girlfriend {p2} and # others}}}" +
+ "male{" +
+ "{num_people,plural,offset:1 "+
+ "=0{she alone}" +
+ "=1{she and her boyfriend {p2}}" +
+ "=2{she and her boyfriend {p2} and another}" +
+ "other{she, her boyfriend {p2} and # others}}}" +
+ "other{" +
+ "{num_people,plural,offset:1 "+
+ "=0{she alone}" +
+ "=1{she and her friend {p2}}" +
+ "=2{she and her friend {p2} and another}" +
+ "other{she, her friend {p2} and # others}}}}}" +
+ "male{" +
+ "{p2_gender,select," +
+ "female{" +
+ "{num_people,plural,offset:1 "+
+ "=0{he alone}" +
+ "=1{he and his girlfriend {p2}}" +
+ "=2{he and his girlfriend {p2} and another}" +
+ "other{he, his girlfriend {p2} and # others}}}" +
+ "male{" +
+ "{num_people,plural,offset:1 "+
+ "=0{he alone}" +
+ "=1{he and his boyfriend {p2}}" +
+ "=2{he and his boyfriend {p2} and another}" +
+ "other{he, his boyfriend {p2} and # others}}}" +
+ "other{" +
+ "{num_people,plural,offset:1 "+
+ "=0{she alone}" +
+ "=1{she and his friend {p2}}" +
+ "=2{she and his friend {p2} and another}" +
+ "other{she, his friend {p2} and # others}}}}}" +
+ "other{" +
+ "{p2_gender,select," +
+ "female{" +
+ "{num_people,plural,offset:1 "+
+ "=0{they alone}" +
+ "=1{they and their girlfriend {p2}}" +
+ "=2{they and their girlfriend {p2} and another}" +
+ "other{they, their girlfriend {p2} and # others}}}" +
+ "male{" +
+ "{num_people,plural,offset:1 "+
+ "=0{they alone}" +
+ "=1{they and their boyfriend {p2}}" +
+ "=2{they and their boyfriend {p2} and another}" +
+ "other{they, their boyfriend {p2} and # others}}}" +
+ "other{" +
+ "{num_people,plural,offset:1 "+
+ "=0{they alone}" +
+ "=1{they and their friend {p2}}" +
+ "=2{they and their friend {p2} and another}" +
+ "other{they, their friend {p2} and # others}}}}}}");
+ }
+}
diff --git a/icu4j/samples/src/main/java/com/ibm/icu/samples/text/messagepattern/MiniMessageFormatter.java b/icu4j/samples/src/main/java/com/ibm/icu/samples/text/messagepattern/MiniMessageFormatter.java
new file mode 100644
index 000000000..aedcac118
--- /dev/null
+++ b/icu4j/samples/src/main/java/com/ibm/icu/samples/text/messagepattern/MiniMessageFormatter.java
@@ -0,0 +1,188 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+/*
+*******************************************************************************
+* Copyright (C) 2010-2011, International Business Machines
+* Corporation and others. All Rights Reserved.
+*******************************************************************************
+* created on: 2010aug21
+* created by: Markus W. Scherer
+*/
+
+package com.ibm.icu.samples.text.messagepattern;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.ibm.icu.text.MessagePattern;
+import com.ibm.icu.text.MessagePattern.ArgType;
+import com.ibm.icu.text.MessagePattern.Part;
+import com.ibm.icu.util.Freezable;
+
+/**
+ * Mini message formatter for a small subset of the ICU MessageFormat syntax.
+ * Supports only string substitution and select formatting.
+ * @author Markus Scherer
+ * @since 2010-aug-21
+ */
+public final class MiniMessageFormatter implements Freezable<MiniMessageFormatter> {
+ public MiniMessageFormatter() {
+ this.msg=new MessagePattern();
+ }
+
+ public MiniMessageFormatter(MessagePattern msg) {
+ this.msg=(MessagePattern)msg.clone();
+ }
+
+ public MiniMessageFormatter(String msg) {
+ this.msg=new MessagePattern(msg);
+ }
+
+ public MiniMessageFormatter applyPattern(String msg) {
+ this.msg.parse(msg);
+ return this;
+ }
+
+ public String getPatternString() {
+ return msg.getPatternString();
+ }
+
+ public boolean hasNamedArguments() {
+ return msg.hasNamedArguments();
+ }
+
+ public boolean hasNumberedArguments() {
+ return msg.hasNumberedArguments();
+ }
+
+ /**
+ * Formats the parsed message with positional arguments.
+ * Supports only string substitution (e.g., {3}) and select format.
+ * @param dest gets the formatted message appended
+ * @param args positional arguments
+ * @return dest
+ */
+ public Appendable format(Appendable dest, Object... args) {
+ if(msg.hasNamedArguments()) {
+ throw new IllegalArgumentException(
+ "Formatting message with named arguments using positional argument values.");
+ }
+ format(0, dest, args, null);
+ return dest;
+ }
+
+ public static final String format(String msg, Object... args) {
+ return new MiniMessageFormatter(msg).format(new StringBuilder(2*msg.length()), args).toString();
+ }
+
+ public Appendable format(Appendable dest, Map<String, Object> argsMap) {
+ if(msg.hasNumberedArguments()) {
+ throw new IllegalArgumentException(
+ "Formatting message with numbered arguments using named argument values.");
+ }
+ format(0, dest, null, argsMap);
+ return dest;
+ }
+
+ public static final String format(String msg, Map<String, Object> argsMap) {
+ return new MiniMessageFormatter(msg).format(new StringBuilder(2*msg.length()), argsMap).toString();
+ }
+
+ private int format(int msgStart, Appendable dest, Object[] args, Map<String, Object> argsMap) {
+ try {
+ String msgString=msg.getPatternString();
+ int prevIndex=msg.getPart(msgStart).getLimit();
+ for(int i=msgStart+1;; ++i) {
+ Part part=msg.getPart(i);
+ Part.Type type=part.getType();
+ int index=part.getIndex();
+ dest.append(msgString, prevIndex, index);
+ if(type==Part.Type.MSG_LIMIT) {
+ return i;
+ }
+ if(type==Part.Type.SKIP_SYNTAX || type==Part.Type.INSERT_CHAR) {
+ prevIndex=part.getLimit();
+ continue;
+ }
+ assert type==Part.Type.ARG_START : "Unexpected Part "+part+" in parsed message.";
+ int argLimit=msg.getLimitPartIndex(i);
+ ArgType argType=part.getArgType();
+ part=msg.getPart(++i);
+ Object arg;
+ if(args!=null) {
+ try {
+ arg=args[part.getValue()]; // args[ARG_NUMBER]
+ } catch(IndexOutOfBoundsException e) {
+ throw new IndexOutOfBoundsException(
+ "No argument at index "+part.getValue());
+ }
+ } else {
+ arg=argsMap.get(msg.getSubstring(part)); // args[ARG_NAME]
+ if(arg==null) {
+ throw new IndexOutOfBoundsException(
+ "No argument for name "+msg.getSubstring(part));
+ }
+ }
+ String argValue=arg.toString();
+ ++i;
+ if(argType==ArgType.NONE) {
+ dest.append(argValue);
+ } else if(argType==ArgType.SELECT) {
+ // Similar to SelectFormat.findSubMessage().
+ int subMsgStart=0;
+ for(;; ++i) { // (ARG_SELECTOR, message) pairs until ARG_LIMIT
+ part=msg.getPart(i++);
+ if(part.getType()==Part.Type.ARG_LIMIT) {
+ assert subMsgStart!=0; // The parser made sure this is the case.
+ break;
+ // else: part is an ARG_SELECTOR followed by a message
+ } else if(msg.partSubstringMatches(part, argValue)) {
+ // keyword matches
+ subMsgStart=i;
+ break;
+ } else if(subMsgStart==0 && msg.partSubstringMatches(part, "other")) {
+ subMsgStart=i;
+ }
+ i=msg.getLimitPartIndex(i);
+ }
+ format(subMsgStart, dest, args, argsMap);
+ } else {
+ throw new UnsupportedOperationException("Unsupported argument type "+argType);
+ }
+ prevIndex=msg.getPart(argLimit).getLimit();
+ i=argLimit;
+ }
+ } catch(IOException e) { // Appendable throws IOException
+ throw new RuntimeException(e); // We do not want a throws clause.
+ }
+ }
+
+ /**
+ * Presents an array of (String, Object) pairs as a Map.
+ * Only for temporary use for formatting with named arguments.
+ */
+ public static Map<String, Object> mapFromNameValuePairs(Object[] args) {
+ HashMap<String, Object> argsMap = new HashMap<String, Object>();
+ for(int i=0; i<args.length; i+=2) {
+ argsMap.put((String)args[i], args[i+1]);
+ }
+ return argsMap;
+ }
+
+ public MiniMessageFormatter cloneAsThawed() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public MiniMessageFormatter freeze() {
+ msg.freeze();
+ return this;
+ }
+
+ public boolean isFrozen() {
+ return msg.isFrozen();
+ }
+
+ private final MessagePattern msg;
+}
diff --git a/icu4j/samples/src/main/java/com/ibm/icu/samples/text/pluralformat/PluralFormatSample.java b/icu4j/samples/src/main/java/com/ibm/icu/samples/text/pluralformat/PluralFormatSample.java
new file mode 100644
index 000000000..c40b35cb5
--- /dev/null
+++ b/icu4j/samples/src/main/java/com/ibm/icu/samples/text/pluralformat/PluralFormatSample.java
@@ -0,0 +1,97 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+/*
+ *******************************************************************************
+ * Copyright (C) 2013-2014, International Business Machines Corporation and *
+ * others. All Rights Reserved. *
+ *******************************************************************************
+ */
+package com.ibm.icu.samples.text.pluralformat;
+// ---PluralFormatExample
+import java.text.FieldPosition;
+
+import com.ibm.icu.text.MessageFormat;
+import com.ibm.icu.text.PluralFormat;
+import com.ibm.icu.util.ULocale;
+// ---PluralFormatExample
+
+public class PluralFormatSample {
+
+ public static void main(String[] args) {
+ PluralFormatExample();
+ }
+
+ private static void PluralFormatExample(){
+
+ System.out.println("=======================================================================================");
+ System.out.println(" PluralFormatExample()");
+ System.out.println();
+ System.out.println(" Use PluralFormat and Messageformat to get appropriate Plural Form for languages below:");
+ System.out.println(" English, Slovenian");
+ System.out.println("=======================================================================================");
+ // ---PluralFormatExample
+ ULocale locEn = new ULocale("en");
+ ULocale locSl = new ULocale("sl");
+
+ String patEn = "one{dog} other{dogs}"; // English 'dog'
+ String patSl = "one{pes} two{psa} few{psi} other{psov}"; // Slovenian translation of dog in Plural Form
+
+ // Create a new PluralFormat for a given locale locale and pattern string
+ PluralFormat plfmtEn = new PluralFormat(locEn, patEn);
+ PluralFormat plfmtSl = new PluralFormat(locSl, patSl);
+ // Constructs a MessageFormat for the specified locale and pattern.
+ MessageFormat msgfmtEn = new MessageFormat("{0,number} {1}", locEn);
+ MessageFormat msgfmtSl = new MessageFormat("{0,number} {1}", locSl);
+
+ final int[] numbers = {0, 1, 2, 3, 4, 5, 10, 100, 101, 102};
+ System.out.println("Output by using PluralFormat and MessageFormat API\n");
+ System.out.printf("%-16s%-16s%-16s\n", "Number", "English", "Slovenian");
+
+ // Use MessageFormat.format () to format the objects and appends to the given StringBuffer
+ for (int num : numbers) {
+ StringBuffer msgEn = new StringBuffer();
+ StringBuffer msgSl = new StringBuffer();
+
+ msgfmtEn.format(new Object[] {num, plfmtEn.format(num)}, msgEn, new FieldPosition(0));
+ msgfmtSl.format(new Object[] {num, plfmtSl.format(num)}, msgSl, new FieldPosition(0));
+
+ System.out.printf("%-16s%-16s%-16s\n", num, msgEn, msgSl);
+ }
+
+ System.out.println();
+
+ // Equivalent code with message format pattern
+ String msgPatEn = "{0,plural, one{# dog} other{# dogs}}";
+ String msgPatSl = "{0,plural, one{# pes} two{# psa} few{# psi} other{# psov}}";
+
+ MessageFormat altMsgfmtEn = new MessageFormat(msgPatEn, locEn);
+ MessageFormat altMsgfmtSl = new MessageFormat(msgPatSl, locSl);
+ System.out.println("Same Output by using MessageFormat API only\n");
+ System.out.printf("%-16s%-16s%-16s\n", "Number", "English", "Slovenian");
+ for (int num : numbers) {
+ StringBuffer msgEn = new StringBuffer();
+ StringBuffer msgSl = new StringBuffer();
+
+ altMsgfmtEn.format(new Object[] {num}, msgEn, new FieldPosition(0));
+ altMsgfmtSl.format(new Object[] {num}, msgSl, new FieldPosition(0));
+
+ System.out.printf("%-16s%-16s%-16s\n", num, msgEn, msgSl);
+ }
+ /** output of the sample code:
+ ********************************************************************
+ Number English Slovenian
+ 0 0 dogs 0 psov
+ 1 1 dog 1 pes
+ 2 2 dogs 2 psa
+ 3 3 dogs 3 psi
+ 4 4 dogs 4 psi
+ 5 5 dogs 5 psov
+ 10 10 dogs 10 psov
+ 100 100 dogs 100 psov
+ 101 101 dogs 101 pes
+ 102 102 dogs 102 psa
+
+ *******************************************************************/
+ // ---PluralFormatExample
+ }
+}
diff --git a/icu4j/samples/src/main/java/com/ibm/icu/samples/util/timescale/PivotDemo.java b/icu4j/samples/src/main/java/com/ibm/icu/samples/util/timescale/PivotDemo.java
new file mode 100644
index 000000000..976b51b5e
--- /dev/null
+++ b/icu4j/samples/src/main/java/com/ibm/icu/samples/util/timescale/PivotDemo.java
@@ -0,0 +1,80 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+/*
+ *******************************************************************************
+ * Copyright (C) 1996-2011, International Business Machines Corporation and *
+ * others. All Rights Reserved. *
+ *******************************************************************************
+ *
+ */
+
+package com.ibm.icu.samples.util.timescale;
+
+import java.util.Locale;
+
+import com.ibm.icu.text.MessageFormat;
+import com.ibm.icu.util.Calendar;
+import com.ibm.icu.util.SimpleTimeZone;
+import com.ibm.icu.util.TimeZone;
+import com.ibm.icu.util.UniversalTimeScale;
+
+/**
+ * This class demonstrates how to use <code>UniversalTimeScale</code> to
+ * convert from one local time scale to another.
+ *
+ * @see UniversalTimeScale
+ */
+public class PivotDemo {
+
+ /**
+ * The default constructor.
+ */
+ public PivotDemo()
+ {
+ }
+
+ /**
+ * The <code>main()</code> method uses <code>UniversalTimeScale</code> to
+ * convert from the Java and Unix time scales to the ICU time scale. It uses
+ * a <code>Calendar</code> object to display the ICU time values.
+ *
+ * @param args the command line arguments.
+ */
+ public static void main(String[] args)
+ {
+ TimeZone utc = new SimpleTimeZone(0, "UTC");
+ Calendar cal = Calendar.getInstance(utc, Locale.ENGLISH);
+ MessageFormat fmt = new MessageFormat("{1} = {0, date, full} {0, time, full}");
+ Object arguments[] = {cal, null};
+
+ arguments[0] = cal;
+
+ System.out.println("\nJava test:");
+ cal.setTimeInMillis(UniversalTimeScale.toLong(UniversalTimeScale.from(0, UniversalTimeScale.JAVA_TIME), UniversalTimeScale.ICU4C_TIME));
+ arguments[1] = " 000000000000000";
+ System.out.println(fmt.format(arguments));
+
+ cal.setTimeInMillis(UniversalTimeScale.toLong(UniversalTimeScale.from(-62164684800000L, UniversalTimeScale.JAVA_TIME), UniversalTimeScale.ICU4C_TIME));
+ arguments[1] = "-62164684800000L";
+ System.out.println(fmt.format(arguments));
+
+ cal.setTimeInMillis(UniversalTimeScale.toLong(UniversalTimeScale.from(-62135769600000L, UniversalTimeScale.JAVA_TIME), UniversalTimeScale.ICU4C_TIME));
+ arguments[1] = "-62135769600000L";
+ System.out.println(fmt.format(arguments));
+
+ System.out.println("\nUnix test:");
+
+ cal.setTimeInMillis(UniversalTimeScale.toLong(UniversalTimeScale.from(0x80000000, UniversalTimeScale.UNIX_TIME), UniversalTimeScale.ICU4C_TIME));
+ arguments[1] = "0x80000000";
+ System.out.println(fmt.format(arguments));
+
+ cal.setTimeInMillis(UniversalTimeScale.toLong(UniversalTimeScale.from(0, UniversalTimeScale.UNIX_TIME), UniversalTimeScale.ICU4C_TIME));
+ arguments[1] = "0x00000000";
+ System.out.println(fmt.format(arguments));
+
+ cal.setTimeInMillis(UniversalTimeScale.toLong(UniversalTimeScale.from(0x7FFFFFFF, UniversalTimeScale.UNIX_TIME), UniversalTimeScale.ICU4C_TIME));
+ arguments[1] = "0x7FFFFFFF";
+ System.out.println(fmt.format(arguments));
+
+ }
+}
diff --git a/icu4j/samples/src/main/java/com/ibm/icu/samples/util/timezone/BasicTimeZoneExample.java b/icu4j/samples/src/main/java/com/ibm/icu/samples/util/timezone/BasicTimeZoneExample.java
new file mode 100644
index 000000000..600846309
--- /dev/null
+++ b/icu4j/samples/src/main/java/com/ibm/icu/samples/util/timezone/BasicTimeZoneExample.java
@@ -0,0 +1,131 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+/*
+ *******************************************************************************
+ * Copyright (C) 2011, International Business Machines Corporation and *
+ * others. All Rights Reserved. *
+ *******************************************************************************
+ */
+package com.ibm.icu.samples.util.timezone;
+
+import java.util.Date;
+
+import com.ibm.icu.text.SimpleDateFormat;
+import com.ibm.icu.util.BasicTimeZone;
+import com.ibm.icu.util.Calendar;
+import com.ibm.icu.util.GregorianCalendar;
+import com.ibm.icu.util.TimeZone;
+import com.ibm.icu.util.TimeZoneRule;
+import com.ibm.icu.util.TimeZoneTransition;
+import com.ibm.icu.util.ULocale;
+
+/**
+ * com.ibm.icu.util.BasicTimeZone Coding Examples
+ */
+public class BasicTimeZoneExample {
+ public static void main(String... args) {
+ nextTransitionExample();
+ previousTransitionExample();
+ timeZoneRulesExample();
+ equivalentTransitionsExample();
+ }
+
+ public static void nextTransitionExample() {
+ // ---getNextTransitionExample
+ System.out.println("### Iterates time zone transitions in America/Los_Angeles starting 2005-01-01 and forward");
+
+ // A TimeZone instance created by getTimeZone with TIMEZONE_ICU is always a BasicTimeZone
+ BasicTimeZone btz = (BasicTimeZone)TimeZone.getTimeZone("America/Los_Angeles", TimeZone.TIMEZONE_ICU);
+
+ // Date format for the wall time
+ SimpleDateFormat wallTimeFmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z", ULocale.US);
+ wallTimeFmt.setTimeZone(btz);
+
+ long start = 1104537600000L; // 2005-01-01 0:00 UTC
+ for (int i = 0; i < 5; i++) { // Up to 5 transitions
+ TimeZoneTransition trans = btz.getNextTransition(start, false /* not including start time */);
+
+ // Display the transition time and offset information
+ long transTime = trans.getTime();
+ System.out.println(wallTimeFmt.format(new Date(transTime - 1)) + " -> " + wallTimeFmt.format(new Date(transTime)));
+ System.out.println(" - Before (Offset/Save): " + trans.getFrom().getRawOffset() + "/" + trans.getFrom().getDSTSavings());
+ System.out.println(" - After (Offset/Save): " + trans.getTo().getRawOffset() + "/" + trans.getTo().getDSTSavings());
+
+ // Update start time for next transition
+ start = transTime;
+ }
+ // ---getNextTransitionExample
+ }
+
+ public static void previousTransitionExample() {
+ // ---getPreviousTransitionExample
+ System.out.println("### Iterates time zone transitions in America/Los_Angeles starting 2010-01-01 and backward");
+
+ // A TimeZone instance created by getTimeZone with TIMEZONE_ICU is always a BasicTimeZone
+ BasicTimeZone btz = (BasicTimeZone)TimeZone.getTimeZone("America/Los_Angeles", TimeZone.TIMEZONE_ICU);
+
+ // Date format for the wall time
+ SimpleDateFormat wallTimeFmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z", ULocale.US);
+ wallTimeFmt.setTimeZone(btz);
+
+ long start = 1262304000000L; // 2010-01-01 0:00 UTC
+ for (int i = 0; i < 5; i++) { // Up to 5 transitions
+ TimeZoneTransition trans = btz.getPreviousTransition(start, false /* not including start time */);
+
+ // Display the transition time and offset information
+ long transTime = trans.getTime();
+ System.out.println(wallTimeFmt.format(new Date(transTime - 1)) + " -> " + wallTimeFmt.format(new Date(transTime)));
+ System.out.println(" - Before (Offset/Save): " + trans.getFrom().getRawOffset() + "/" + trans.getFrom().getDSTSavings());
+ System.out.println(" - After (Offset/Save): " + trans.getTo().getRawOffset() + "/" + trans.getTo().getDSTSavings());
+
+ // Update start time for next transition
+ start = transTime;
+ }
+ // ---getPreviousTransitionExample
+ }
+
+ public static void timeZoneRulesExample() {
+ // ---getTimeZoneRulesExample
+ System.out.println("### Extracts time zone rules used by America/Los_Angeles since year 2005");
+
+ // A TimeZone instance created by getTimeZone with TIMEZONE_ICU is always a BasicTimeZone
+ BasicTimeZone btz = (BasicTimeZone)TimeZone.getTimeZone("America/Los_Angeles", TimeZone.TIMEZONE_ICU);
+ long since = 1104537600000L; // 2005-01-01 0:00 UTC
+ TimeZoneRule[] rules = btz.getTimeZoneRules(since);
+ System.out.println("Rule(initial): " + rules[0]);
+ for (int i = 1; i < rules.length; i++) {
+ System.out.println("Rule: " + rules[i]);
+ }
+ // ---getTimeZoneRulesExample
+ }
+
+ public static void equivalentTransitionsExample() {
+ // ---hasEquivalentTransitionsExample
+ System.out.println("### Compare America/New_York and America/Detroit since year 1970");
+
+ // A TimeZone instance created by getTimeZone with TIMEZONE_ICU is always a BasicTimeZone
+ BasicTimeZone tzNewYork = (BasicTimeZone)TimeZone.getTimeZone("America/New_York", TimeZone.TIMEZONE_ICU);
+ BasicTimeZone tzDetroit = (BasicTimeZone)TimeZone.getTimeZone("America/Detroit", TimeZone.TIMEZONE_ICU);
+
+ GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone("Etc/GMT"));
+
+ // Compare these time zones every 10 years since year 1970 up to year 2009
+ for (int startYear = 1970; startYear <= 2000; startYear += 10) {
+ long start, end;
+
+ cal.set(startYear, Calendar.JANUARY, 1, 0, 0, 0);
+ cal.set(Calendar.MILLISECOND, 0);
+ start = cal.getTimeInMillis();
+
+ // Set the end time to the end of startYear + 9
+ int endYear = startYear + 9;
+ cal.set(endYear + 1, Calendar.JANUARY, 1, 0, 0, 0);
+ end = cal.getTimeInMillis() - 1;
+
+ // Check if these two zones have equivalent time zone transitions for the given time range
+ boolean isEquivalent = tzNewYork.hasEquivalentTransitions(tzDetroit, start, end);
+ System.out.println(startYear + "-" + endYear + ": " + isEquivalent);
+ }
+ // ---hasEquivalentTransitionsExample
+ }
+}