LEFT | RIGHT |
1 // © 2017 and later: Unicode, Inc. and others. | 1 // © 2017 and later: Unicode, Inc. and others. |
2 // License & terms of use: http://www.unicode.org/copyright.html#License | 2 // License & terms of use: http://www.unicode.org/copyright.html#License |
3 package com.ibm.icu.impl.number; | 3 package com.ibm.icu.impl.number; |
4 | 4 |
5 import java.text.ParseException; | 5 import com.ibm.icu.impl.number.Modifier.AffixModifier; |
6 | |
7 import com.ibm.icu.impl.number.formatters.CompactDecimalFormat; | 6 import com.ibm.icu.impl.number.formatters.CompactDecimalFormat; |
8 import com.ibm.icu.impl.number.formatters.PositiveNegativeAffixFormat; | 7 import com.ibm.icu.impl.number.formatters.PositiveNegativeAffixFormat; |
9 import com.ibm.icu.impl.number.formatters.PositiveNegativeAffixFormat.IPropertie
s; | 8 import com.ibm.icu.impl.number.formatters.PositiveNegativeAffixFormat.IPropertie
s; |
10 import com.ibm.icu.impl.number.modifiers.ConstantAffixModifier; | 9 import com.ibm.icu.impl.number.modifiers.ConstantAffixModifier; |
| 10 import com.ibm.icu.impl.number.modifiers.ConstantMultiFieldModifier; |
11 import com.ibm.icu.text.DecimalFormatSymbols; | 11 import com.ibm.icu.text.DecimalFormatSymbols; |
| 12 import com.ibm.icu.text.NumberFormat.Field; |
12 | 13 |
13 /** | 14 /** |
14 * A class to convert from a bag of prefix/suffix properties into a positive and | 15 * A class to convert from a bag of prefix/suffix properties into a positive and
negative {@link |
15 * negative {@link Modifier}. This is a standard implementation used by {@link | 16 * Modifier}. This is a standard implementation used by {@link PositiveNegativeA
ffixFormat}, {@link |
16 * PositiveNegativeAffixFormat}, {@link CompactDecimalFormat}, {@link Parse}, an
d others. | 17 * CompactDecimalFormat}, {@link Parse}, and others. |
17 * | 18 * |
18 * <p>This class is is intended to be an efficient generator for instances of Mo
difier by a single | 19 * <p>This class is is intended to be an efficient generator for instances of Mo
difier by a single |
19 * thread during construction of a formatter or during static formatting. It use
s internal caching | 20 * thread during construction of a formatter or during static formatting. It use
s internal caching |
20 * to avoid creating new Modifier objects when possible. It is NOT THREAD SAFE a
nd NOT IMMUTABLE. | 21 * to avoid creating new Modifier objects when possible. It is NOT THREAD SAFE a
nd NOT IMMUTABLE. |
21 * | 22 * |
22 * <p>The thread-local instance of this class provided by {@link #getThreadLocal
Instance} should be | 23 * <p>The thread-local instance of this class provided by {@link #getThreadLocal
Instance} should be |
23 * used in most cases instead of constructing a new instance of the object. | 24 * used in most cases instead of constructing a new instance of the object. |
24 * | 25 * |
25 * <p>This class also handles the logic of assigning positive signs, negative si
gns, and currency | 26 * <p>This class also handles the logic of assigning positive signs, negative si
gns, and currency |
26 * signs according to the LDML specification. | 27 * signs according to the LDML specification. |
27 */ | 28 */ |
28 public class PNAffixGenerator { | 29 public class PNAffixGenerator { |
29 public static class Result { | 30 public static class Result { |
30 public ConstantAffixModifier positive = null; | 31 public AffixModifier positive = null; |
31 public ConstantAffixModifier negative = null; | 32 public AffixModifier negative = null; |
32 } | 33 } |
33 | 34 |
34 protected static final ThreadLocal<PNAffixGenerator> threadLocalInstance = | 35 protected static final ThreadLocal<PNAffixGenerator> threadLocalInstance = |
35 new ThreadLocal<PNAffixGenerator>() { | 36 new ThreadLocal<PNAffixGenerator>() { |
36 @Override | 37 @Override |
37 protected PNAffixGenerator initialValue() { | 38 protected PNAffixGenerator initialValue() { |
38 return new PNAffixGenerator(); | 39 return new PNAffixGenerator(); |
39 } | 40 } |
40 }; | 41 }; |
41 | 42 |
42 public static PNAffixGenerator getThreadLocalInstance() { | 43 public static PNAffixGenerator getThreadLocalInstance() { |
43 return threadLocalInstance.get(); | 44 return threadLocalInstance.get(); |
44 } | 45 } |
45 | 46 |
46 // These instances are used internally and cached to avoid object creation. T
he resultInstance | 47 // These instances are used internally and cached to avoid object creation. T
he resultInstance |
47 // also serves as a 1-element cache to avoid creating objects when subsequent
calls have | 48 // also serves as a 1-element cache to avoid creating objects when subsequent
calls have |
48 // identical prefixes and suffixes. This happens, for example, when consuming
CDF data. | 49 // identical prefixes and suffixes. This happens, for example, when consuming
CDF data. |
49 private Result resultInstance = new Result(); | 50 private Result resultInstance = new Result(); |
50 private StringBuilder sb1 = new StringBuilder(); | 51 private NumberStringBuilder sb1 = new NumberStringBuilder(); |
51 private StringBuilder sb2 = new StringBuilder(); | 52 private NumberStringBuilder sb2 = new NumberStringBuilder(); |
52 private StringBuilder sb3 = new StringBuilder(); | 53 private NumberStringBuilder sb3 = new NumberStringBuilder(); |
53 private StringBuilder sb4 = new StringBuilder(); | 54 private NumberStringBuilder sb4 = new NumberStringBuilder(); |
54 | 55 |
55 /** | 56 /** |
56 * Generates modifiers using default currency symbols. | 57 * Generates modifiers using default currency symbols. |
57 * | 58 * |
58 * @param symbols The symbols to interpolate for minus, plus, percent, permill
e, and currency. | 59 * @param symbols The symbols to interpolate for minus, plus, percent, permill
e, and currency. |
59 * @param properties The bag of properties to convert. | 60 * @param properties The bag of properties to convert. |
60 * @return The positive and negative {@link Modifier}. | 61 * @return The positive and negative {@link Modifier}. |
61 * @throws ParseException | |
62 */ | 62 */ |
63 public Result getModifiers( | 63 public Result getModifiers( |
64 DecimalFormatSymbols symbols, PositiveNegativeAffixFormat.IProperties prop
erties) | 64 DecimalFormatSymbols symbols, PositiveNegativeAffixFormat.IProperties prop
erties) { |
65 throws ParseException { | |
66 // If this method is used, the user doesn't care about currencies. Default t
he currency symbols | 65 // If this method is used, the user doesn't care about currencies. Default t
he currency symbols |
67 // to the information we can get from the DecimalFormatSymbols instance. | 66 // to the information we can get from the DecimalFormatSymbols instance. |
68 return getModifiers( | 67 return getModifiers( |
69 symbols, | 68 symbols, |
70 symbols.getCurrencySymbol(), | 69 symbols.getCurrencySymbol(), |
71 symbols.getInternationalCurrencySymbol(), | 70 symbols.getInternationalCurrencySymbol(), |
72 symbols.getCurrencySymbol(), | 71 symbols.getCurrencySymbol(), |
73 properties); | 72 properties); |
74 } | 73 } |
75 | 74 |
76 /** | 75 /** |
77 * Generates modifiers using the specified currency symbol for all three lengt
hs of currency | 76 * Generates modifiers using the specified currency symbol for all three lengt
hs of currency |
78 * placeholders in the pattern string. | 77 * placeholders in the pattern string. |
79 * | 78 * |
80 * @param symbols The symbols to interpolate for minus, plus, percent, and per
mille. | 79 * @param symbols The symbols to interpolate for minus, plus, percent, and per
mille. |
81 * @param currencySymbol The currency symbol. | 80 * @param currencySymbol The currency symbol. |
82 * @param properties The bag of properties to convert. | 81 * @param properties The bag of properties to convert. |
83 * @return The positive and negative {@link Modifier}. | 82 * @return The positive and negative {@link Modifier}. |
84 * @throws ParseException | |
85 */ | 83 */ |
86 public Result getModifiers( | 84 public Result getModifiers( |
87 DecimalFormatSymbols symbols, | 85 DecimalFormatSymbols symbols, |
88 String currencySymbol, | 86 String currencySymbol, |
89 PositiveNegativeAffixFormat.IProperties properties) | 87 PositiveNegativeAffixFormat.IProperties properties) { |
90 throws ParseException { | |
91 // If this method is used, the user doesn't cares about currencies but doesn
't care about | 88 // If this method is used, the user doesn't cares about currencies but doesn
't care about |
92 // supporting all three sizes of currency placeholders. Use the one provide
d string for all | 89 // supporting all three sizes of currency placeholders. Use the one provide
d string for all |
93 // three sizes of placeholders. | 90 // three sizes of placeholders. |
94 return getModifiers(symbols, currencySymbol, currencySymbol, currencySymbol,
properties); | 91 return getModifiers(symbols, currencySymbol, currencySymbol, currencySymbol,
properties); |
95 } | 92 } |
96 | 93 |
97 /** | 94 /** |
98 * Generates modifiers using the three specified strings to replace the three
lengths of currency | 95 * Generates modifiers using the three specified strings to replace the three
lengths of currency |
99 * placeholders: "¤", "¤¤", and "¤¤¤". | 96 * placeholders: "¤", "¤¤", and "¤¤¤". |
100 * | 97 * |
101 * @param symbols The symbols to interpolate for minus, plus, percent, and per
mille. | 98 * @param symbols The symbols to interpolate for minus, plus, percent, and per
mille. |
102 * @param curr1 The string to replace "¤". | 99 * @param curr1 The string to replace "¤". |
103 * @param curr2 The string to replace "¤¤". | 100 * @param curr2 The string to replace "¤¤". |
104 * @param curr3 The string to replace "¤¤¤". | 101 * @param curr3 The string to replace "¤¤¤". |
105 * @param properties The bag of properties to convert. | 102 * @param properties The bag of properties to convert. |
106 * @return The positive and negative {@link Modifier}. | 103 * @return The positive and negative {@link Modifier}. |
107 * @throws ParseException | |
108 */ | 104 */ |
109 public Result getModifiers( | 105 public Result getModifiers( |
110 DecimalFormatSymbols symbols, | 106 DecimalFormatSymbols symbols, |
111 String curr1, | 107 String curr1, |
112 String curr2, | 108 String curr2, |
113 String curr3, | 109 String curr3, |
114 PositiveNegativeAffixFormat.IProperties properties) | 110 PositiveNegativeAffixFormat.IProperties properties) { |
115 throws ParseException { | |
116 | 111 |
117 // Use a different code path for handling affixes with "always show plus sig
n" | 112 // Use a different code path for handling affixes with "always show plus sig
n" |
118 if (properties.getAlwaysShowPlusSign()) { | 113 if (properties.getPlusSignAlwaysShown()) { |
119 return getModifiersWithPlusSign(symbols, curr1, curr2, curr3, properties); | 114 return getModifiersWithPlusSign(symbols, curr1, curr2, curr3, properties); |
120 } | 115 } |
121 | 116 |
122 CharSequence ppp = properties.getPositivePrefixPattern(); | 117 CharSequence ppp = properties.getPositivePrefixPattern(); |
123 CharSequence psp = properties.getPositiveSuffixPattern(); | 118 CharSequence psp = properties.getPositiveSuffixPattern(); |
124 CharSequence npp = properties.getNegativePrefixPattern(); | 119 CharSequence npp = properties.getNegativePrefixPattern(); |
125 CharSequence nsp = properties.getNegativeSuffixPattern(); | 120 CharSequence nsp = properties.getNegativeSuffixPattern(); |
126 | 121 |
127 // Set sb1/sb2 to the positive prefix/suffix. | 122 // Set sb1/sb2 to the positive prefix/suffix. |
128 sb1.setLength(0); | 123 sb1.clear(); |
129 sb2.setLength(0); | 124 sb2.clear(); |
130 LiteralString.unescape(ppp, symbols, curr1, curr2, curr3, null, sb1); | 125 AffixPatternUtils.unescape(ppp, symbols, curr1, curr2, curr3, null, sb1); |
131 LiteralString.unescape(psp, symbols, curr1, curr2, curr3, null, sb2); | 126 AffixPatternUtils.unescape(psp, symbols, curr1, curr2, curr3, null, sb2); |
132 setPositiveResult(sb1, sb2, properties); | 127 setPositiveResult(sb1, sb2, properties); |
133 | 128 |
134 // Set sb1/sb2 to the negative prefix/suffix. | 129 // Set sb1/sb2 to the negative prefix/suffix. |
135 if (npp == null && nsp == null) { | 130 if (npp == null && nsp == null) { |
136 // Negative prefix defaults to positive prefix prepended with the minus si
gn. | 131 // Negative prefix defaults to positive prefix prepended with the minus si
gn. |
137 // Negative suffix defaults to positive suffix. | 132 // Negative suffix defaults to positive suffix. |
138 sb1.insert(0, symbols.getMinusSignString()); | 133 sb1.insert(0, symbols.getMinusSignString(), Field.SIGN); |
139 } else { | 134 } else { |
140 sb1.setLength(0); | 135 sb1.clear(); |
141 sb2.setLength(0); | 136 sb2.clear(); |
142 LiteralString.unescape(npp, symbols, curr1, curr2, curr3, null, sb1); | 137 AffixPatternUtils.unescape(npp, symbols, curr1, curr2, curr3, null, sb1); |
143 LiteralString.unescape(nsp, symbols, curr1, curr2, curr3, null, sb2); | 138 AffixPatternUtils.unescape(nsp, symbols, curr1, curr2, curr3, null, sb2); |
144 } | 139 } |
145 setNegativeResult(sb1, sb2, properties); | 140 setNegativeResult(sb1, sb2, properties); |
146 | 141 |
147 return resultInstance; | 142 return resultInstance; |
148 } | 143 } |
149 | 144 |
150 private Result getModifiersWithPlusSign( | 145 private Result getModifiersWithPlusSign( |
151 DecimalFormatSymbols symbols, | 146 DecimalFormatSymbols symbols, |
152 String curr1, | 147 String curr1, |
153 String curr2, | 148 String curr2, |
154 String curr3, | 149 String curr3, |
155 IProperties properties) | 150 IProperties properties) { |
156 throws ParseException { | |
157 | 151 |
158 CharSequence ppp = properties.getPositivePrefixPattern(); | 152 CharSequence ppp = properties.getPositivePrefixPattern(); |
159 CharSequence psp = properties.getPositiveSuffixPattern(); | 153 CharSequence psp = properties.getPositiveSuffixPattern(); |
160 CharSequence npp = properties.getNegativePrefixPattern(); | 154 CharSequence npp = properties.getNegativePrefixPattern(); |
161 CharSequence nsp = properties.getNegativeSuffixPattern(); | 155 CharSequence nsp = properties.getNegativeSuffixPattern(); |
162 | 156 |
163 // There are three cases, listed below with their expected outcomes. | 157 // There are three cases, listed below with their expected outcomes. |
164 // TODO: Should we handle the cases when the positive subpattern has a '+' a
lready? | 158 // TODO: Should we handle the cases when the positive subpattern has a '+' a
lready? |
165 // | 159 // |
166 // 1) No negative subpattern. | 160 // 1) No negative subpattern. |
167 // Positive => Positive subpattern prepended with '+' | 161 // Positive => Positive subpattern prepended with '+' |
168 // Negative => Positive subpattern prepended with '-' | 162 // Negative => Positive subpattern prepended with '-' |
169 // 2) Negative subpattern does not have '-'. | 163 // 2) Negative subpattern does not have '-'. |
170 // Positive => Positive subpattern prepended with '+' | 164 // Positive => Positive subpattern prepended with '+' |
171 // Negative => Negative subpattern | 165 // Negative => Negative subpattern |
172 // 3) Negative subpattern has '-'. | 166 // 3) Negative subpattern has '-'. |
173 // Positive => Negative subpattern with '+' substituted for '-' | 167 // Positive => Negative subpattern with '+' substituted for '-' |
174 // Negative => Negative subpattern | 168 // Negative => Negative subpattern |
175 | 169 |
176 if (npp != null || nsp != null) { | 170 if (npp != null || nsp != null) { |
177 // Case 2 or Case 3 | 171 // Case 2 or Case 3 |
178 sb1.setLength(0); | 172 sb1.clear(); |
179 sb2.setLength(0); | 173 sb2.clear(); |
180 sb3.setLength(0); | 174 sb3.clear(); |
181 sb4.setLength(0); | 175 sb4.clear(); |
182 LiteralString.unescape(npp, symbols, curr1, curr2, curr3, null, sb1); | 176 AffixPatternUtils.unescape(npp, symbols, curr1, curr2, curr3, null, sb1); |
183 LiteralString.unescape(nsp, symbols, curr1, curr2, curr3, null, sb2); | 177 AffixPatternUtils.unescape(nsp, symbols, curr1, curr2, curr3, null, sb2); |
184 LiteralString.unescape(npp, symbols, curr1, curr2, curr3, symbols.getPlusS
ignString(), sb3); | 178 AffixPatternUtils.unescape( |
185 LiteralString.unescape(nsp, symbols, curr1, curr2, curr3, symbols.getPlusS
ignString(), sb4); | 179 npp, symbols, curr1, curr2, curr3, symbols.getPlusSignString(), sb3); |
| 180 AffixPatternUtils.unescape( |
| 181 nsp, symbols, curr1, curr2, curr3, symbols.getPlusSignString(), sb4); |
186 if (!charSequenceEquals(sb1, sb3) || !charSequenceEquals(sb2, sb4)) { | 182 if (!charSequenceEquals(sb1, sb3) || !charSequenceEquals(sb2, sb4)) { |
187 // Case 3. The plus sign substitution was successful. | 183 // Case 3. The plus sign substitution was successful. |
188 setPositiveResult(sb3, sb4, properties); | 184 setPositiveResult(sb3, sb4, properties); |
189 setNegativeResult(sb1, sb2, properties); | 185 setNegativeResult(sb1, sb2, properties); |
190 return resultInstance; | 186 return resultInstance; |
191 } else { | 187 } else { |
192 // Case 2. There was no minus sign. Set the negative result and fall thr
ough. | 188 // Case 2. There was no minus sign. Set the negative result and fall thr
ough. |
193 setNegativeResult(sb1, sb2, properties); | 189 setNegativeResult(sb1, sb2, properties); |
194 } | 190 } |
195 } | 191 } |
196 | 192 |
197 // Case 1 or 2. Set sb1/sb2 to the positive prefix/suffix. | 193 // Case 1 or 2. Set sb1/sb2 to the positive prefix/suffix. |
198 sb1.setLength(0); | 194 sb1.clear(); |
199 sb2.setLength(0); | 195 sb2.clear(); |
200 LiteralString.unescape(ppp, symbols, curr1, curr2, curr3, null, sb1); | 196 AffixPatternUtils.unescape(ppp, symbols, curr1, curr2, curr3, null, sb1); |
201 LiteralString.unescape(psp, symbols, curr1, curr2, curr3, null, sb2); | 197 AffixPatternUtils.unescape(psp, symbols, curr1, curr2, curr3, null, sb2); |
202 | 198 |
203 if (npp == null && nsp == null) { | 199 if (npp == null && nsp == null) { |
204 // Case 1. Compute the negative result from the positive subpattern. | 200 // Case 1. Compute the negative result from the positive subpattern. |
205 sb3.setLength(0); | 201 sb3.clear(); |
206 sb3.append(symbols.getMinusSignString()); | 202 sb3.append(symbols.getMinusSignString(), Field.SIGN); |
207 sb3.append(sb1); | 203 sb3.append(sb1); |
208 setNegativeResult(sb3, sb2, properties); | 204 setNegativeResult(sb3, sb2, properties); |
209 } | 205 } |
210 | 206 |
211 // Case 1 or 2. Prepend a '+' sign to the positive prefix. | 207 // Case 1 or 2. Prepend a '+' sign to the positive prefix. |
212 sb1.insert(0, symbols.getPlusSignString()); | 208 sb1.insert(0, symbols.getPlusSignString(), Field.SIGN); |
213 setPositiveResult(sb1, sb2, properties); | 209 setPositiveResult(sb1, sb2, properties); |
214 | 210 |
215 return resultInstance; | 211 return resultInstance; |
216 } | 212 } |
217 | 213 |
218 private void setPositiveResult(CharSequence prefix, CharSequence suffix, IProp
erties properties) { | 214 private void setPositiveResult( |
219 // Perform overrides. | 215 NumberStringBuilder prefix, NumberStringBuilder suffix, IProperties proper
ties) { |
220 if (properties.getPositivePrefix() != null) prefix = properties.getPositiveP
refix(); | 216 if (properties.getPositivePrefix() != null || properties.getPositiveSuffix()
!= null) { |
221 if (properties.getPositiveSuffix() != null) suffix = properties.getPositiveS
uffix(); | 217 // Override with custom affixes |
222 | 218 String _prefix = properties.getPositivePrefix(); |
223 // Construct the modifier. | 219 String _suffix = properties.getPositiveSuffix(); |
224 if (prefix.length() == 0 && suffix.length() == 0) { | 220 if (_prefix == null) _prefix = ""; |
225 resultInstance.positive = ConstantAffixModifier.EMPTY; | 221 if (_suffix == null) _suffix = ""; |
226 } else if (resultInstance.positive != null | 222 if (_prefix.length() == 0 && _suffix.length() == 0) { |
227 && charSequenceEquals(prefix, resultInstance.positive.prefix) | 223 resultInstance.positive = ConstantAffixModifier.EMPTY; |
228 && charSequenceEquals(suffix, resultInstance.positive.suffix)) { | 224 return; |
229 // Use the cached modifier | 225 } |
| 226 if (resultInstance.positive != null |
| 227 && (resultInstance.positive instanceof ConstantAffixModifier) |
| 228 && ((ConstantAffixModifier) resultInstance.positive).contentEquals(_pr
efix, _suffix)) { |
| 229 // Use the cached modifier |
| 230 return; |
| 231 } |
| 232 resultInstance.positive = |
| 233 new ConstantAffixModifier(_prefix, _suffix, null, false); |
230 } else { | 234 } else { |
231 resultInstance.positive = new ConstantAffixModifier(prefix.toString(), suf
fix.toString()); | 235 // Use pattern affixes |
232 } | 236 if (prefix.length() == 0 && suffix.length() == 0) { |
233 } | 237 resultInstance.positive = ConstantAffixModifier.EMPTY; |
234 | 238 return; |
235 private void setNegativeResult(CharSequence prefix, CharSequence suffix, IProp
erties properties) { | 239 } |
236 // Perform overrides. | 240 if (resultInstance.positive != null |
237 if (properties.getNegativePrefix() != null) prefix = properties.getNegativeP
refix(); | 241 && (resultInstance.positive instanceof ConstantMultiFieldModifier) |
238 if (properties.getNegativeSuffix() != null) suffix = properties.getNegativeS
uffix(); | 242 && ((ConstantMultiFieldModifier) resultInstance.positive).contentEqual
s(prefix, suffix)) { |
239 | 243 // Use the cached modifier |
240 // Construct the modifier. | 244 return; |
241 if (prefix.length() == 0 && suffix.length() == 0) { | 245 } |
242 resultInstance.negative = ConstantAffixModifier.EMPTY; | 246 resultInstance.positive = new ConstantMultiFieldModifier(prefix, suffix, f
alse); |
243 } else if (resultInstance.negative != null | 247 } |
244 && charSequenceEquals(prefix, resultInstance.negative.prefix) | 248 } |
245 && charSequenceEquals(suffix, resultInstance.negative.suffix)) { | 249 |
246 // Use the cached modifier | 250 private void setNegativeResult( |
| 251 NumberStringBuilder prefix, NumberStringBuilder suffix, IProperties proper
ties) { |
| 252 if (properties.getNegativePrefix() != null || properties.getNegativeSuffix()
!= null) { |
| 253 // Override with custom affixes |
| 254 String _prefix = properties.getNegativePrefix(); |
| 255 String _suffix = properties.getNegativeSuffix(); |
| 256 if (_prefix == null) _prefix = ""; |
| 257 if (_suffix == null) _suffix = ""; |
| 258 if (_prefix.length() == 0 && _suffix.length() == 0) { |
| 259 resultInstance.negative = ConstantAffixModifier.EMPTY; |
| 260 return; |
| 261 } |
| 262 if (resultInstance.negative != null |
| 263 && (resultInstance.negative instanceof ConstantAffixModifier) |
| 264 && ((ConstantAffixModifier) resultInstance.negative).contentEquals(_pr
efix, _suffix)) { |
| 265 // Use the cached modifier |
| 266 return; |
| 267 } |
| 268 resultInstance.negative = |
| 269 new ConstantAffixModifier(_prefix, _suffix, null, false); |
247 } else { | 270 } else { |
248 resultInstance.negative = new ConstantAffixModifier(prefix.toString(), suf
fix.toString()); | 271 // Use pattern affixes |
| 272 if (prefix.length() == 0 && suffix.length() == 0) { |
| 273 resultInstance.negative = ConstantAffixModifier.EMPTY; |
| 274 return; |
| 275 } |
| 276 if (resultInstance.negative != null |
| 277 && (resultInstance.negative instanceof ConstantMultiFieldModifier) |
| 278 && ((ConstantMultiFieldModifier) resultInstance.negative).contentEqual
s(prefix, suffix)) { |
| 279 // Use the cached modifier |
| 280 return; |
| 281 } |
| 282 resultInstance.negative = new ConstantMultiFieldModifier(prefix, suffix, f
alse); |
249 } | 283 } |
250 } | 284 } |
251 | 285 |
252 /** A null-safe equals method for CharSequences. */ | 286 /** A null-safe equals method for CharSequences. */ |
253 private static boolean charSequenceEquals(CharSequence a, CharSequence b) { | 287 private static boolean charSequenceEquals(CharSequence a, CharSequence b) { |
254 if (a == b) return true; | 288 if (a == b) return true; |
255 if (a == null || b == null) return false; | 289 if (a == null || b == null) return false; |
256 if (a.length() != b.length()) return false; | 290 if (a.length() != b.length()) return false; |
257 for (int i = 0; i < a.length(); i++) { | 291 for (int i = 0; i < a.length(); i++) { |
258 if (a.charAt(i) != b.charAt(i)) return false; | 292 if (a.charAt(i) != b.charAt(i)) return false; |
259 } | 293 } |
260 return true; | 294 return true; |
261 } | 295 } |
262 } | 296 } |
LEFT | RIGHT |