12ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller/* GENERATED SOURCE. DO NOT MODIFY. */ 2f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert// © 2016 and later: Unicode, Inc. and others. 3f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html#License 42ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller/* 52ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller ******************************************************************************* 6bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * Copyright (C) 2004-2016, International Business Machines Corporation and * 72ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * others. All Rights Reserved. * 82ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Copyright (C) 2009 , Yahoo! Inc. * 92ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller ******************************************************************************* 102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerpackage android.icu.text; 122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.io.IOException; 142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.io.ObjectInputStream; 152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.text.FieldPosition; 162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.text.Format; 172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.text.ParsePosition; 182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport android.icu.impl.PatternProps; 202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller/** 222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p><code>SelectFormat</code> supports the creation of internationalized 232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * messages by selecting phrases based on keywords. The pattern specifies 242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * how to map keywords to phrases and provides a default phrase. The 252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * object provided to the format method is a string that's matched 262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * against the keywords. If there is a match, the corresponding phrase 27bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * is selected; otherwise, the default phrase is used. 282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 29bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <h3>Using <code>SelectFormat</code> for Gender Agreement</h3> 302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>Note: Typically, select formatting is done via <code>MessageFormat</code> 322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * with a <code>select</code> argument type, 33bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * rather than using a stand-alone <code>SelectFormat</code>. 342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>The main use case for the select format is gender based inflection. 362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * When names or nouns are inserted into sentences, their gender can affect pronouns, 372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * verb forms, articles, and adjectives. Special care needs to be 382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * taken for the case where the gender cannot be determined. 39bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * The impact varies between languages: 402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <ul> 422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <li>English has three genders, and unknown gender is handled as a special 432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * case. Names use the gender of the named person (if known), nouns referring 442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * to people use natural gender, and inanimate objects are usually neutral. 452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * The gender only affects pronouns: "he", "she", "it", "they". 462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <li>German differs from English in that the gender of nouns is rather 48bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * arbitrary, even for nouns referring to people ("Mädchen", girl, is neutral). 492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * The gender affects pronouns ("er", "sie", "es"), articles ("der", "die", 50bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * "das"), and adjective forms ("guter Mann", "gute Frau", "gutes Mädchen"). 512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <li>French has only two genders; as in German the gender of nouns 532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * is rather arbitrary - for sun and moon, the genders 542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * are the opposite of those in German. The gender affects 552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * pronouns ("il", "elle"), articles ("le", "la"), 562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * adjective forms ("bon", "bonne"), and sometimes 57bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * verb forms ("allé", "allée"). 582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <li>Polish distinguishes five genders (or noun classes), 602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * human masculine, animate non-human masculine, inanimate masculine, 612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * feminine, and neuter. 622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </ul> 632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>Some other languages have noun classes that are not related to gender, 652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * but similar in grammatical use. 66bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * Some African languages have around 20 noun classes. 672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p><b>Note:</b>For the gender of a <i>person</i> in a given sentence, 69bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * we usually need to distinguish only between female, male and other/unknown. 702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>To enable localizers to create sentence patterns that take their 722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * language's gender dependencies into consideration, software has to provide 732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * information about the gender associated with a noun or name to 742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <code>MessageFormat</code>. 75bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * Two main cases can be distinguished: 762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <ul> 782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <li>For people, natural gender information should be maintained for each person. 792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Keywords like "male", "female", "mixed" (for groups of people) 802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * and "unknown" could be used. 812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <li>For nouns, grammatical gender information should be maintained for 832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * each noun and per language, e.g., in resource bundles. 842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * The keywords "masculine", "feminine", and "neuter" are commonly used, 852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * but some languages may require other keywords. 862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </ul> 872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>The resulting keyword is provided to <code>MessageFormat</code> as a 892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * parameter separate from the name or noun it's associated with. For example, 902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * to generate a message such as "Jean went to Paris", three separate arguments 912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * would be provided: The name of the person as argument 0, the gender of 922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * the person as argument 1, and the name of the city as argument 2. 932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * The sentence pattern for English, where the gender of the person has 94bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * no impact on this simple sentence, would not refer to argument 1 at all: 952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <pre>{0} went to {2}.</pre> 972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p><b>Note:</b> The entire sentence should be included (and partially repeated) 992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * inside each phrase. Otherwise translators would have to be trained on how to 1002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * move bits of the sentence in and out of the select argument of a message. 101bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * (The examples below do not follow this recommendation!) 1022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 1032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>The sentence pattern for French, where the gender of the person affects 104bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * the form of the participle, uses a select format based on argument 1: 1052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 106bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <pre>{0} est {1, select, female {allée} other {allé}} à {2}.</pre> 1072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 1082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>Patterns can be nested, so that it's possible to handle interactions of 1092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * number and gender where necessary. For example, if the above sentence should 1102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * allow for the names of several people to be inserted, the following sentence 1112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * pattern can be used (with argument 0 the list of people's names, 1122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * argument 1 the number of people, argument 2 their combined gender, and 113bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * argument 3 the city name): 1142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 1152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <pre>{0} {1, plural, 116bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * one {est {2, select, female {allée} other {allé}}} 117bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * other {sont {2, select, female {allées} other {allés}}} 118bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * }à {3}.</pre> 1192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 1202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <h4>Patterns and Their Interpretation</h4> 1212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 1222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>The <code>SelectFormat</code> pattern string defines the phrase output 1232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * for each user-defined keyword. 1242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * The pattern is a sequence of (keyword, message) pairs. 125bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * A keyword is a "pattern identifier": [^[[:Pattern_Syntax:][:Pattern_White_Space:]]]+ 1262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 127bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <p>Each message is a MessageFormat pattern string enclosed in {curly braces}. 1282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 1292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>You always have to define a phrase for the default keyword 1302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <code>other</code>; this phrase is returned when the keyword 1312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * provided to 1322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * the <code>format</code> method matches no other keyword. 1332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * If a pattern does not provide a phrase for <code>other</code>, the method 1342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * it's provided to returns the error <code>U_DEFAULT_KEYWORD_MISSING</code>. 135bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <br> 1362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Pattern_White_Space between keywords and messages is ignored. 137bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * Pattern_White_Space within a message is preserved and output. 1382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 139bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <pre>Example: 1402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * MessageFormat msgFmt = new MessageFormat("{0} est " + 141bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * "{1, select, female {allée} other {allé}} à Paris.", 1422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * new ULocale("fr")); 1432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Object args[] = {"Kirti","female"}; 1442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * System.out.println(msgFmt.format(args)); 1452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </pre> 1462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p> 147bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * Produces the output:<br> 148bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <code>Kirti est allée à Paris.</code> 1492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 1502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 1512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerpublic class SelectFormat extends Format{ 1522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // Generated by serialver from JDK 1.5 1532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private static final long serialVersionUID = 2993154333257524984L; 1542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 1552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /* 1562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * The applied pattern string. 1572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 1582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private String pattern = null; 1592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 1602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 1612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * The MessagePattern which contains the parsed structure of the pattern string. 1622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 1632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller transient private MessagePattern msgPattern; 1642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 1652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 1662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Creates a new <code>SelectFormat</code> for a given pattern string. 1672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param pattern the pattern for this <code>SelectFormat</code>. 1682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 1692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public SelectFormat(String pattern) { 1702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller applyPattern(pattern); 1712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 1722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 1732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /* 1742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Resets the <code>SelectFormat</code> object. 1752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 1762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private void reset() { 1772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller pattern = null; 1782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if(msgPattern != null) { 1792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller msgPattern.clear(); 1802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 1812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 1822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 1832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 1842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Sets the pattern used by this select format. 1852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Patterns and their interpretation are specified in the class description. 1862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 1872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param pattern the pattern for this select format. 1882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @throws IllegalArgumentException when the pattern is not a valid select format pattern. 1892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 1902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public void applyPattern(String pattern) { 1912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller this.pattern = pattern; 1922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (msgPattern == null) { 1932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller msgPattern = new MessagePattern(); 1942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 1952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller try { 1962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller msgPattern.parseSelectStyle(pattern); 1972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } catch(RuntimeException e) { 1982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller reset(); 1992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller throw e; 2002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 2012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 2022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 2032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 2042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Returns the pattern for this <code>SelectFormat</code> 2052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 2062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @return the pattern string 2072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 2082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public String toPattern() { 2092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return pattern; 2102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 2112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 2122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 2132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Finds the SelectFormat sub-message for the given keyword, or the "other" sub-message. 2142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param pattern A MessagePattern. 2152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param partIndex the index of the first SelectFormat argument style part. 2162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param keyword a keyword to be matched to one of the SelectFormat argument's keywords. 2172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @return the sub-message start part index. 2182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 2192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /*package*/ static int findSubMessage(MessagePattern pattern, int partIndex, String keyword) { 2202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller int count=pattern.countParts(); 2212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller int msgStart=0; 2222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // Iterate over (ARG_SELECTOR, message) pairs until ARG_LIMIT or end of select-only pattern. 2232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller do { 2242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller MessagePattern.Part part=pattern.getPart(partIndex++); 2252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller MessagePattern.Part.Type type=part.getType(); 2262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if(type==MessagePattern.Part.Type.ARG_LIMIT) { 2272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller break; 2282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 2292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller assert type==MessagePattern.Part.Type.ARG_SELECTOR; 2302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // part is an ARG_SELECTOR followed by a message 2312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if(pattern.partSubstringMatches(part, keyword)) { 2322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // keyword matches 2332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return partIndex; 2342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } else if(msgStart==0 && pattern.partSubstringMatches(part, "other")) { 2352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller msgStart=partIndex; 2362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 2372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller partIndex=pattern.getLimitPartIndex(partIndex); 2382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } while(++partIndex<count); 2392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return msgStart; 2402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 2412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 2422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 2432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Selects the phrase for the given keyword. 2442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 2452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param keyword a phrase selection keyword. 2462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @return the string containing the formatted select message. 2472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @throws IllegalArgumentException when the given keyword is not a "pattern identifier" 2482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 2492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public final String format(String keyword) { 2502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller //Check for the validity of the keyword 2512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (!PatternProps.isIdentifier(keyword)) { 2522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller throw new IllegalArgumentException("Invalid formatting argument."); 2532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 2542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // If no pattern was applied, throw an exception 2552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (msgPattern == null || msgPattern.countParts() == 0) { 2562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller throw new IllegalStateException("Invalid format error."); 2572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 2582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 2592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // Get the appropriate sub-message. 2602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller int msgStart = findSubMessage(msgPattern, 0, keyword); 2612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (!msgPattern.jdkAposMode()) { 2622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller int msgLimit = msgPattern.getLimitPartIndex(msgStart); 2632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return msgPattern.getPatternString().substring(msgPattern.getPart(msgStart).getLimit(), 2642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller msgPattern.getPatternIndex(msgLimit)); 2652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 2662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // JDK compatibility mode: Remove SKIP_SYNTAX. 2672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller StringBuilder result = null; 2682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller int prevIndex = msgPattern.getPart(msgStart).getLimit(); 2692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller for (int i = msgStart;;) { 2702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller MessagePattern.Part part = msgPattern.getPart(++i); 2712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller MessagePattern.Part.Type type = part.getType(); 2722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller int index = part.getIndex(); 2732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (type == MessagePattern.Part.Type.MSG_LIMIT) { 2742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (result == null) { 2752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return pattern.substring(prevIndex, index); 2762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } else { 2772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return result.append(pattern, prevIndex, index).toString(); 2782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 2792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } else if (type == MessagePattern.Part.Type.SKIP_SYNTAX) { 2802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (result == null) { 2812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller result = new StringBuilder(); 2822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 2832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller result.append(pattern, prevIndex, index); 2842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller prevIndex = part.getLimit(); 2852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } else if (type == MessagePattern.Part.Type.ARG_START) { 2862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (result == null) { 2872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller result = new StringBuilder(); 2882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 2892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller result.append(pattern, prevIndex, index); 2902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller prevIndex = index; 2912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller i = msgPattern.getLimitPartIndex(i); 2922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller index = msgPattern.getPart(i).getLimit(); 2932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller MessagePattern.appendReducedApostrophes(pattern, prevIndex, index, result); 2942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller prevIndex = index; 2952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 2962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 2972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 2982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 2992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 3002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Selects the phrase for the given keyword. 3012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * and appends the formatted message to the given <code>StringBuffer</code>. 3022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param keyword a phrase selection keyword. 3032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param toAppendTo the selected phrase will be appended to this 3042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <code>StringBuffer</code>. 3052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param pos will be ignored by this method. 3062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @throws IllegalArgumentException when the given keyword is not a String 3072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * or not a "pattern identifier" 3082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @return the string buffer passed in as toAppendTo, with formatted text 3092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * appended. 3102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 3112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public StringBuffer format(Object keyword, StringBuffer toAppendTo, 3122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller FieldPosition pos) { 3132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (keyword instanceof String) { 3142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller toAppendTo.append(format( (String)keyword)); 3152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller }else{ 3162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller throw new IllegalArgumentException("'" + keyword + "' is not a String"); 3172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 3182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return toAppendTo; 3192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 3202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 3212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 3222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * This method is not supported by <code>SelectFormat</code>. 3232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param source the string to be parsed. 3242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param pos defines the position where parsing is to begin, 3252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * and upon return, the position where parsing left off. If the position 3262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * has not changed upon return, then parsing failed. 3272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @return nothing because this method is not supported. 3282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @throws UnsupportedOperationException thrown always. 3292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 3302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public Object parseObject(String source, ParsePosition pos) { 3312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller throw new UnsupportedOperationException(); 3322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 3332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 3342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 3352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * {@inheritDoc} 3362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 3372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller @Override 3382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public boolean equals(Object obj) { 3392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if(this == obj) { 3402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return true; 3412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 3422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if(obj == null || getClass() != obj.getClass()) { 3432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return false; 3442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 3452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller SelectFormat sf = (SelectFormat) obj; 3462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return msgPattern == null ? sf.msgPattern == null : msgPattern.equals(sf.msgPattern); 3472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 3482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 3492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 3502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * {@inheritDoc} 3512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 3522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller @Override 3532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public int hashCode() { 3542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (pattern != null) { 3552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return pattern.hashCode(); 3562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 3572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return 0; 3582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 3592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 3602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 3612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * {@inheritDoc} 3622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 3632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller @Override 3642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public String toString() { 3652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return "pattern='" + pattern + "'"; 3662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 3672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 3682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private void readObject(ObjectInputStream in) 3692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller throws IOException, ClassNotFoundException { 3702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller in.defaultReadObject(); 3712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (pattern != null) { 3722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller applyPattern(pattern); 3732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 3742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 3752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller} 376