1 /* GENERATED SOURCE. DO NOT MODIFY. */ 2 // © 2018 and later: Unicode, Inc. and others. 3 // License & terms of use: http://www.unicode.org/copyright.html#License 4 package ohos.global.icu.number; 5 6 import ohos.global.icu.impl.number.range.RangeMacroProps; 7 import ohos.global.icu.number.NumberRangeFormatter.RangeCollapse; 8 import ohos.global.icu.number.NumberRangeFormatter.RangeIdentityFallback; 9 import ohos.global.icu.util.ULocale; 10 11 /** 12 * An abstract base class for specifying settings related to number formatting. This class is implemented by 13 * {@link UnlocalizedNumberRangeFormatter} and {@link LocalizedNumberRangeFormatter}. This class is not intended for 14 * public subclassing. 15 * 16 * @author sffc 17 * @see NumberRangeFormatter 18 * @hide exposed on OHOS 19 */ 20 public abstract class NumberRangeFormatterSettings<T extends NumberRangeFormatterSettings<?>> { 21 22 static final int KEY_MACROS = 0; // not used 23 static final int KEY_LOCALE = 1; 24 static final int KEY_FORMATTER_1 = 2; 25 static final int KEY_FORMATTER_2 = 3; 26 static final int KEY_SAME_FORMATTERS = 4; 27 static final int KEY_COLLAPSE = 5; 28 static final int KEY_IDENTITY_FALLBACK = 6; 29 static final int KEY_MAX = 7; 30 31 private final NumberRangeFormatterSettings<?> parent; 32 private final int key; 33 private final Object value; 34 private volatile RangeMacroProps resolvedMacros; 35 NumberRangeFormatterSettings(NumberRangeFormatterSettings<?> parent, int key, Object value)36 NumberRangeFormatterSettings(NumberRangeFormatterSettings<?> parent, int key, Object value) { 37 this.parent = parent; 38 this.key = key; 39 this.value = value; 40 } 41 42 /** 43 * Sets the NumberFormatter instance to use for the numbers in the range. The same formatter is applied to both 44 * sides of the range. 45 * <p> 46 * The NumberFormatter instances must not have a locale applied yet; the locale specified on the 47 * NumberRangeFormatter will be used. 48 * 49 * @param formatter 50 * The formatter to use for both numbers in the range. 51 * @return The fluent chain. 52 * @see NumberFormatter 53 * @see NumberRangeFormatter 54 */ 55 @SuppressWarnings("unchecked") numberFormatterBoth(UnlocalizedNumberFormatter formatter)56 public T numberFormatterBoth(UnlocalizedNumberFormatter formatter) { 57 return (T) create(KEY_SAME_FORMATTERS, true).create(KEY_FORMATTER_1, formatter); 58 } 59 60 /** 61 * Sets the NumberFormatter instance to use for the first number in the range. 62 * <p> 63 * The NumberFormatter instance must not have a locale applied yet; the locale specified on the 64 * NumberRangeFormatter will be used. 65 * 66 * @param formatterFirst 67 * The formatter to use for the first number in the range. 68 * @return The fluent chain. 69 * @see NumberFormatter 70 * @see NumberRangeFormatter 71 */ 72 @SuppressWarnings("unchecked") numberFormatterFirst(UnlocalizedNumberFormatter formatterFirst)73 public T numberFormatterFirst(UnlocalizedNumberFormatter formatterFirst) { 74 return (T) create(KEY_SAME_FORMATTERS, false).create(KEY_FORMATTER_1, formatterFirst); 75 } 76 77 /** 78 * Sets the NumberFormatter instances to use for the second number in the range. 79 * <p> 80 * The NumberFormatter instance must not have a locale applied yet; the locale specified on the 81 * NumberRangeFormatter will be used. 82 * 83 * @param formatterSecond 84 * The formatter to use for the second number in the range. 85 * @return The fluent chain. 86 * @see NumberFormatter 87 * @see NumberRangeFormatter 88 */ 89 @SuppressWarnings("unchecked") numberFormatterSecond(UnlocalizedNumberFormatter formatterSecond)90 public T numberFormatterSecond(UnlocalizedNumberFormatter formatterSecond) { 91 return (T) create(KEY_SAME_FORMATTERS, false).create(KEY_FORMATTER_2, formatterSecond); 92 } 93 94 /** 95 * Sets the aggressiveness of "collapsing" fields across the range separator. Possible values: 96 * <ul> 97 * <li>ALL: "3-5K miles"</li> 98 * <li>UNIT: "3K - 5K miles"</li> 99 * <li>NONE: "3K miles - 5K miles"</li> 100 * <li>AUTO: usually UNIT or NONE, depending on the locale and formatter settings</li> 101 * </ul> 102 * <p> 103 * The default value is AUTO. 104 * 105 * @param collapse 106 * The collapsing strategy to use for this range. 107 * @return The fluent chain. 108 * @see NumberRangeFormatter 109 */ collapse(RangeCollapse collapse)110 public T collapse(RangeCollapse collapse) { 111 return create(KEY_COLLAPSE, collapse); 112 } 113 114 /** 115 * Sets the behavior when the two sides of the range are the same. This could happen if the same two numbers are 116 * passed to the formatRange function, or if different numbers are passed to the function but they become the same 117 * after rounding rules are applied. Possible values: 118 * <ul> 119 * <li>SINGLE_VALUE: "5 miles"</li> 120 * <li>APPROXIMATELY_OR_SINGLE_VALUE: "~5 miles" or "5 miles", depending on whether the number was the same before 121 * rounding was applied</li> 122 * <li>APPROXIMATELY: "~5 miles"</li> 123 * <li>RANGE: "5-5 miles" (with collapse=UNIT)</li> 124 * </ul> 125 * <p> 126 * The default value is APPROXIMATELY. 127 * 128 * @param identityFallback 129 * The strategy to use when formatting two numbers that end up being the same. 130 * @return The fluent chain. 131 * @see NumberRangeFormatter 132 */ identityFallback(RangeIdentityFallback identityFallback)133 public T identityFallback(RangeIdentityFallback identityFallback) { 134 return create(KEY_IDENTITY_FALLBACK, identityFallback); 135 } 136 create(int key, Object value)137 /* package-protected */ abstract T create(int key, Object value); 138 resolve()139 RangeMacroProps resolve() { 140 if (resolvedMacros != null) { 141 return resolvedMacros; 142 } 143 // Although the linked-list fluent storage approach requires this method, 144 // my benchmarks show that linked-list is still faster than a full clone 145 // of a MacroProps object at each step. 146 // TODO: Remove the reference to the parent after the macros are resolved? 147 RangeMacroProps macros = new RangeMacroProps(); 148 NumberRangeFormatterSettings<?> current = this; 149 while (current != null) { 150 switch (current.key) { 151 case KEY_MACROS: 152 // ignored for now 153 break; 154 case KEY_LOCALE: 155 if (macros.loc == null) { 156 macros.loc = (ULocale) current.value; 157 } 158 break; 159 case KEY_FORMATTER_1: 160 if (macros.formatter1 == null) { 161 macros.formatter1 = (UnlocalizedNumberFormatter) current.value; 162 } 163 break; 164 case KEY_FORMATTER_2: 165 if (macros.formatter2 == null) { 166 macros.formatter2 = (UnlocalizedNumberFormatter) current.value; 167 } 168 break; 169 case KEY_SAME_FORMATTERS: 170 if (macros.sameFormatters == -1) { 171 macros.sameFormatters = (boolean) current.value ? 1 : 0; 172 } 173 break; 174 case KEY_COLLAPSE: 175 if (macros.collapse == null) { 176 macros.collapse = (RangeCollapse) current.value; 177 } 178 break; 179 case KEY_IDENTITY_FALLBACK: 180 if (macros.identityFallback == null) { 181 macros.identityFallback = (RangeIdentityFallback) current.value; 182 } 183 break; 184 default: 185 throw new AssertionError("Unknown key: " + current.key); 186 } 187 current = current.parent; 188 } 189 // Copy the locale into the children (see touchRangeLocales in C++) 190 if (macros.formatter1 != null) { 191 macros.formatter1.resolve().loc = macros.loc; 192 } 193 if (macros.formatter2 != null) { 194 macros.formatter2.resolve().loc = macros.loc; 195 } 196 resolvedMacros = macros; 197 return macros; 198 } 199 200 /** 201 * {@inheritDoc} 202 */ 203 @Override hashCode()204 public int hashCode() { 205 return resolve().hashCode(); 206 } 207 208 /** 209 * {@inheritDoc} 210 */ 211 @Override equals(Object other)212 public boolean equals(Object other) { 213 if (this == other) { 214 return true; 215 } 216 if (other == null) { 217 return false; 218 } 219 if (!(other instanceof NumberRangeFormatterSettings)) { 220 return false; 221 } 222 return resolve().equals(((NumberRangeFormatterSettings<?>) other).resolve()); 223 } 224 } 225