15d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath/* 25d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath ******************************************************************************* 38d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath * Copyright (C) 2007-2014, International Business Machines Corporation and 45d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * others. All Rights Reserved. 55d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath ******************************************************************************* 65d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 75d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 88d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamathpackage com.ibm.icu.simple; 95d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 105d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamathimport java.io.IOException; 115d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamathimport java.io.NotSerializableException; 125d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamathimport java.io.ObjectInputStream; 135d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamathimport java.io.ObjectOutputStream; 145d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamathimport java.io.Serializable; 155d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamathimport java.text.ParseException; 165d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamathimport java.util.ArrayList; 175d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamathimport java.util.Collection; 185d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamathimport java.util.Collections; 195d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamathimport java.util.HashSet; 205d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamathimport java.util.Iterator; 215d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamathimport java.util.LinkedHashSet; 225d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamathimport java.util.List; 235d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamathimport java.util.Locale; 245d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamathimport java.util.Set; 255d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamathimport java.util.TreeSet; 265d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamathimport java.util.regex.Pattern; 275d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 285d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamathimport com.ibm.icu.util.Output; 295d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 305d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath/** 315d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <p> 325d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Defines rules for mapping non-negative numeric values onto a small set of keywords. 335d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * </p> 345d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <p> 355d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Rules are constructed from a text description, consisting of a series of keywords and conditions. The {@link #select} 365d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * method examines each condition in order and returns the keyword for the first condition that matches the number. If 375d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * none match, {@link #KEYWORD_OTHER} is returned. 385d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * </p> 395d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <p> 405d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * A PluralRules object is immutable. It contains caches for sample values, but those are synchronized. 415d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <p> 425d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * PluralRules is Serializable so that it can be used in formatters, which are serializable. 435d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * </p> 445d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <p> 455d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * For more information, details, and tips for writing rules, see the <a 465d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * href="http://www.unicode.org/draft/reports/tr35/tr35.html#Language_Plural_Rules">LDML spec, C.11 Language Plural 475d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Rules</a> 485d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * </p> 495d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <p> 505d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Examples: 515d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * </p> 525d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * 535d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <pre> 545d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * "one: n is 1; few: n in 2..4" 555d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * </pre> 565d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <p> 575d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * This defines two rules, for 'one' and 'few'. The condition for 'one' is "n is 1" which means that the number must be 585d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * equal to 1 for this condition to pass. The condition for 'few' is "n in 2..4" which means that the number must be 595d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * between 2 and 4 inclusive - and be an integer - for this condition to pass. All other numbers are assigned the 605d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * keyword "other" by the default rule. 615d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * </p> 625d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * 635d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <pre> 645d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * "zero: n is 0; one: n is 1; zero: n mod 100 in 1..19" 655d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * </pre> 665d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <p> 675d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * This illustrates that the same keyword can be defined multiple times. Each rule is examined in order, and the first 685d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * keyword whose condition passes is the one returned. Also notes that a modulus is applied to n in the last rule. Thus 695d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * its condition holds for 119, 219, 319... 705d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * </p> 715d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * 725d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <pre> 735d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * "one: n is 1; few: n mod 10 in 2..4 and n mod 100 not in 12..14" 745d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * </pre> 755d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <p> 765d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * This illustrates conjunction and negation. The condition for 'few' has two parts, both of which must be met: 775d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * "n mod 10 in 2..4" and "n mod 100 not in 12..14". The first part applies a modulus to n before the test as in the 785d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * previous example. The second part applies a different modulus and also uses negation, thus it matches all numbers 795d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * _not_ in 12, 13, 14, 112, 113, 114, 212, 213, 214... 805d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * </p> 815d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <p> 825d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Syntax: 835d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * </p> 845d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <pre> 855d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * rules = rule (';' rule)* 865d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * rule = keyword ':' condition 875d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * keyword = <identifier> 885d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * condition = and_condition ('or' and_condition)* 895d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * and_condition = relation ('and' relation)* 905d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * relation = not? expr not? rel not? range_list 915d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * expr = ('n' | 'i' | 'f' | 'v' | 't') (mod value)? 925d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * not = 'not' | '!' 935d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * rel = 'in' | 'is' | '=' | '≠' | 'within' 945d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * mod = 'mod' | '%' 955d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * range_list = (range | value) (',' range_list)* 965d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * value = digit+ 975d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * digit = 0|1|2|3|4|5|6|7|8|9 985d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * range = value'..'value 995d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * </pre> 1005d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <p>Each <b>not</b> term inverts the meaning; however, there should not be more than one of them.</p> 1015d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <p> 1025d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * The i, f, t, and v values are defined as follows: 1035d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * </p> 1045d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <ul> 1055d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <li>i to be the integer digits.</li> 1065d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <li>f to be the visible decimal digits, as an integer.</li> 1075d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <li>t to be the visible decimal digits—without trailing zeros—as an integer.</li> 1085d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <li>v to be the number of visible fraction digits.</li> 1095d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <li>j is defined to only match integers. That is j is 3 fails if v != 0 (eg for 3.1 or 3.0).</li> 1105d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * </ul> 1115d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <p> 1125d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Examples are in the following table: 1135d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * </p> 1145d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <table border='1' style="border-collapse:collapse"> 1155d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <tbody> 1165d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <tr> 1175d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <th>n</th> 1185d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <th>i</th> 1195d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <th>f</th> 1205d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <th>v</th> 1215d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * </tr> 1225d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <tr> 1235d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <td>1.0</td> 1245d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <td>1</td> 1255d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <td align="right">0</td> 1265d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <td>1</td> 1275d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * </tr> 1285d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <tr> 1295d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <td>1.00</td> 1305d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <td>1</td> 1315d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <td align="right">0</td> 1325d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <td>2</td> 1335d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * </tr> 1345d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <tr> 1355d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <td>1.3</td> 1365d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <td>1</td> 1375d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <td align="right">3</td> 1385d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <td>1</td> 1395d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * </tr> 1405d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <tr> 1415d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <td>1.03</td> 1425d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <td>1</td> 1435d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <td align="right">3</td> 1445d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <td>2</td> 1455d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * </tr> 1465d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <tr> 1475d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <td>1.23</td> 1485d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <td>1</td> 1495d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <td align="right">23</td> 1505d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <td>2</td> 1515d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * </tr> 1525d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * </tbody> 1535d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * </table> 1545d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <p> 1555d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * An "identifier" is a sequence of characters that do not have the Unicode Pattern_Syntax or Pattern_White_Space 1565d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * properties. 1575d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <p> 1585d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * The difference between 'in' and 'within' is that 'in' only includes integers in the specified range, while 'within' 1595d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * includes all values. Using 'within' with a range_list consisting entirely of values is the same as using 'in' (it's 1605d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * not an error). 1615d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * </p> 1625d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * 1635d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @stable ICU 3.8 1645d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 1655d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamathpublic class PluralRules implements Serializable { 1665d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 1678d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath // static final UnicodeSet ALLOWED_ID = new UnicodeSet("[a-z]").freeze(); 1685d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 1695d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath // TODO Remove RulesList by moving its API and fields into PluralRules. 1705d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 1715d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 1725d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 1735d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 1748d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 1755d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public static final String CATEGORY_SEPARATOR = "; "; 1765d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 1775d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 1785d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 1795d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 1808d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 1815d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public static final String KEYWORD_RULE_SEPARATOR = ": "; 1825d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 1835d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private static final long serialVersionUID = 1; 1845d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 1855d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private final RuleList rules; 1865d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private final transient Set<String> keywords; 1875d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 1885d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 1895d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Provides a factory for returning plural rules 1905d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * 1915d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 1928d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath * @deprecated This API is ICU internal only. 1935d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 1948d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 1955d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public static abstract class Factory { 1965d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 1975d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Provides access to the predefined <code>PluralRules</code> for a given locale and the plural type. 1985d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * 1995d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <p> 2005d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * ICU defines plural rules for many locales based on CLDR <i>Language Plural Rules</i>. For these predefined 2015d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * rules, see CLDR page at http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html 2025d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * 2035d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @param locale 2045d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * The locale for which a <code>PluralRules</code> object is returned. 2055d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @param type 2065d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * The plural type (e.g., cardinal or ordinal). 2075d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @return The predefined <code>PluralRules</code> object for this locale. If there's no predefined rules for 2085d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * this locale, the rules for the closest parent in the locale hierarchy that has one will be returned. 2095d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * The final fallback always returns the default rules. 2105d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 2118d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath * @deprecated This API is ICU internal only. 2125d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 2138d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 2148d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath public abstract PluralRules forLocale(Locale locale, PluralType type); 2155d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 2165d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 2175d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Utility for getting CARDINAL rules. 2185d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @param locale the locale 2195d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @return plural rules. 2205d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 2218d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath * @deprecated This API is ICU internal only. 2225d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 2238d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 2248d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath public final PluralRules forLocale(Locale locale) { 2255d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return forLocale(locale, PluralType.CARDINAL); 2265d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 2275d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 2285d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 2295d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Returns the locales for which there is plurals data. 2305d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * 2315d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 2328d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath * @deprecated This API is ICU internal only. 2338d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 2345d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public abstract ULocale[] getAvailableULocales(); 2358d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath */ 2365d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 2375d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 2385d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Returns the 'functionally equivalent' locale with respect to plural rules. Calling PluralRules.forLocale with 2395d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * the functionally equivalent locale, and with the provided locale, returns rules that behave the same. <br/> 2405d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * All locales with the same functionally equivalent locale have plural rules that behave the same. This is not 2415d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * exaustive; there may be other locales whose plural rules behave the same that do not have the same equivalent 2425d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * locale. 2435d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * 2445d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @param locale 2455d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * the locale to check 2465d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @param isAvailable 2475d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * if not null and of length > 0, this will hold 'true' at index 0 if locale is directly defined 2485d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * (without fallback) as having plural rules 2495d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @return the functionally-equivalent locale 2505d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 2518d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath * @deprecated This API is ICU internal only. 2528d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 2535d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public abstract ULocale getFunctionalEquivalent(ULocale locale, boolean[] isAvailable); 2548d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath */ 2555d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 2565d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 2575d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Returns the default factory. 2585d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 2598d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath * @deprecated This API is ICU internal only. 2605d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 2618d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 2625d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public static PluralRulesLoader getDefaultFactory() { 2635d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return PluralRulesLoader.loader; 2645d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 2655d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 2665d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 2675d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Returns whether or not there are overrides. 2685d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 2698d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath * @deprecated This API is ICU internal only. 2708d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 2715d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public abstract boolean hasOverride(ULocale locale); 2728d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath */ 2735d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 2745d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath // Standard keywords. 2755d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 2765d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 2775d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Common name for the 'zero' plural form. 2785d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @stable ICU 3.8 2795d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 2805d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public static final String KEYWORD_ZERO = "zero"; 2815d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 2825d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 2835d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Common name for the 'singular' plural form. 2845d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @stable ICU 3.8 2855d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 2865d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public static final String KEYWORD_ONE = "one"; 2875d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 2885d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 2895d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Common name for the 'dual' plural form. 2905d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @stable ICU 3.8 2915d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 2925d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public static final String KEYWORD_TWO = "two"; 2935d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 2945d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 2955d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Common name for the 'paucal' or other special plural form. 2965d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @stable ICU 3.8 2975d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 2985d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public static final String KEYWORD_FEW = "few"; 2995d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 3005d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 3015d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Common name for the arabic (11 to 99) plural form. 3025d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @stable ICU 3.8 3035d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 3045d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public static final String KEYWORD_MANY = "many"; 3055d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 3065d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 3075d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Common name for the default plural form. This name is returned 3085d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * for values to which no other form in the rule applies. It 3095d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * can additionally be assigned rules of its own. 3105d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @stable ICU 3.8 3115d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 3125d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public static final String KEYWORD_OTHER = "other"; 3135d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 3145d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 3155d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Value returned by {@link #getUniqueKeywordValue} when there is no 3165d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * unique value to return. 3175d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @stable ICU 4.8 3185d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 3195d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public static final double NO_UNIQUE_VALUE = -0.00123456777; 3205d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 3215d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 3225d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Type of plurals and PluralRules. 3235d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @stable ICU 50 3245d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 3255d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public enum PluralType { 3265d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 3275d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Plural rules for cardinal numbers: 1 file vs. 2 files. 3285d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @stable ICU 50 3295d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 3305d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath CARDINAL, 3315d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 3325d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Plural rules for ordinal numbers: 1st file, 2nd file, 3rd file, 4th file, etc. 3335d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @stable ICU 50 3345d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 3355d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath ORDINAL 3365d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath }; 3375d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 3385d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /* 3395d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * The default constraint that is always satisfied. 3405d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 3415d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private static final Constraint NO_CONSTRAINT = new Constraint() { 3425d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private static final long serialVersionUID = 9163464945387899416L; 3435d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 3445d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public boolean isFulfilled(FixedDecimal n) { 3455d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return true; 3465d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 3475d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 3485d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public boolean isLimited(SampleType sampleType) { 3495d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return false; 3505d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 3515d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 3525d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public String toString() { 3535d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return ""; 3545d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 3555d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath }; 3565d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 3575d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 3585d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * 3595d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 3605d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private static final Rule DEFAULT_RULE = new Rule("other", NO_CONSTRAINT, null, null); 3615d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 3625d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 3635d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Parses a plural rules description and returns a PluralRules. 3645d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @param description the rule description. 3655d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @throws ParseException if the description cannot be parsed. 3665d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * The exception index is typically not set, it will be -1. 3675d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @stable ICU 3.8 3685d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 3695d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public static PluralRules parseDescription(String description) 3705d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath throws ParseException { 3715d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 3725d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath description = description.trim(); 3735d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return description.length() == 0 ? DEFAULT : new PluralRules(parseRuleChain(description)); 3745d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 3755d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 3765d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 3775d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Creates a PluralRules from a description if it is parsable, 3785d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * otherwise returns null. 3795d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @param description the rule description. 3805d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @return the PluralRules 3815d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @stable ICU 3.8 3825d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 3835d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public static PluralRules createRules(String description) { 3845d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath try { 3855d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return parseDescription(description); 3865d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } catch(Exception e) { 3875d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return null; 3885d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 3895d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 3905d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 3915d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 3925d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * The default rules that accept any number and return 3935d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * {@link #KEYWORD_OTHER}. 3945d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @stable ICU 3.8 3955d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 3965d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public static final PluralRules DEFAULT = new PluralRules(new RuleList().addRule(DEFAULT_RULE)); 3975d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 3985d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private enum Operand { 3995d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath n, 4005d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath i, 4015d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath f, 4025d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath t, 4035d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath v, 4045d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath w, 4058d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath /* deprecated */ 4065d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath j; 4075d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 4085d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 4095d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 4105d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 4115d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 4125d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 4138d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 4145d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public static class FixedDecimal extends Number implements Comparable<FixedDecimal> { 4155d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private static final long serialVersionUID = -4756200506571685661L; 4165d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 4175d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 4185d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 4195d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 4208d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 4215d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public final double source; 4225d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 4235d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 4245d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 4255d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 4268d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 4275d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public final int visibleDecimalDigitCount; 4285d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 4295d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 4305d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 4315d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 4328d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 4335d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public final int visibleDecimalDigitCountWithoutTrailingZeros; 4345d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 4355d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 4365d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 4375d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 4388d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 4395d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public final long decimalDigits; 4405d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 4415d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 4425d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 4435d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 4448d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 4455d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public final long decimalDigitsWithoutTrailingZeros; 4465d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 4475d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 4485d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 4495d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 4508d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 4515d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public final long integerValue; 4525d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 4535d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 4545d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 4555d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 4568d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 4575d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public final boolean hasIntegerValue; 4585d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 4595d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 4605d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 4615d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 4628d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 4635d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public final boolean isNegative; 4645d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private final int baseFactor; 4655d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 4665d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 4675d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 4685d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 4695d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 4708d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 4715d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public double getSource() { 4725d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return source; 4735d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 4745d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 4755d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 4765d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 4775d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 4785d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 4798d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 4805d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public int getVisibleDecimalDigitCount() { 4815d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return visibleDecimalDigitCount; 4825d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 4835d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 4845d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 4855d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 4865d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 4875d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 4888d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 4895d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public int getVisibleDecimalDigitCountWithoutTrailingZeros() { 4905d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return visibleDecimalDigitCountWithoutTrailingZeros; 4915d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 4925d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 4935d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 4945d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 4955d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 4965d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 4978d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 4985d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public long getDecimalDigits() { 4995d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return decimalDigits; 5005d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 5015d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 5025d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 5035d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 5045d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 5055d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 5068d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 5075d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public long getDecimalDigitsWithoutTrailingZeros() { 5085d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return decimalDigitsWithoutTrailingZeros; 5095d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 5105d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 5115d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 5125d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 5135d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 5145d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 5158d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 5165d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public long getIntegerValue() { 5175d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return integerValue; 5185d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 5195d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 5205d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 5215d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 5225d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 5235d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 5248d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 5255d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public boolean isHasIntegerValue() { 5265d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return hasIntegerValue; 5275d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 5285d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 5295d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 5305d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 5315d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 5325d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 5338d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 5345d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public boolean isNegative() { 5355d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return isNegative; 5365d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 5375d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 5385d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 5395d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 5405d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 5415d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 5428d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 5435d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public int getBaseFactor() { 5445d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return baseFactor; 5455d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 5465d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 5478d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath static final long MAX = (long)1E18; 5488d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath 5495d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 5505d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 5515d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 5525d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @param n is the original number 5535d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @param v number of digits to the right of the decimal place. e.g 1.00 = 2 25. = 0 5545d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @param f Corresponds to f in the plural rules grammar. 5555d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * The digits to the right of the decimal place as an integer. e.g 1.10 = 10 5565d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 5578d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 5585d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public FixedDecimal(double n, int v, long f) { 5595d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath isNegative = n < 0; 5605d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath source = isNegative ? -n : n; 5615d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath visibleDecimalDigitCount = v; 5625d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath decimalDigits = f; 5638d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath integerValue = n > MAX 5648d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath ? MAX 5658d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath : (long)n; 5665d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath hasIntegerValue = source == integerValue; 5675d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath // check values. TODO make into unit test. 5685d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath // 5695d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath // long visiblePower = (int) Math.pow(10, v); 5705d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath // if (fractionalDigits > visiblePower) { 5715d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath // throw new IllegalArgumentException(); 5725d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath // } 5735d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath // double fraction = intValue + (fractionalDigits / (double) visiblePower); 5745d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath // if (fraction != source) { 5755d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath // double diff = Math.abs(fraction - source)/(Math.abs(fraction) + Math.abs(source)); 5765d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath // if (diff > 0.00000001d) { 5775d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath // throw new IllegalArgumentException(); 5785d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath // } 5795d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath // } 5805d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (f == 0) { 5815d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath decimalDigitsWithoutTrailingZeros = 0; 5825d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath visibleDecimalDigitCountWithoutTrailingZeros = 0; 5835d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } else { 5845d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath long fdwtz = f; 5855d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath int trimmedCount = v; 5865d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath while ((fdwtz%10) == 0) { 5875d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath fdwtz /= 10; 5885d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath --trimmedCount; 5895d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 5905d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath decimalDigitsWithoutTrailingZeros = fdwtz; 5915d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath visibleDecimalDigitCountWithoutTrailingZeros = trimmedCount; 5925d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 5935d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath baseFactor = (int) Math.pow(10, v); 5945d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 5955d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 5965d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 5975d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 5985d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 5995d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 6008d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 6015d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public FixedDecimal(double n, int v) { 6025d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath this(n,v,getFractionalDigits(n, v)); 6035d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 6045d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 6055d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private static int getFractionalDigits(double n, int v) { 6065d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (v == 0) { 6075d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return 0; 6085d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } else { 6098d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath if (n < 0) { 6108d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath n = -n; 6118d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath } 6125d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath int baseFactor = (int) Math.pow(10, v); 6135d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath long scaled = Math.round(n * baseFactor); 6145d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return (int) (scaled % baseFactor); 6155d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 6165d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 6175d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 6185d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 6195d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 6205d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 6215d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 6228d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 6235d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public FixedDecimal(double n) { 6245d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath this(n, decimals(n)); 6255d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 6265d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 6275d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 6285d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 6295d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 6305d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 6318d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 6325d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public FixedDecimal(long n) { 6335d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath this(n,0); 6345d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 6355d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 6368d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath private static final long MAX_INTEGER_PART = 1000000000; 6375d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 6388d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath * Return a guess as to the number of decimals that would be displayed. This is only a guess; callers should 6398d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath * always supply the decimals explicitly if possible. Currently, it is up to 6 decimals (without trailing zeros). 6408d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath * Returns 0 for infinities and nans. 6415d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 6425d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 6438d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath * 6445d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 6458d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 6465d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public static int decimals(double n) { 6475d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath // Ugly... 6488d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath if (Double.isInfinite(n) || Double.isNaN(n)) { 6498d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath return 0; 6508d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath } 6518d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath if (n < 0) { 6528d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath n = -n; 6538d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath } 6548d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath if (n < MAX_INTEGER_PART) { 6558d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath long temp = (long)(n * 1000000) % 1000000; // get 6 decimals 6568d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath for (int mask = 10, digits = 6; digits > 0; mask *= 10, --digits) { 6578d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath if ((temp % mask) != 0) { 6588d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath return digits; 6598d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath } 6608d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath } 6618d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath return 0; 6628d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath } else { 6638d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath String buf = String.format(Locale.ENGLISH, "%1.15e", n); 6648d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath int ePos = buf.lastIndexOf('e'); 6658d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath int expNumPos = ePos + 1; 6668d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath if (buf.charAt(expNumPos) == '+') { 6678d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath expNumPos++; 6688d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath } 6698d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath String exponentStr = buf.substring(expNumPos); 6708d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath int exponent = Integer.parseInt(exponentStr); 6718d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath int numFractionDigits = ePos - 2 - exponent; 6728d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath if (numFractionDigits < 0) { 6738d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath return 0; 6748d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath } 6758d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath for (int i=ePos-1; numFractionDigits > 0; --i) { 6768d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath if (buf.charAt(i) != '0') { 6778d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath break; 6788d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath } 6798d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath --numFractionDigits; 6808d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath } 6818d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath return numFractionDigits; 6828d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath } 6835d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 6845d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 6855d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 6865d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 6875d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 6885d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 6898d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 6905d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public FixedDecimal (String n) { 6915d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath // Ugly, but for samples we don't care. 6925d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath this(Double.parseDouble(n), getVisibleFractionCount(n)); 6935d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 6945d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 6955d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private static int getVisibleFractionCount(String value) { 6965d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath value = value.trim(); 6975d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath int decimalPos = value.indexOf('.') + 1; 6985d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (decimalPos == 0) { 6995d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return 0; 7005d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } else { 7015d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return value.length() - decimalPos; 7025d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 7035d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 7045d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 7055d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 7065d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 7075d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 7085d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 7098d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 7105d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public double get(Operand operand) { 7115d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath switch(operand) { 7125d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath default: return source; 7135d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath case i: return integerValue; 7145d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath case f: return decimalDigits; 7155d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath case t: return decimalDigitsWithoutTrailingZeros; 7165d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath case v: return visibleDecimalDigitCount; 7175d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath case w: return visibleDecimalDigitCountWithoutTrailingZeros; 7185d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 7195d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 7205d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 7215d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 7225d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 7235d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 7245d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 7258d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 7265d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public static Operand getOperand(String t) { 7275d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return Operand.valueOf(t); 7285d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 7295d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 7305d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 7315d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * We're not going to care about NaN. 7325d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 7335d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 7345d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 7358d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 7365d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public int compareTo(FixedDecimal other) { 7375d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (integerValue != other.integerValue) { 7385d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return integerValue < other.integerValue ? -1 : 1; 7395d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 7405d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (source != other.source) { 7415d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return source < other.source ? -1 : 1; 7425d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 7435d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (visibleDecimalDigitCount != other.visibleDecimalDigitCount) { 7445d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return visibleDecimalDigitCount < other.visibleDecimalDigitCount ? -1 : 1; 7455d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 7465d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath long diff = decimalDigits - other.decimalDigits; 7475d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (diff != 0) { 7485d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return diff < 0 ? -1 : 1; 7495d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 7505d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return 0; 7515d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 7525d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 7535d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 7545d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 7555d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 7565d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 7578d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 7585d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath @Override 7595d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public boolean equals(Object arg0) { 7605d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (arg0 == null) { 7615d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return false; 7625d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 7635d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (arg0 == this) { 7645d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return true; 7655d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 7665d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (!(arg0 instanceof FixedDecimal)) { 7675d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return false; 7685d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 7695d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath FixedDecimal other = (FixedDecimal)arg0; 7705d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return source == other.source && visibleDecimalDigitCount == other.visibleDecimalDigitCount && decimalDigits == other.decimalDigits; 7715d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 7725d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 7735d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 7745d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 7755d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 7765d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 7778d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 7785d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath @Override 7795d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public int hashCode() { 7805d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath // TODO Auto-generated method stub 7815d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return (int)(decimalDigits + 37 * (visibleDecimalDigitCount + (int)(37 * source))); 7825d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 7835d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 7845d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 7855d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 7865d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 7875d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 7888d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 7895d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath @Override 7905d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public String toString() { 7915d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return String.format("%." + visibleDecimalDigitCount + "f", source); 7925d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 7935d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 7945d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 7955d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 7965d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 7975d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 7988d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 7995d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public boolean hasIntegerValue() { 8005d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return hasIntegerValue; 8015d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 8025d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 8035d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 8045d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 8055d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 8065d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 8078d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 8085d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath @Override 8095d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public int intValue() { 8105d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath // TODO Auto-generated method stub 8115d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return (int)integerValue; 8125d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 8135d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 8145d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 8155d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 8165d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 8175d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 8188d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 8195d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath @Override 8205d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public long longValue() { 8215d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return integerValue; 8225d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 8235d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 8245d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 8255d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 8265d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 8275d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 8288d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 8295d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath @Override 8305d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public float floatValue() { 8315d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return (float) source; 8325d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 8335d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 8345d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 8355d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 8365d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 8375d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 8388d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 8395d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath @Override 8405d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public double doubleValue() { 8418d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath return isNegative ? -source : source; 8425d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 8435d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 8445d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 8455d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 8465d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 8475d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 8488d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 8495d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public long getShiftedValue() { 8505d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return integerValue * baseFactor + decimalDigits; 8515d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 8525d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 8535d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private void writeObject( 8545d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath ObjectOutputStream out) 8555d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath throws IOException { 8565d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath throw new NotSerializableException(); 8575d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 8585d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 8595d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private void readObject(ObjectInputStream in 8605d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath ) throws IOException, ClassNotFoundException { 8615d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath throw new NotSerializableException(); 8625d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 8635d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 8645d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 8655d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 8665d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Selection parameter for either integer-only or decimal-only. 8675d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 8685d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 8695d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 8708d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 8718d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath public enum SampleType { 8728d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath /** 8738d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath * @internal 8748d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath * @deprecated This API is ICU internal only. 8758d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath */ 8768d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 8778d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath INTEGER, 8788d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath /** 8798d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath * @internal 8808d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath * @deprecated This API is ICU internal only. 8818d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath */ 8828d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 8838d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath DECIMAL 8848d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath } 8855d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 8865d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 8875d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * A range of NumberInfo that includes all values with the same visibleFractionDigitCount. 8885d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 8895d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 8905d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 8918d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 8925d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public static class FixedDecimalRange { 8935d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 8945d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 8955d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 8965d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 8978d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 8985d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public final FixedDecimal start; 8995d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 9005d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 9015d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 9025d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 9038d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 9045d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public final FixedDecimal end; 9055d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 9065d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 9075d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 9085d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 9098d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 9105d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public FixedDecimalRange(FixedDecimal start, FixedDecimal end) { 9115d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (start.visibleDecimalDigitCount != end.visibleDecimalDigitCount) { 9125d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath throw new IllegalArgumentException("Ranges must have the same number of visible decimals: " + start + "~" + end); 9135d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 9145d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath this.start = start; 9155d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath this.end = end; 9165d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 9175d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 9185d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 9195d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 9205d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 9218d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 9225d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath @Override 9235d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public String toString() { 9245d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return start + (end == start ? "" : "~" + end); 9255d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 9265d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 9275d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 9285d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 9295d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * A list of NumberInfo that includes all values with the same visibleFractionDigitCount. 9305d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 9315d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 9325d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 9338d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 9345d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public static class FixedDecimalSamples { 9355d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 9365d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 9375d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 9385d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 9398d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 9405d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public final SampleType sampleType; 9415d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 9425d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 9435d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 9445d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 9458d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 9465d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public final Set<FixedDecimalRange> samples; 9475d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 9485d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 9495d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 9505d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 9518d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 9525d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public final boolean bounded; 9535d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 9545d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * The samples must be immutable. 9555d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @param sampleType 9565d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @param samples 9575d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 9585d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private FixedDecimalSamples(SampleType sampleType, Set<FixedDecimalRange> samples, boolean bounded) { 9595d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath super(); 9605d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath this.sampleType = sampleType; 9615d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath this.samples = samples; 9625d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath this.bounded = bounded; 9635d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 9645d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /* 9655d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Parse a list of the form described in CLDR. The source must be trimmed. 9665d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 9675d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath static FixedDecimalSamples parse(String source) { 9685d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath SampleType sampleType2; 9695d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath boolean bounded2 = true; 9705d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath boolean haveBound = false; 9715d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath Set<FixedDecimalRange> samples2 = new LinkedHashSet<FixedDecimalRange>(); 9725d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 9735d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (source.startsWith("integer")) { 9745d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath sampleType2 = SampleType.INTEGER; 9755d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } else if (source.startsWith("decimal")) { 9765d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath sampleType2 = SampleType.DECIMAL; 9775d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } else { 9785d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath throw new IllegalArgumentException("Samples must start with 'integer' or 'decimal'"); 9795d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 9805d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath source = source.substring(7).trim(); // remove both 9815d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 9825d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath for (String range : COMMA_SEPARATED.split(source)) { 9835d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (range.equals("…") || range.equals("...")) { 9845d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath bounded2 = false; 9855d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath haveBound = true; 9865d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath continue; 9875d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 9885d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (haveBound) { 9895d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath throw new IllegalArgumentException("Can only have … at the end of samples: " + range); 9905d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 9915d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath String[] rangeParts = TILDE_SEPARATED.split(range); 9925d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath switch (rangeParts.length) { 9935d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath case 1: 9945d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath FixedDecimal sample = new FixedDecimal(rangeParts[0]); 9955d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath checkDecimal(sampleType2, sample); 9965d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath samples2.add(new FixedDecimalRange(sample, sample)); 9975d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath break; 9985d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath case 2: 9995d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath FixedDecimal start = new FixedDecimal(rangeParts[0]); 10005d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath FixedDecimal end = new FixedDecimal(rangeParts[1]); 10015d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath checkDecimal(sampleType2, start); 10025d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath checkDecimal(sampleType2, end); 10035d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath samples2.add(new FixedDecimalRange(start, end)); 10045d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath break; 10055d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath default: throw new IllegalArgumentException("Ill-formed number range: " + range); 10065d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 10075d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 10085d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return new FixedDecimalSamples(sampleType2, Collections.unmodifiableSet(samples2), bounded2); 10095d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 10105d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 10115d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private static void checkDecimal(SampleType sampleType2, FixedDecimal sample) { 10125d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if ((sampleType2 == SampleType.INTEGER) != (sample.getVisibleDecimalDigitCount() == 0)) { 10135d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath throw new IllegalArgumentException("Ill-formed number range: " + sample); 10145d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 10155d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 10165d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 10175d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 10185d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 10195d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 10205d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 10218d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 10225d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public Set<Double> addSamples(Set<Double> result) { 10235d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath for (FixedDecimalRange item : samples) { 10245d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath // we have to convert to longs so we don't get strange double issues 10255d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath long startDouble = item.start.getShiftedValue(); 10265d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath long endDouble = item.end.getShiftedValue(); 10275d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 10285d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath for (long d = startDouble; d <= endDouble; d += 1) { 10295d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath result.add(d/(double)item.start.baseFactor); 10305d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 10315d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 10325d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return result; 10335d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 10345d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 10355d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 10365d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 10375d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 10385d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 10398d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 10405d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath @Override 10415d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public String toString() { 10425d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath StringBuilder b = new StringBuilder("@").append(sampleType.toString().toLowerCase(Locale.ENGLISH)); 10435d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath boolean first = true; 10445d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath for (FixedDecimalRange item : samples) { 10455d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (first) { 10465d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath first = false; 10475d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } else { 10485d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath b.append(","); 10495d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 10505d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath b.append(' ').append(item); 10515d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 10525d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (!bounded) { 10535d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath b.append(", …"); 10545d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 10555d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return b.toString(); 10565d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 10575d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 10585d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 10595d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 10605d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 10615d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 10628d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 10635d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public Set<FixedDecimalRange> getSamples() { 10645d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return samples; 10655d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 10665d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 10675d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 10685d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 10695d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 10705d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 10718d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 10725d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public void getStartEndSamples(Set<FixedDecimal> target) { 10735d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath for (FixedDecimalRange item : samples) { 10745d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath target.add(item.start); 10755d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath target.add(item.end); 10765d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 10775d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 10785d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 10795d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 10805d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /* 10815d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * A constraint on a number. 10825d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 10835d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private interface Constraint extends Serializable { 10845d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /* 10855d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Returns true if the number fulfills the constraint. 10865d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @param n the number to test, >= 0. 10875d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 10885d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath boolean isFulfilled(FixedDecimal n); 10895d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 10905d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /* 10915d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Returns false if an unlimited number of values fulfills the 10925d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * constraint. 10935d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 10945d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath boolean isLimited(SampleType sampleType); 10955d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 10965d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 10978d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath private static final boolean isBreakAndIgnore(char c) { 10988d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath return c <= 0x20 && (c == 0x20 || c == 9 || c == 0xa || c == 0xc || c == 0xd); 10998d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath } 11008d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath private static final boolean isBreakAndKeep(char c) { 11018d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath return c <= '=' && c >= '!' && (c == '!' || c == '%' || c == ',' || c == '.' || c == '='); 11028d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath } 11035d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath static class SimpleTokenizer { 11048d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath // static final UnicodeSet BREAK_AND_IGNORE = new UnicodeSet(0x09, 0x0a, 0x0c, 0x0d, 0x20, 0x20).freeze(); 11058d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath // static final UnicodeSet BREAK_AND_KEEP = new UnicodeSet('!', '!', '%', '%', ',', ',', '.', '.', '=', '=').freeze(); 11065d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath static String[] split(String source) { 11075d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath int last = -1; 11085d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath List<String> result = new ArrayList<String>(); 11095d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath for (int i = 0; i < source.length(); ++i) { 11105d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath char ch = source.charAt(i); 11118d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath if (isBreakAndIgnore(ch) /* BREAK_AND_IGNORE.contains(ch) */) { 11125d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (last >= 0) { 11135d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath result.add(source.substring(last,i)); 11145d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath last = -1; 11155d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 11168d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath } else if (isBreakAndKeep(ch) /* BREAK_AND_KEEP.contains(ch) */) { 11175d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (last >= 0) { 11185d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath result.add(source.substring(last,i)); 11195d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 11205d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath result.add(source.substring(i,i+1)); 11215d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath last = -1; 11225d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } else if (last < 0) { 11235d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath last = i; 11245d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 11255d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 11265d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (last >= 0) { 11275d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath result.add(source.substring(last)); 11285d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 11295d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return result.toArray(new String[result.size()]); 11305d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 11315d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 11325d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 11335d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /* 11345d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * syntax: 11355d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * condition : or_condition 11365d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * and_condition 11375d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * or_condition : and_condition 'or' condition 11385d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * and_condition : relation 11395d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * relation 'and' relation 11405d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * relation : in_relation 11415d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * within_relation 11425d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * in_relation : not? expr not? in not? range 11435d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * within_relation : not? expr not? 'within' not? range 11445d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * not : 'not' 11455d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * '!' 11465d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * expr : 'n' 11475d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * 'n' mod value 11485d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * mod : 'mod' 11495d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * '%' 11505d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * in : 'in' 11515d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * 'is' 11525d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * '=' 11535d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * '≠' 11545d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * value : digit+ 11555d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * digit : 0|1|2|3|4|5|6|7|8|9 11565d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * range : value'..'value 11575d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 11585d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private static Constraint parseConstraint(String description) 11595d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath throws ParseException { 11605d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 11615d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath Constraint result = null; 11625d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath String[] or_together = OR_SEPARATED.split(description); 11635d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath for (int i = 0; i < or_together.length; ++i) { 11645d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath Constraint andConstraint = null; 11655d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath String[] and_together = AND_SEPARATED.split(or_together[i]); 11665d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath for (int j = 0; j < and_together.length; ++j) { 11675d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath Constraint newConstraint = NO_CONSTRAINT; 11685d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 11695d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath String condition = and_together[j].trim(); 11705d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath String[] tokens = SimpleTokenizer.split(condition); 11715d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 11725d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath int mod = 0; 11735d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath boolean inRange = true; 11745d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath boolean integersOnly = true; 11755d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath double lowBound = Long.MAX_VALUE; 11765d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath double highBound = Long.MIN_VALUE; 11775d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath long[] vals = null; 11785d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 11795d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath int x = 0; 11805d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath String t = tokens[x++]; 11815d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath boolean hackForCompatibility = false; 11825d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath Operand operand; 11835d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath try { 11845d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath operand = FixedDecimal.getOperand(t); 11855d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } catch (Exception e) { 11865d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath throw unexpected(t, condition); 11875d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 11885d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (x < tokens.length) { 11895d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath t = tokens[x++]; 11905d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if ("mod".equals(t) || "%".equals(t)) { 11915d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath mod = Integer.parseInt(tokens[x++]); 11925d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath t = nextToken(tokens, x++, condition); 11935d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 11945d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if ("not".equals(t)) { 11955d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath inRange = !inRange; 11965d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath t = nextToken(tokens, x++, condition); 11975d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if ("=".equals(t)) { 11985d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath throw unexpected(t, condition); 11995d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 12005d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } else if ("!".equals(t)) { 12015d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath inRange = !inRange; 12025d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath t = nextToken(tokens, x++, condition); 12035d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (!"=".equals(t)) { 12045d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath throw unexpected(t, condition); 12055d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 12065d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 12075d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if ("is".equals(t) || "in".equals(t) || "=".equals(t)) { 12085d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath hackForCompatibility = "is".equals(t); 12095d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (hackForCompatibility && !inRange) { 12105d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath throw unexpected(t, condition); 12115d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 12125d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath t = nextToken(tokens, x++, condition); 12135d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } else if ("within".equals(t)) { 12145d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath integersOnly = false; 12155d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath t = nextToken(tokens, x++, condition); 12165d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } else { 12175d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath throw unexpected(t, condition); 12185d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 12195d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if ("not".equals(t)) { 12205d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (!hackForCompatibility && !inRange) { 12215d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath throw unexpected(t, condition); 12225d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 12235d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath inRange = !inRange; 12245d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath t = nextToken(tokens, x++, condition); 12255d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 12265d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 12275d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath List<Long> valueList = new ArrayList<Long>(); 12285d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 12295d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath // the token t is always one item ahead 12305d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath while (true) { 12315d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath long low = Long.parseLong(t); 12325d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath long high = low; 12335d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (x < tokens.length) { 12345d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath t = nextToken(tokens, x++, condition); 12355d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (t.equals(".")) { 12365d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath t = nextToken(tokens, x++, condition); 12375d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (!t.equals(".")) { 12385d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath throw unexpected(t, condition); 12395d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 12405d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath t = nextToken(tokens, x++, condition); 12415d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath high = Long.parseLong(t); 12425d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (x < tokens.length) { 12435d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath t = nextToken(tokens, x++, condition); 12445d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (!t.equals(",")) { // adjacent number: 1 2 12455d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath // no separator, fail 12465d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath throw unexpected(t, condition); 12475d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 12485d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 12495d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } else if (!t.equals(",")) { // adjacent number: 1 2 12505d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath // no separator, fail 12515d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath throw unexpected(t, condition); 12525d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 12535d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 12545d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath // at this point, either we are out of tokens, or t is ',' 12555d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (low > high) { 12565d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath throw unexpected(low + "~" + high, condition); 12575d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } else if (mod != 0 && high >= mod) { 12585d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath throw unexpected(high + ">mod=" + mod, condition); 12595d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 12605d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath valueList.add(low); 12615d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath valueList.add(high); 12625d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath lowBound = Math.min(lowBound, low); 12635d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath highBound = Math.max(highBound, high); 12645d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (x >= tokens.length) { 12655d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath break; 12665d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 12675d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath t = nextToken(tokens, x++, condition); 12685d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 12695d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 12705d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (t.equals(",")) { 12715d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath throw unexpected(t, condition); 12725d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 12735d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 12745d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (valueList.size() == 2) { 12755d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath vals = null; 12765d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } else { 12775d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath vals = new long[valueList.size()]; 12785d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath for (int k = 0; k < vals.length; ++k) { 12795d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath vals[k] = valueList.get(k); 12805d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 12815d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 12825d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 12835d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath // Hack to exclude "is not 1,2" 12845d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (lowBound != highBound && hackForCompatibility && !inRange) { 12855d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath throw unexpected("is not <range>", condition); 12865d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 12875d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 12885d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath newConstraint = 12895d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath new RangeConstraint(mod, inRange, operand, integersOnly, lowBound, highBound, vals); 12905d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 12915d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 12925d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (andConstraint == null) { 12935d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath andConstraint = newConstraint; 12945d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } else { 12955d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath andConstraint = new AndConstraint(andConstraint, 12965d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath newConstraint); 12975d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 12985d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 12995d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 13005d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (result == null) { 13015d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath result = andConstraint; 13025d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } else { 13035d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath result = new OrConstraint(result, andConstraint); 13045d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 13055d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 13065d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return result; 13075d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 13085d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 13095d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath static final Pattern AT_SEPARATED = Pattern.compile("\\s*\\Q\\E@\\s*"); 13105d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath static final Pattern OR_SEPARATED = Pattern.compile("\\s*or\\s*"); 13115d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath static final Pattern AND_SEPARATED = Pattern.compile("\\s*and\\s*"); 13125d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath static final Pattern COMMA_SEPARATED = Pattern.compile("\\s*,\\s*"); 13135d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath static final Pattern DOTDOT_SEPARATED = Pattern.compile("\\s*\\Q..\\E\\s*"); 13145d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath static final Pattern TILDE_SEPARATED = Pattern.compile("\\s*~\\s*"); 13155d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath static final Pattern SEMI_SEPARATED = Pattern.compile("\\s*;\\s*"); 13165d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 13175d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 13185d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /* Returns a parse exception wrapping the token and context strings. */ 13195d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private static ParseException unexpected(String token, String context) { 13205d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return new ParseException("unexpected token '" + token + 13215d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath "' in '" + context + "'", -1); 13225d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 13235d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 13245d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /* 13255d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Returns the token at x if available, else throws a parse exception. 13265d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 13275d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private static String nextToken(String[] tokens, int x, String context) 13285d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath throws ParseException { 13295d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (x < tokens.length) { 13305d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return tokens[x]; 13315d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 13325d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath throw new ParseException("missing token at end of '" + context + "'", -1); 13335d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 13345d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 13355d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /* 13365d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Syntax: 13375d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * rule : keyword ':' condition 13385d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * keyword: <identifier> 13395d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 13405d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private static Rule parseRule(String description) throws ParseException { 13415d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (description.length() == 0) { 13425d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return DEFAULT_RULE; 13435d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 13445d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 13455d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath description = description.toLowerCase(Locale.ENGLISH); 13465d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 13475d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath int x = description.indexOf(':'); 13485d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (x == -1) { 13495d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath throw new ParseException("missing ':' in rule description '" + 13505d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath description + "'", 0); 13515d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 13525d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 13535d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath String keyword = description.substring(0, x).trim(); 13545d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (!isValidKeyword(keyword)) { 13555d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath throw new ParseException("keyword '" + keyword + 13565d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath " is not valid", 0); 13575d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 13585d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 13595d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath description = description.substring(x+1).trim(); 13605d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath String[] constraintOrSamples = AT_SEPARATED.split(description); 13615d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath boolean sampleFailure = false; 13625d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath FixedDecimalSamples integerSamples = null, decimalSamples = null; 13635d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath switch (constraintOrSamples.length) { 13645d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath case 1: break; 13655d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath case 2: 13665d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath integerSamples = FixedDecimalSamples.parse(constraintOrSamples[1]); 13675d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (integerSamples.sampleType == SampleType.DECIMAL) { 13685d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath decimalSamples = integerSamples; 13695d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath integerSamples = null; 13705d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 13715d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath break; 13725d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath case 3: 13735d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath integerSamples = FixedDecimalSamples.parse(constraintOrSamples[1]); 13745d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath decimalSamples = FixedDecimalSamples.parse(constraintOrSamples[2]); 13755d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (integerSamples.sampleType != SampleType.INTEGER || decimalSamples.sampleType != SampleType.DECIMAL) { 13765d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath throw new IllegalArgumentException("Must have @integer then @decimal in " + description); 13775d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 13785d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath break; 13795d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath default: 13805d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath throw new IllegalArgumentException("Too many samples in " + description); 13815d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 13825d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (sampleFailure) { 13835d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath throw new IllegalArgumentException("Ill-formed samples—'@' characters."); 13845d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 13855d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 13865d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath // 'other' is special, and must have no rules; all other keywords must have rules. 13875d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath boolean isOther = keyword.equals("other"); 13885d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (isOther != (constraintOrSamples[0].length() == 0)) { 13895d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath throw new IllegalArgumentException("The keyword 'other' must have no constraints, just samples."); 13905d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 13915d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 13925d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath Constraint constraint; 13935d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (isOther) { 13945d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath constraint = NO_CONSTRAINT; 13955d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } else { 13965d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath constraint = parseConstraint(constraintOrSamples[0]); 13975d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 13985d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return new Rule(keyword, constraint, integerSamples, decimalSamples); 13995d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 14005d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 14015d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 14025d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /* 14035d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Syntax: 14045d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * rules : rule 14055d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * rule ';' rules 14065d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 14075d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private static RuleList parseRuleChain(String description) 14085d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath throws ParseException { 14095d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath RuleList result = new RuleList(); 14105d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath // remove trailing ; 14115d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (description.endsWith(";")) { 14125d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath description = description.substring(0,description.length()-1); 14135d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 14145d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath String[] rules = SEMI_SEPARATED.split(description); 14155d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath for (int i = 0; i < rules.length; ++i) { 14165d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath Rule rule = parseRule(rules[i].trim()); 14175d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath result.hasExplicitBoundingInfo |= rule.integerSamples != null || rule.decimalSamples != null; 14185d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath result.addRule(rule); 14195d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 14205d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return result.finish(); 14215d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 14225d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 14235d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /* 14245d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * An implementation of Constraint representing a modulus, 14255d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * a range of values, and include/exclude. Provides lots of 14265d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * convenience factory methods. 14275d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 14285d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private static class RangeConstraint implements Constraint, Serializable { 14295d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private static final long serialVersionUID = 1; 14305d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 14315d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private final int mod; 14325d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private final boolean inRange; 14335d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private final boolean integersOnly; 14345d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private final double lowerBound; 14355d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private final double upperBound; 14365d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private final long[] range_list; 14375d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private final Operand operand; 14385d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 14395d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath RangeConstraint(int mod, boolean inRange, Operand operand, boolean integersOnly, 14405d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath double lowBound, double highBound, long[] vals) { 14415d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath this.mod = mod; 14425d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath this.inRange = inRange; 14435d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath this.integersOnly = integersOnly; 14445d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath this.lowerBound = lowBound; 14455d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath this.upperBound = highBound; 14465d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath this.range_list = vals; 14475d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath this.operand = operand; 14485d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 14495d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 14505d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public boolean isFulfilled(FixedDecimal number) { 14515d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath double n = number.get(operand); 14525d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if ((integersOnly && (n - (long)n) != 0.0 14535d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath || operand == Operand.j && number.visibleDecimalDigitCount != 0)) { 14545d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return !inRange; 14555d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 14565d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (mod != 0) { 14575d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath n = n % mod; // java % handles double numerator the way we want 14585d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 14595d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath boolean test = n >= lowerBound && n <= upperBound; 14605d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (test && range_list != null) { 14615d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath test = false; 14625d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath for (int i = 0; !test && i < range_list.length; i += 2) { 14635d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath test = n >= range_list[i] && n <= range_list[i+1]; 14645d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 14655d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 14665d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return inRange == test; 14675d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 14685d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 14695d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public boolean isLimited(SampleType sampleType) { 14705d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath boolean valueIsZero = lowerBound == upperBound && lowerBound == 0d; 14715d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath boolean hasDecimals = 14725d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath (operand == Operand.v || operand == Operand.w || operand == Operand.f || operand == Operand.t) 14735d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath && inRange != valueIsZero; // either NOT f = zero or f = non-zero 14745d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath switch (sampleType) { 14755d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath case INTEGER: 14765d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return hasDecimals // will be empty 14775d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath || (operand == Operand.n || operand == Operand.i || operand == Operand.j) 14785d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath && mod == 0 14795d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath && inRange; 14805d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 14815d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath case DECIMAL: 14825d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return (!hasDecimals || operand == Operand.n || operand == Operand.j) 14835d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath && (integersOnly || lowerBound == upperBound) 14845d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath && mod == 0 14855d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath && inRange; 14865d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 14875d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return false; 14885d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 14895d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 14905d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public String toString() { 14915d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath StringBuilder result = new StringBuilder(); 14925d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath result.append(operand); 14935d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (mod != 0) { 14945d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath result.append(" % ").append(mod); 14955d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 14965d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath boolean isList = lowerBound != upperBound; 14975d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath result.append( 14985d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath !isList ? (inRange ? " = " : " != ") 14995d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath : integersOnly ? (inRange ? " = " : " != ") 15005d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath : (inRange ? " within " : " not within ") 15015d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath ); 15025d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (range_list != null) { 15035d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath for (int i = 0; i < range_list.length; i += 2) { 15045d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath addRange(result, range_list[i], range_list[i+1], i != 0); 15055d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 15065d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } else { 15075d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath addRange(result, lowerBound, upperBound, false); 15085d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 15095d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return result.toString(); 15105d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 15115d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 15125d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 15135d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private static void addRange(StringBuilder result, double lb, double ub, boolean addSeparator) { 15145d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (addSeparator) { 15155d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath result.append(","); 15165d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 15175d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (lb == ub) { 15185d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath result.append(format(lb)); 15195d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } else { 15205d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath result.append(format(lb) + ".." + format(ub)); 15215d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 15225d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 15235d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 15245d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private static String format(double lb) { 15255d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath long lbi = (long) lb; 15265d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return lb == lbi ? String.valueOf(lbi) : String.valueOf(lb); 15275d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 15285d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 15295d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /* Convenience base class for and/or constraints. */ 15305d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private static abstract class BinaryConstraint implements Constraint, 15315d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath Serializable { 15325d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private static final long serialVersionUID = 1; 15335d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath protected final Constraint a; 15345d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath protected final Constraint b; 15355d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 15365d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath protected BinaryConstraint(Constraint a, Constraint b) { 15375d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath this.a = a; 15385d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath this.b = b; 15395d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 15405d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 15415d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 15425d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /* A constraint representing the logical and of two constraints. */ 15435d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private static class AndConstraint extends BinaryConstraint { 15445d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private static final long serialVersionUID = 7766999779862263523L; 15455d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 15465d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath AndConstraint(Constraint a, Constraint b) { 15475d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath super(a, b); 15485d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 15495d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 15505d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public boolean isFulfilled(FixedDecimal n) { 15515d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return a.isFulfilled(n) 15525d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath && b.isFulfilled(n); 15535d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 15545d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 15555d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public boolean isLimited(SampleType sampleType) { 15565d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath // we ignore the case where both a and b are unlimited but no values 15575d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath // satisfy both-- we still consider this 'unlimited' 15585d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return a.isLimited(sampleType) 15595d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath || b.isLimited(sampleType); 15605d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 15615d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 15625d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public String toString() { 15635d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return a.toString() + " and " + b.toString(); 15645d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 15655d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 15665d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 15675d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /* A constraint representing the logical or of two constraints. */ 15685d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private static class OrConstraint extends BinaryConstraint { 15695d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private static final long serialVersionUID = 1405488568664762222L; 15705d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 15715d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath OrConstraint(Constraint a, Constraint b) { 15725d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath super(a, b); 15735d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 15745d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 15755d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public boolean isFulfilled(FixedDecimal n) { 15765d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return a.isFulfilled(n) 15775d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath || b.isFulfilled(n); 15785d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 15795d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 15805d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public boolean isLimited(SampleType sampleType) { 15815d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return a.isLimited(sampleType) 15825d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath && b.isLimited(sampleType); 15835d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 15845d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 15855d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public String toString() { 15865d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return a.toString() + " or " + b.toString(); 15875d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 15885d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 15895d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 15905d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /* 15915d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Implementation of Rule that uses a constraint. 15925d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Provides 'and' and 'or' to combine constraints. Immutable. 15935d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 15945d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private static class Rule implements Serializable { 15955d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private static final long serialVersionUID = 1; 15965d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private final String keyword; 15975d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private final Constraint constraint; 15985d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private final FixedDecimalSamples integerSamples; 15995d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private final FixedDecimalSamples decimalSamples; 16005d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 16015d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public Rule(String keyword, Constraint constraint, FixedDecimalSamples integerSamples, FixedDecimalSamples decimalSamples) { 16025d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath this.keyword = keyword; 16035d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath this.constraint = constraint; 16045d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath this.integerSamples = integerSamples; 16055d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath this.decimalSamples = decimalSamples; 16065d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 16075d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 16085d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath @SuppressWarnings("unused") 16095d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public Rule and(Constraint c) { 16105d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return new Rule(keyword, new AndConstraint(constraint, c), integerSamples, decimalSamples); 16115d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 16125d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 16135d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath @SuppressWarnings("unused") 16145d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public Rule or(Constraint c) { 16155d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return new Rule(keyword, new OrConstraint(constraint, c), integerSamples, decimalSamples); 16165d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 16175d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 16185d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public String getKeyword() { 16195d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return keyword; 16205d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 16215d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 16225d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public boolean appliesTo(FixedDecimal n) { 16235d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return constraint.isFulfilled(n); 16245d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 16255d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 16265d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public boolean isLimited(SampleType sampleType) { 16275d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return constraint.isLimited(sampleType); 16285d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 16295d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 16305d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public String toString() { 16315d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return keyword + ": " + constraint.toString() 16325d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath + (integerSamples == null ? "" : " " + integerSamples.toString()) 16335d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath + (decimalSamples == null ? "" : " " + decimalSamples.toString()); 16345d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 16355d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 16365d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 16375d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 16385d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 16395d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 16408d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 16415d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath @Override 16425d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public int hashCode() { 16435d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return keyword.hashCode() ^ constraint.hashCode(); 16445d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 16455d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 16465d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public String getConstraint() { 16475d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return constraint.toString(); 16485d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 16495d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 16505d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 16515d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private static class RuleList implements Serializable { 16525d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private boolean hasExplicitBoundingInfo = false; 16535d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private static final long serialVersionUID = 1; 16545d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private final List<Rule> rules = new ArrayList<Rule>(); 16555d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 16565d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public RuleList addRule(Rule nextRule) { 16575d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath String keyword = nextRule.getKeyword(); 16585d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath for (Rule rule : rules) { 16595d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (keyword.equals(rule.getKeyword())) { 16605d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath throw new IllegalArgumentException("Duplicate keyword: " + keyword); 16615d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 16625d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 16635d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath rules.add(nextRule); 16645d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return this; 16655d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 16665d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 16675d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public RuleList finish() throws ParseException { 16685d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath // make sure that 'other' is present, and at the end. 16695d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath Rule otherRule = null; 16705d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath for (Iterator<Rule> it = rules.iterator(); it.hasNext();) { 16715d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath Rule rule = it.next(); 16725d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if ("other".equals(rule.getKeyword())) { 16735d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath otherRule = rule; 16745d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath it.remove(); 16755d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 16765d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 16775d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (otherRule == null) { 16785d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath otherRule = parseRule("other:"); // make sure we have always have an 'other' a rule 16795d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 16805d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath rules.add(otherRule); 16815d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return this; 16825d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 16835d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 16845d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private Rule selectRule(FixedDecimal n) { 16855d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath for (Rule rule : rules) { 16865d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (rule.appliesTo(n)) { 16875d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return rule; 16885d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 16895d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 16905d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return null; 16915d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 16925d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 16935d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public String select(FixedDecimal n) { 16948d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath if (Double.isInfinite(n.source) || Double.isNaN(n.source)) { 16958d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath return KEYWORD_OTHER; 16968d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath } 16975d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath Rule r = selectRule(n); 16985d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return r.getKeyword(); 16995d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 17005d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 17015d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public Set<String> getKeywords() { 17025d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath Set<String> result = new LinkedHashSet<String>(); 17035d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath for (Rule rule : rules) { 17045d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath result.add(rule.getKeyword()); 17055d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 17065d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath // since we have explict 'other', we don't need this. 17075d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath //result.add(KEYWORD_OTHER); 17085d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return result; 17095d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 17105d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 17115d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public boolean isLimited(String keyword, SampleType sampleType) { 17125d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (hasExplicitBoundingInfo) { 17135d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath FixedDecimalSamples mySamples = getDecimalSamples(keyword, sampleType); 17145d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return mySamples == null ? true : mySamples.bounded; 17155d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 17165d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 17175d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return computeLimited(keyword, sampleType); 17185d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 17195d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 17205d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public boolean computeLimited(String keyword, SampleType sampleType) { 17215d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath // if all rules with this keyword are limited, it's limited, 17225d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath // and if there's no rule with this keyword, it's unlimited 17235d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath boolean result = false; 17245d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath for (Rule rule : rules) { 17255d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (keyword.equals(rule.getKeyword())) { 17265d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (!rule.isLimited(sampleType)) { 17275d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return false; 17285d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 17295d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath result = true; 17305d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 17315d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 17325d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return result; 17335d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 17345d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 17355d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public String toString() { 17365d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath StringBuilder builder = new StringBuilder(); 17375d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath for (Rule rule : rules) { 17385d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (builder.length() != 0) { 17395d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath builder.append(CATEGORY_SEPARATOR); 17405d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 17415d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath builder.append(rule); 17425d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 17435d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return builder.toString(); 17445d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 17455d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 17465d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public String getRules(String keyword) { 17475d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath for (Rule rule : rules) { 17485d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (rule.getKeyword().equals(keyword)) { 17495d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return rule.getConstraint(); 17505d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 17515d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 17525d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return null; 17535d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 17545d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 17555d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public boolean select(FixedDecimal sample, String keyword) { 17565d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath for (Rule rule : rules) { 17575d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (rule.getKeyword().equals(keyword) && rule.appliesTo(sample)) { 17585d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return true; 17595d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 17605d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 17615d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return false; 17625d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 17635d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 17645d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public FixedDecimalSamples getDecimalSamples(String keyword, SampleType sampleType) { 17655d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath for (Rule rule : rules) { 17665d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (rule.getKeyword().equals(keyword)) { 17675d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return sampleType == SampleType.INTEGER ? rule.integerSamples : rule.decimalSamples; 17685d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 17695d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 17705d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return null; 17715d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 17725d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 17735d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 17745d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 17755d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 17765d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 17775d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 17788d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 17795d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public enum StandardPluralCategories { 17808d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath /** 17818d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath * @internal 17828d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath * @deprecated This API is ICU internal only. 17838d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath */ 17848d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 17855d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath zero, 17868d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath /** 17878d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath * @internal 17888d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath * @deprecated This API is ICU internal only. 17898d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath */ 17908d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 17915d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath one, 17928d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath /** 17938d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath * @internal 17948d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath * @deprecated This API is ICU internal only. 17958d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath */ 17968d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 17975d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath two, 17988d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath /** 17998d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath * @internal 18008d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath * @deprecated This API is ICU internal only. 18018d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath */ 18028d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 18035d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath few, 18048d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath /** 18058d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath * @internal 18068d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath * @deprecated This API is ICU internal only. 18078d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath */ 18088d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 18095d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath many, 18108d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath /** 18118d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath * @internal 18128d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath * @deprecated This API is ICU internal only. 18138d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath */ 18148d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 18155d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath other; 18165d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath static StandardPluralCategories forString(String s) { 18175d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath StandardPluralCategories a; 18185d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath try { 18195d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath a = valueOf(s); 18205d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } catch (Exception e) { 18215d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return null; 18225d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 18235d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return a; 18245d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 18255d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 18265d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 18275d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath @SuppressWarnings("unused") 18285d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private boolean addConditional(Set<FixedDecimal> toAddTo, Set<FixedDecimal> others, double trial) { 18295d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath boolean added; 18305d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath FixedDecimal toAdd = new FixedDecimal(trial); 18315d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (!toAddTo.contains(toAdd) && !others.contains(toAdd)) { 18325d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath others.add(toAdd); 18335d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath added = true; 18345d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } else { 18355d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath added = false; 18365d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 18375d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return added; 18385d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 18395d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 18405d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 18415d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 18425d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath // ------------------------------------------------------------------------- 18435d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath // Static class methods. 18445d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath // ------------------------------------------------------------------------- 18455d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 18465d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 18475d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Provides access to the predefined cardinal-number <code>PluralRules</code> for a given 18485d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * locale. 18495d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Same as forLocale(locale, PluralType.CARDINAL). 18505d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * 18515d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <p>ICU defines plural rules for many locales based on CLDR <i>Language Plural Rules</i>. 18525d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * For these predefined rules, see CLDR page at 18535d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html 18545d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * 18555d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @param locale The locale for which a <code>PluralRules</code> object is 18565d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * returned. 18575d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @return The predefined <code>PluralRules</code> object for this locale. 18585d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * If there's no predefined rules for this locale, the rules 18595d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * for the closest parent in the locale hierarchy that has one will 18605d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * be returned. The final fallback always returns the default 18615d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * rules. 18625d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @stable ICU 3.8 18635d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 18648d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath public static PluralRules forLocale(Locale locale) { 18658d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath return forLocale(locale, PluralType.CARDINAL); 18665d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 18675d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 18685d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 18695d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Provides access to the predefined <code>PluralRules</code> for a given 18705d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * locale and the plural type. 18715d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * 18725d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <p>ICU defines plural rules for many locales based on CLDR <i>Language Plural Rules</i>. 18735d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * For these predefined rules, see CLDR page at 18745d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html 18755d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * 18765d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @param locale The locale for which a <code>PluralRules</code> object is 18775d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * returned. 18785d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @param type The plural type (e.g., cardinal or ordinal). 18795d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @return The predefined <code>PluralRules</code> object for this locale. 18805d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * If there's no predefined rules for this locale, the rules 18815d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * for the closest parent in the locale hierarchy that has one will 18825d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * be returned. The final fallback always returns the default 18835d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * rules. 18845d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @stable ICU 50 18855d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 18868d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath public static PluralRules forLocale(Locale locale, PluralType type) { 18875d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return Factory.getDefaultFactory().forLocale(locale, type); 18885d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 18895d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 18905d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /* 18915d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Checks whether a token is a valid keyword. 18925d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * 18935d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @param token the token to be checked 18945d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @return true if the token is a valid keyword. 18955d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 18965d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private static boolean isValidKeyword(String token) { 18978d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath // return ALLOWED_ID.containsAll(token); 18988d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath for (int i = 0; i < token.length(); ++i) { 18998d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath char c = token.charAt(i); 19008d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath if (!('a' <= c && c <= 'z')) { 19018d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath return false; 19028d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath } 19038d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath } 19048d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath return true; 19055d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 19065d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 19075d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /* 19085d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Creates a new <code>PluralRules</code> object. Immutable. 19095d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 19105d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private PluralRules(RuleList rules) { 19115d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath this.rules = rules; 19125d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath this.keywords = Collections.unmodifiableSet(rules.getKeywords()); 19135d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 19145d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 19155d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 19165d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 19175d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 19185d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 19198d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 19205d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath @Override 19215d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public int hashCode() { 19225d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return rules.hashCode(); 19235d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 19245d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 19255d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Given a number, returns the keyword of the first rule that applies to 19265d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * the number. 19275d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * 19285d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @param number The number for which the rule has to be determined. 19295d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @return The keyword of the selected rule. 19305d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @stable ICU 4.0 19315d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 19325d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public String select(double number) { 19335d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return rules.select(new FixedDecimal(number)); 19345d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 19355d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 19365d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 19375d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Given a number, returns the keyword of the first rule that applies to 19385d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * the number. 19395d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * 19405d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @param number The number for which the rule has to be determined. 19415d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @return The keyword of the selected rule. 19425d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 19435d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 19445d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 19458d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 19465d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public String select(double number, int countVisibleFractionDigits, long fractionaldigits) { 19475d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return rules.select(new FixedDecimal(number, countVisibleFractionDigits, fractionaldigits)); 19485d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 19495d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 19505d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 19515d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Given a number information, returns the keyword of the first rule that applies to 19525d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * the number. 19535d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * 19545d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @param sample The number information for which the rule has to be determined. 19555d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @return The keyword of the selected rule. 19565d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 19575d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 19585d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 19598d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 19605d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public String select(FixedDecimal sample) { 19615d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return rules.select(sample); 19625d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 19635d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 19645d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 19655d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 19665d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Given a number information, and keyword, return whether the keyword would match the number. 19675d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * 19685d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @param sample The number information for which the rule has to be determined. 19695d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @param keyword The keyword to filter on 19705d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 19715d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 19725d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 19738d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 19745d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public boolean matches(FixedDecimal sample, String keyword) { 19755d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return rules.select(sample, keyword); 19765d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 19775d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 19785d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 19795d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Returns a set of all rule keywords used in this <code>PluralRules</code> 19805d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * object. The rule "other" is always present by default. 19815d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * 19825d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @return The set of keywords. 19835d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @stable ICU 3.8 19845d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 19855d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public Set<String> getKeywords() { 19865d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return keywords; 19875d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 19885d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 19895d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 19905d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Returns the unique value that this keyword matches, or {@link #NO_UNIQUE_VALUE} 19915d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * if the keyword matches multiple values or is not defined for this PluralRules. 19925d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * 19935d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @param keyword the keyword to check for a unique value 19945d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @return The unique value for the keyword, or NO_UNIQUE_VALUE. 19955d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @stable ICU 4.8 19965d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 19975d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public double getUniqueKeywordValue(String keyword) { 19985d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath Collection<Double> values = getAllKeywordValues(keyword); 19995d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (values != null && values.size() == 1) { 20005d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return values.iterator().next(); 20015d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 20025d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return NO_UNIQUE_VALUE; 20035d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 20045d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 20055d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 20065d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Returns all the values that trigger this keyword, or null if the number of such 20075d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * values is unlimited. 20085d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * 20095d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @param keyword the keyword 20105d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @return the values that trigger this keyword, or null. The returned collection 20115d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * is immutable. It will be empty if the keyword is not defined. 20125d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @stable ICU 4.8 20135d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 20145d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public Collection<Double> getAllKeywordValues(String keyword) { 20155d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return getAllKeywordValues(keyword, SampleType.INTEGER); 20165d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 20175d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 20185d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 20195d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Returns all the values that trigger this keyword, or null if the number of such 20205d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * values is unlimited. 20215d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * 20225d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @param keyword the keyword 20238d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath * @param type the type of samples requested, INTEGER or DECIMAL 20245d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @return the values that trigger this keyword, or null. The returned collection 20255d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * is immutable. It will be empty if the keyword is not defined. 20265d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * 20275d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 20285d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 20295d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 20308d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 20315d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public Collection<Double> getAllKeywordValues(String keyword, SampleType type) { 20325d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (!isLimited(keyword, type)) { 20335d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return null; 20345d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 20355d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath Collection<Double> samples = getSamples(keyword, type); 20365d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return samples == null ? null : Collections.unmodifiableCollection(samples); 20375d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 20385d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 20395d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 20408d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath * Returns a list of integer values for which select() would return that keyword, 20415d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * or null if the keyword is not defined. The returned collection is unmodifiable. 20425d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * The returned list is not complete, and there might be additional values that 20435d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * would return the keyword. 20445d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * 20455d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @param keyword the keyword to test 20465d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @return a list of values matching the keyword. 20475d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @stable ICU 4.8 20485d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 20495d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public Collection<Double> getSamples(String keyword) { 20505d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return getSamples(keyword, SampleType.INTEGER); 20515d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 20525d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 20535d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 20545d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Returns a list of values for which select() would return that keyword, 20555d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * or null if the keyword is not defined. 20565d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * The returned collection is unmodifiable. 20575d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * The returned list is not complete, and there might be additional values that 20585d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * would return the keyword. The keyword might be defined, and yet have an empty set of samples, 20595d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * IF there are samples for the other sampleType. 20605d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * 20615d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @param keyword the keyword to test 20628d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath * @param sampleType the type of samples requested, INTEGER or DECIMAL 20635d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @return a list of values matching the keyword. 20648d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath * @internal 20655d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated ICU internal only 20665d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 20678d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 20685d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public Collection<Double> getSamples(String keyword, SampleType sampleType) { 20695d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (!keywords.contains(keyword)) { 20705d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return null; 20715d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 20725d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath Set<Double> result = new TreeSet<Double>(); 20735d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 20745d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (rules.hasExplicitBoundingInfo) { 20755d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath FixedDecimalSamples samples = rules.getDecimalSamples(keyword, sampleType); 20765d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return samples == null ? Collections.unmodifiableSet(result) 20775d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath : Collections.unmodifiableSet(samples.addSamples(result)); 20785d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 20795d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 20805d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath // hack in case the rule is created without explicit samples 20815d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath int maxCount = isLimited(keyword, sampleType) ? Integer.MAX_VALUE : 20; 20825d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 20835d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath switch (sampleType) { 20845d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath case INTEGER: 20855d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath for (int i = 0; i < 200; ++i) { 20865d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (!addSample(keyword, i, maxCount, result)) { 20875d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath break; 20885d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 20895d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 20905d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath addSample(keyword, 1000000, maxCount, result); // hack for Welsh 20915d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath break; 20925d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath case DECIMAL: 20935d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath for (int i = 0; i < 2000; ++i) { 20945d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (!addSample(keyword, new FixedDecimal(i/10d, 1), maxCount, result)) { 20955d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath break; 20965d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 20975d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 20985d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath addSample(keyword, new FixedDecimal(1000000d, 1), maxCount, result); // hack for Welsh 20995d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath break; 21005d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 21015d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return result.size() == 0 ? null : Collections.unmodifiableSet(result); 21025d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 21035d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 21045d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 21055d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 21065d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 21075d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 21088d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 21095d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public boolean addSample(String keyword, Number sample, int maxCount, Set<Double> result) { 21105d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath String selectedKeyword = sample instanceof FixedDecimal ? select((FixedDecimal)sample) : select(sample.doubleValue()); 21115d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (selectedKeyword.equals(keyword)) { 21125d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath result.add(sample.doubleValue()); 21135d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (--maxCount < 0) { 21145d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return false; 21155d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 21165d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 21175d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return true; 21185d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 21195d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 21205d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 21215d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Returns a list of values for which select() would return that keyword, 21225d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * or null if the keyword is not defined or no samples are available. 21235d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * The returned collection is unmodifiable. 21245d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * The returned list is not complete, and there might be additional values that 21255d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * would return the keyword. 21265d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * 21275d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @param keyword the keyword to test 21288d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath * @param sampleType the type of samples requested, INTEGER or DECIMAL 21295d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @return a list of values matching the keyword. 21305d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 21315d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 21325d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 21338d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 21345d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public FixedDecimalSamples getDecimalSamples(String keyword, SampleType sampleType) { 21355d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return rules.getDecimalSamples(keyword, sampleType); 21365d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 21375d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 21385d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 21395d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Returns the set of locales for which PluralRules are known. 21405d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @return the set of locales for which PluralRules are known, as a list 21415d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @draft ICU 4.2 21425d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @provisional This API might change or be removed in a future release. 21435d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public static ULocale[] getAvailableULocales() { 21445d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return Factory.getDefaultFactory().getAvailableULocales(); 21455d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 21468d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath */ 21475d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 21485d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 21495d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Returns the 'functionally equivalent' locale with respect to 21505d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * plural rules. Calling PluralRules.forLocale with the functionally equivalent 21515d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * locale, and with the provided locale, returns rules that behave the same. 21525d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * <br/> 21535d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * All locales with the same functionally equivalent locale have 21545d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * plural rules that behave the same. This is not exaustive; 21555d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * there may be other locales whose plural rules behave the same 21565d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * that do not have the same equivalent locale. 21575d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * 21585d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @param locale the locale to check 21595d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @param isAvailable if not null and of length > 0, this will hold 'true' at 21605d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * index 0 if locale is directly defined (without fallback) as having plural rules 21615d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @return the functionally-equivalent locale 21625d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @draft ICU 4.2 21635d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @provisional This API might change or be removed in a future release. 21645d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public static ULocale getFunctionalEquivalent(ULocale locale, boolean[] isAvailable) { 21655d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return Factory.getDefaultFactory().getFunctionalEquivalent(locale, isAvailable); 21665d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 21678d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath */ 21685d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 21695d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 21705d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * {@inheritDoc} 21715d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @stable ICU 3.8 21725d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 21735d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public String toString() { 21745d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return rules.toString(); 21755d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 21765d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 21775d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 21785d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * {@inheritDoc} 21795d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @stable ICU 3.8 21805d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 21815d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public boolean equals(Object rhs) { 21825d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return rhs instanceof PluralRules && equals((PluralRules)rhs); 21835d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 21845d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 21855d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 21865d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Returns true if rhs is equal to this. 21875d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @param rhs the PluralRules to compare to. 21885d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @return true if this and rhs are equal. 21895d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @stable ICU 3.8 21905d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 21915d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath // TODO Optimize this 21925d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public boolean equals(PluralRules rhs) { 21935d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return rhs != null && toString().equals(rhs.toString()); 21945d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 21955d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 21965d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 21975d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Status of the keyword for the rules, given a set of explicit values. 21985d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * 21995d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @draft ICU 50 22005d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @provisional This API might change or be removed in a future release. 22015d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 22025d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public enum KeywordStatus { 22035d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 22045d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * The keyword is not valid for the rules. 22055d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * 22065d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @draft ICU 50 22075d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @provisional This API might change or be removed in a future release. 22085d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 22095d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath INVALID, 22105d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 22115d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * The keyword is valid, but unused (it is covered by the explicit values, OR has no values for the given {@link SampleType}). 22125d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * 22135d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @draft ICU 50 22145d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @provisional This API might change or be removed in a future release. 22155d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 22165d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath SUPPRESSED, 22175d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 22185d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * The keyword is valid, used, and has a single possible value (before considering explicit values). 22195d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * 22205d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @draft ICU 50 22215d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @provisional This API might change or be removed in a future release. 22225d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 22235d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath UNIQUE, 22245d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 22255d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * The keyword is valid, used, not unique, and has a finite set of values. 22265d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * 22275d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @draft ICU 50 22285d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @provisional This API might change or be removed in a future release. 22295d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 22305d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath BOUNDED, 22315d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 22325d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * The keyword is valid but not bounded; there indefinitely many matching values. 22335d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * 22345d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @draft ICU 50 22355d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @provisional This API might change or be removed in a future release. 22365d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 22375d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath UNBOUNDED 22385d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 22395d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 22405d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 22415d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Find the status for the keyword, given a certain set of explicit values. 22425d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * 22435d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @param keyword 22445d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * the particular keyword (call rules.getKeywords() to get the valid ones) 22455d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @param offset 22465d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * the offset used, or 0.0d if not. Internally, the offset is subtracted from each explicit value before 22475d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * checking against the keyword values. 22485d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @param explicits 22495d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * a set of Doubles that are used explicitly (eg [=0], "[=1]"). May be empty or null. 22505d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @param uniqueValue 22515d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * If non null, set to the unique value. 22525d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @return the KeywordStatus 22535d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @draft ICU 50 22545d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @provisional This API might change or be removed in a future release. 22555d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 22565d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public KeywordStatus getKeywordStatus(String keyword, int offset, Set<Double> explicits, 22575d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath Output<Double> uniqueValue) { 22585d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return getKeywordStatus(keyword, offset, explicits, uniqueValue, SampleType.INTEGER); 22595d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 22605d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 22615d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * Find the status for the keyword, given a certain set of explicit values. 22625d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * 22635d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @param keyword 22645d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * the particular keyword (call rules.getKeywords() to get the valid ones) 22655d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @param offset 22665d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * the offset used, or 0.0d if not. Internally, the offset is subtracted from each explicit value before 22675d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * checking against the keyword values. 22685d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @param explicits 22695d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * a set of Doubles that are used explicitly (eg [=0], "[=1]"). May be empty or null. 22708d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath * @param sampleType 22718d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath * request KeywordStatus relative to INTEGER or DECIMAL values 22725d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @param uniqueValue 22735d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * If non null, set to the unique value. 22745d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @return the KeywordStatus 22755d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 22765d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @provisional This API might change or be removed in a future release. 22775d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 22785d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public KeywordStatus getKeywordStatus(String keyword, int offset, Set<Double> explicits, 22795d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath Output<Double> uniqueValue, SampleType sampleType) { 22805d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (uniqueValue != null) { 22815d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath uniqueValue.value = null; 22825d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 22835d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 22845d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (!keywords.contains(keyword)) { 22855d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return KeywordStatus.INVALID; 22865d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 22875d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 22885d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (!isLimited(keyword, sampleType)) { 22895d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return KeywordStatus.UNBOUNDED; 22905d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 22915d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 22925d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath Collection<Double> values = getSamples(keyword, sampleType); 22935d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 22945d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath int originalSize = values.size(); 22955d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 22965d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (explicits == null) { 22975d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath explicits = Collections.emptySet(); 22985d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 22995d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 23005d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath // Quick check on whether there are multiple elements 23015d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 23025d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (originalSize > explicits.size()) { 23035d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (originalSize == 1) { 23045d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (uniqueValue != null) { 23055d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath uniqueValue.value = values.iterator().next(); 23065d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 23075d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return KeywordStatus.UNIQUE; 23085d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 23095d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return KeywordStatus.BOUNDED; 23105d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 23115d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 23125d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath // Compute if the quick test is insufficient. 23135d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 23145d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath HashSet<Double> subtractedSet = new HashSet<Double>(values); 23155d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath for (Double explicit : explicits) { 23165d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath subtractedSet.remove(explicit - offset); 23175d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 23185d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (subtractedSet.size() == 0) { 23195d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return KeywordStatus.SUPPRESSED; 23205d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 23215d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 23225d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath if (uniqueValue != null && subtractedSet.size() == 1) { 23235d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath uniqueValue.value = subtractedSet.iterator().next(); 23245d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 23255d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 23265d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return originalSize == 1 ? KeywordStatus.UNIQUE : KeywordStatus.BOUNDED; 23275d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 23285d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 23295d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 23305d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 23315d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated This API is ICU internal only. 23325d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 23338d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 23345d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public String getRules(String keyword) { 23355d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return rules.getRules(keyword); 23365d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 23378d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath /* 23385d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private void writeObject( 23395d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath ObjectOutputStream out) 23405d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath throws IOException { 23415d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath throw new NotSerializableException(); 23425d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 23435d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 23445d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private void readObject(ObjectInputStream in 23455d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath ) throws IOException, ClassNotFoundException { 23465d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath throw new NotSerializableException(); 23475d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 23485d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 23495d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath private Object writeReplace() throws ObjectStreamException { 23505d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return new PluralRulesSerialProxy(toString()); 23515d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 23528d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath */ 23535d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 23545d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 23555d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated internal 23565d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 23578d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 23585d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public int compareTo(PluralRules other) { 23595d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return toString().compareTo(other.toString()); 23605d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 23615d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 23625d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 23635d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 23645d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated internal 23655d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 23668d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 23675d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public Boolean isLimited(String keyword) { 23685d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return rules.isLimited(keyword, SampleType.INTEGER); 23695d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 23705d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 23715d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 23725d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 23735d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated internal 23745d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 23758d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 23765d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public boolean isLimited(String keyword, SampleType sampleType) { 23775d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return rules.isLimited(keyword, sampleType); 23785d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 23795d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath 23805d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath /** 23815d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @internal 23825d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath * @deprecated internal 23835d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath */ 23848d05787d6a4b5762d790ccd2a9ed9dc8885986efNarayan Kamath @Deprecated 23855d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath public boolean computeLimited(String keyword, SampleType sampleType) { 23865d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath return rules.computeLimited(keyword, sampleType); 23875d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath } 23885d1b0c9f348c25f01c6f2f5be04d2409409c08feNarayan Kamath} 2389