1 /* 2 ******************************************************************************* 3 * Copyright (C) 2008-2011, International Business Machines Corporation and * 4 * others. All Rights Reserved. * 5 ******************************************************************************* 6 */ 7 package com.ibm.icu.impl.jdkadapter; 8 9 import java.math.RoundingMode; 10 import java.text.AttributedCharacterIterator; 11 import java.text.AttributedString; 12 import java.text.CharacterIterator; 13 import java.text.DecimalFormatSymbols; 14 import java.text.FieldPosition; 15 import java.text.ParsePosition; 16 import java.util.Currency; 17 import java.util.HashMap; 18 import java.util.Map; 19 import java.util.Map.Entry; 20 21 import com.ibm.icu.text.DecimalFormat; 22 import com.ibm.icu.text.NumberFormat; 23 24 /** 25 * DecimalFormatICU is an adapter class which wraps ICU4J DecimalFormat and 26 * implements java.text.DecimalFormat APIs. 27 */ 28 public class DecimalFormatICU extends java.text.DecimalFormat { 29 30 private static final long serialVersionUID = 6441573352964019403L; 31 32 private DecimalFormat fIcuDecfmt; 33 DecimalFormatICU(DecimalFormat icuDecfmt)34 private DecimalFormatICU(DecimalFormat icuDecfmt) { 35 fIcuDecfmt = icuDecfmt; 36 } 37 wrap(DecimalFormat icuDecfmt)38 public static java.text.DecimalFormat wrap(DecimalFormat icuDecfmt) { 39 return new DecimalFormatICU(icuDecfmt); 40 } 41 unwrap()42 public DecimalFormat unwrap() { 43 return fIcuDecfmt; 44 } 45 46 // Methods overriding java.text.DecimalFormat 47 @Override applyLocalizedPattern(String pattern)48 public void applyLocalizedPattern(String pattern) { 49 fIcuDecfmt.applyLocalizedPattern(pattern); 50 } 51 52 @Override applyPattern(String pattern)53 public void applyPattern(String pattern) { 54 fIcuDecfmt.applyPattern(pattern); 55 } 56 57 @Override clone()58 public Object clone() { 59 DecimalFormatICU other = (DecimalFormatICU)super.clone(); 60 other.fIcuDecfmt = (DecimalFormat)fIcuDecfmt.clone(); 61 return other; 62 } 63 64 @Override equals(Object obj)65 public boolean equals(Object obj) { 66 if (obj instanceof DecimalFormatICU) { 67 return ((DecimalFormatICU)obj).fIcuDecfmt.equals(fIcuDecfmt); 68 } 69 return false; 70 } 71 72 @Override format(double number, StringBuffer result, FieldPosition fieldPosition)73 public StringBuffer format(double number, StringBuffer result, FieldPosition fieldPosition) { 74 return fIcuDecfmt.format(number, result, fieldPosition); 75 } 76 77 @Override format(long number, StringBuffer result, FieldPosition fieldPosition)78 public StringBuffer format(long number, StringBuffer result, FieldPosition fieldPosition) { 79 return fIcuDecfmt.format(number, result, fieldPosition); 80 } 81 82 @Override formatToCharacterIterator(Object obj)83 public AttributedCharacterIterator formatToCharacterIterator(Object obj) { 84 AttributedCharacterIterator aci = fIcuDecfmt.formatToCharacterIterator(obj); 85 86 // Create a new AttributedString 87 StringBuilder sb = new StringBuilder(aci.getEndIndex() - aci.getBeginIndex()); 88 char c = aci.first(); 89 while (true) { 90 sb.append(c); 91 c = aci.next(); 92 if (c == CharacterIterator.DONE) { 93 break; 94 } 95 } 96 AttributedString resstr = new AttributedString(sb.toString()); 97 98 // Mapping attributes 99 Map<AttributedCharacterIterator.Attribute,Object> attributes = null; 100 int index = aci.getBeginIndex(); 101 int residx = 0; 102 while (true) { 103 if (aci.setIndex(index) == CharacterIterator.DONE) { 104 break; 105 } 106 attributes = aci.getAttributes(); 107 if (attributes != null) { 108 int end = aci.getRunLimit(); 109 Map<AttributedCharacterIterator.Attribute,Object> jdkAttributes = 110 new HashMap<AttributedCharacterIterator.Attribute,Object>(); 111 for (Entry<AttributedCharacterIterator.Attribute, Object> entry 112 : attributes.entrySet()) { 113 AttributedCharacterIterator.Attribute key = entry.getKey(); 114 AttributedCharacterIterator.Attribute jdkKey = mapAttribute(key); 115 Object jdkVal = entry.getValue(); 116 if (jdkVal instanceof AttributedCharacterIterator.Attribute) { 117 jdkVal = mapAttribute((AttributedCharacterIterator.Attribute)jdkVal); 118 } 119 jdkAttributes.put(jdkKey, jdkVal); 120 } 121 int resend = residx + (end - index); 122 resstr.addAttributes(jdkAttributes, residx, resend); 123 124 index = end; 125 residx = resend; 126 } 127 } 128 return resstr.getIterator(); 129 } 130 131 @Override getCurrency()132 public Currency getCurrency() { 133 com.ibm.icu.util.Currency icuCurrency = fIcuDecfmt.getCurrency(); 134 if (icuCurrency == null) { 135 return null; 136 } 137 return Currency.getInstance(icuCurrency.getCurrencyCode()); 138 } 139 140 @Override getDecimalFormatSymbols()141 public DecimalFormatSymbols getDecimalFormatSymbols() { 142 return DecimalFormatSymbolsICU.wrap(fIcuDecfmt.getDecimalFormatSymbols()); 143 } 144 145 @Override getGroupingSize()146 public int getGroupingSize() { 147 return fIcuDecfmt.getGroupingSize(); 148 } 149 150 @Override getMaximumFractionDigits()151 public int getMaximumFractionDigits() { 152 return fIcuDecfmt.getMaximumFractionDigits(); 153 } 154 155 @Override getMaximumIntegerDigits()156 public int getMaximumIntegerDigits() { 157 return fIcuDecfmt.getMaximumIntegerDigits(); 158 } 159 160 @Override getMinimumFractionDigits()161 public int getMinimumFractionDigits() { 162 return fIcuDecfmt.getMinimumFractionDigits(); 163 } 164 165 @Override getMinimumIntegerDigits()166 public int getMinimumIntegerDigits() { 167 return fIcuDecfmt.getMinimumIntegerDigits(); 168 } 169 170 @Override getMultiplier()171 public int getMultiplier() { 172 return fIcuDecfmt.getMultiplier(); 173 } 174 175 @Override getNegativePrefix()176 public String getNegativePrefix() { 177 return fIcuDecfmt.getNegativePrefix(); 178 } 179 180 @Override getNegativeSuffix()181 public String getNegativeSuffix() { 182 return fIcuDecfmt.getNegativeSuffix(); 183 } 184 185 @Override getPositivePrefix()186 public String getPositivePrefix() { 187 return fIcuDecfmt.getPositivePrefix(); 188 } 189 190 @Override getPositiveSuffix()191 public String getPositiveSuffix() { 192 return fIcuDecfmt.getPositiveSuffix(); 193 } 194 195 @Override getRoundingMode()196 public RoundingMode getRoundingMode() { 197 int icuMode = fIcuDecfmt.getRoundingMode(); 198 RoundingMode mode = RoundingMode.UP; 199 switch (icuMode) { 200 case com.ibm.icu.math.BigDecimal.ROUND_CEILING: 201 mode = RoundingMode.CEILING; 202 break; 203 case com.ibm.icu.math.BigDecimal.ROUND_DOWN: 204 mode = RoundingMode.DOWN; 205 break; 206 case com.ibm.icu.math.BigDecimal.ROUND_FLOOR: 207 mode = RoundingMode.FLOOR; 208 break; 209 case com.ibm.icu.math.BigDecimal.ROUND_HALF_DOWN: 210 mode = RoundingMode.HALF_DOWN; 211 break; 212 case com.ibm.icu.math.BigDecimal.ROUND_HALF_EVEN: 213 mode = RoundingMode.HALF_EVEN; 214 break; 215 case com.ibm.icu.math.BigDecimal.ROUND_HALF_UP: 216 mode = RoundingMode.HALF_UP; 217 break; 218 case com.ibm.icu.math.BigDecimal.ROUND_UNNECESSARY: 219 mode = RoundingMode.UNNECESSARY; 220 break; 221 case com.ibm.icu.math.BigDecimal.ROUND_UP: 222 mode = RoundingMode.UP; 223 break; 224 } 225 return mode; 226 } 227 228 @Override hashCode()229 public int hashCode() { 230 return fIcuDecfmt.hashCode(); 231 } 232 233 @Override isDecimalSeparatorAlwaysShown()234 public boolean isDecimalSeparatorAlwaysShown() { 235 return fIcuDecfmt.isDecimalSeparatorAlwaysShown(); 236 } 237 238 @Override isParseBigDecimal()239 public boolean isParseBigDecimal() { 240 return fIcuDecfmt.isParseBigDecimal(); 241 } 242 243 @Override parse(String text, ParsePosition pos)244 public Number parse(String text, ParsePosition pos) { 245 return fIcuDecfmt.parse(text, pos); 246 } 247 248 @Override setCurrency(Currency currency)249 public void setCurrency(Currency currency) { 250 if (currency == null) { 251 fIcuDecfmt.setCurrency(null); 252 } else { 253 fIcuDecfmt.setCurrency(com.ibm.icu.util.Currency.getInstance(currency.getCurrencyCode())); 254 } 255 } 256 257 @Override setDecimalFormatSymbols(DecimalFormatSymbols newSymbols)258 public void setDecimalFormatSymbols(DecimalFormatSymbols newSymbols) { 259 com.ibm.icu.text.DecimalFormatSymbols icuDecfs = null; 260 if (newSymbols instanceof DecimalFormatSymbolsICU) { 261 icuDecfs = ((DecimalFormatSymbolsICU)newSymbols).unwrap(); 262 } else { 263 icuDecfs = fIcuDecfmt.getDecimalFormatSymbols(); 264 265 Currency currency = newSymbols.getCurrency(); 266 if (currency == null) { 267 icuDecfs.setCurrency(null); 268 } else { 269 icuDecfs.setCurrency(com.ibm.icu.util.Currency.getInstance(currency.getCurrencyCode())); 270 } 271 272 // Copy symbols 273 icuDecfs.setCurrencySymbol(newSymbols.getCurrencySymbol()); 274 icuDecfs.setDecimalSeparator(newSymbols.getDecimalSeparator()); 275 icuDecfs.setDigit(newSymbols.getDigit()); 276 icuDecfs.setExponentSeparator(newSymbols.getExponentSeparator()); 277 icuDecfs.setGroupingSeparator(newSymbols.getGroupingSeparator()); 278 icuDecfs.setInfinity(newSymbols.getInfinity()); 279 icuDecfs.setInternationalCurrencySymbol(newSymbols.getInternationalCurrencySymbol()); 280 icuDecfs.setMinusSign(newSymbols.getMinusSign()); 281 icuDecfs.setMonetaryDecimalSeparator(newSymbols.getMonetaryDecimalSeparator()); 282 icuDecfs.setNaN(newSymbols.getNaN()); 283 icuDecfs.setPatternSeparator(newSymbols.getPatternSeparator()); 284 icuDecfs.setPercent(newSymbols.getPercent()); 285 icuDecfs.setPerMill(newSymbols.getPerMill()); 286 icuDecfs.setZeroDigit(newSymbols.getZeroDigit()); 287 } 288 fIcuDecfmt.setDecimalFormatSymbols(icuDecfs); 289 } 290 291 @Override setDecimalSeparatorAlwaysShown(boolean newValue)292 public void setDecimalSeparatorAlwaysShown(boolean newValue) { 293 if (fIcuDecfmt != null) { 294 fIcuDecfmt.setDecimalSeparatorAlwaysShown(newValue); 295 } 296 } 297 298 @Override setGroupingSize(int newValue)299 public void setGroupingSize(int newValue) { 300 if (fIcuDecfmt != null) { 301 fIcuDecfmt.setGroupingSize(newValue); 302 } 303 } 304 305 @Override setMaximumFractionDigits(int newValue)306 public void setMaximumFractionDigits(int newValue) { 307 if (fIcuDecfmt != null) { 308 fIcuDecfmt.setMaximumFractionDigits(newValue); 309 } 310 } 311 312 @Override setMaximumIntegerDigits(int newValue)313 public void setMaximumIntegerDigits(int newValue) { 314 if (fIcuDecfmt != null) { 315 fIcuDecfmt.setMaximumIntegerDigits(newValue); 316 } 317 } 318 319 @Override setMinimumFractionDigits(int newValue)320 public void setMinimumFractionDigits(int newValue) { 321 if (fIcuDecfmt != null) { 322 fIcuDecfmt.setMinimumFractionDigits(newValue); 323 } 324 } 325 326 @Override setMinimumIntegerDigits(int newValue)327 public void setMinimumIntegerDigits(int newValue) { 328 if (fIcuDecfmt != null) { 329 fIcuDecfmt.setMinimumIntegerDigits(newValue); 330 } 331 } 332 333 @Override setMultiplier(int newValue)334 public void setMultiplier(int newValue) { 335 fIcuDecfmt.setMultiplier(newValue); 336 } 337 338 @Override setNegativePrefix(String newValue)339 public void setNegativePrefix(String newValue) { 340 fIcuDecfmt.setNegativePrefix(newValue); 341 } 342 343 @Override setNegativeSuffix(String newValue)344 public void setNegativeSuffix(String newValue) { 345 fIcuDecfmt.setNegativeSuffix(newValue); 346 } 347 348 @Override setParseBigDecimal(boolean newValue)349 public void setParseBigDecimal(boolean newValue) { 350 fIcuDecfmt.setParseBigDecimal(newValue); 351 } 352 353 @Override setPositivePrefix(String newValue)354 public void setPositivePrefix(String newValue) { 355 fIcuDecfmt.setPositivePrefix(newValue); 356 } 357 358 @Override setPositiveSuffix(String newValue)359 public void setPositiveSuffix(String newValue) { 360 fIcuDecfmt.setPositiveSuffix(newValue); 361 } 362 363 @Override setRoundingMode(RoundingMode roundingMode)364 public void setRoundingMode(RoundingMode roundingMode) { 365 if (roundingMode.equals(RoundingMode.CEILING)) { 366 fIcuDecfmt.setRoundingMode(com.ibm.icu.math.BigDecimal.ROUND_CEILING); 367 } else if (roundingMode.equals(RoundingMode.DOWN)) { 368 fIcuDecfmt.setRoundingMode(com.ibm.icu.math.BigDecimal.ROUND_DOWN); 369 } else if (roundingMode.equals(RoundingMode.FLOOR)) { 370 fIcuDecfmt.setRoundingMode(com.ibm.icu.math.BigDecimal.ROUND_FLOOR); 371 } else if (roundingMode.equals(RoundingMode.HALF_DOWN)) { 372 fIcuDecfmt.setRoundingMode(com.ibm.icu.math.BigDecimal.ROUND_HALF_DOWN); 373 } else if (roundingMode.equals(RoundingMode.HALF_EVEN)) { 374 fIcuDecfmt.setRoundingMode(com.ibm.icu.math.BigDecimal.ROUND_HALF_EVEN); 375 } else if (roundingMode.equals(RoundingMode.HALF_UP)) { 376 fIcuDecfmt.setRoundingMode(com.ibm.icu.math.BigDecimal.ROUND_HALF_UP); 377 } else if (roundingMode.equals(RoundingMode.UNNECESSARY)) { 378 fIcuDecfmt.setRoundingMode(com.ibm.icu.math.BigDecimal.ROUND_UNNECESSARY); 379 } else if (roundingMode.equals(RoundingMode.UP)) { 380 fIcuDecfmt.setRoundingMode(com.ibm.icu.math.BigDecimal.ROUND_UP); 381 } else { 382 throw new IllegalArgumentException("Invalid rounding mode was specified."); 383 } 384 } 385 386 @Override toLocalizedPattern()387 public String toLocalizedPattern() { 388 return fIcuDecfmt.toLocalizedPattern(); 389 } 390 391 @Override toPattern()392 public String toPattern() { 393 return fIcuDecfmt.toPattern(); 394 } 395 396 // Methods overriding java.text.NumberFormat 397 398 @Override isGroupingUsed()399 public boolean isGroupingUsed() { 400 return fIcuDecfmt.isGroupingUsed(); 401 } 402 403 @Override isParseIntegerOnly()404 public boolean isParseIntegerOnly() { 405 return fIcuDecfmt.isParseIntegerOnly(); 406 } 407 408 @Override setGroupingUsed(boolean newValue)409 public void setGroupingUsed(boolean newValue) { 410 if (fIcuDecfmt != null) { 411 fIcuDecfmt.setGroupingUsed(newValue); 412 } 413 } 414 415 @Override setParseIntegerOnly(boolean value)416 public void setParseIntegerOnly(boolean value) { 417 fIcuDecfmt.setParseIntegerOnly(value); 418 } 419 mapAttribute(AttributedCharacterIterator.Attribute icuAttribute)420 private static AttributedCharacterIterator.Attribute mapAttribute(AttributedCharacterIterator.Attribute icuAttribute) { 421 AttributedCharacterIterator.Attribute jdkAttribute = icuAttribute; 422 423 if (icuAttribute == NumberFormat.Field.CURRENCY) { 424 jdkAttribute = java.text.NumberFormat.Field.CURRENCY; 425 } else if (icuAttribute == NumberFormat.Field.DECIMAL_SEPARATOR) { 426 jdkAttribute = java.text.NumberFormat.Field.DECIMAL_SEPARATOR; 427 } else if (icuAttribute == NumberFormat.Field.EXPONENT) { 428 jdkAttribute = java.text.NumberFormat.Field.EXPONENT; 429 } else if (icuAttribute == NumberFormat.Field.EXPONENT_SIGN) { 430 jdkAttribute = java.text.NumberFormat.Field.EXPONENT_SIGN; 431 } else if (icuAttribute == NumberFormat.Field.EXPONENT_SYMBOL) { 432 jdkAttribute = java.text.NumberFormat.Field.EXPONENT_SYMBOL; 433 } else if (icuAttribute == NumberFormat.Field.FRACTION) { 434 jdkAttribute = java.text.NumberFormat.Field.FRACTION; 435 } else if (icuAttribute == NumberFormat.Field.GROUPING_SEPARATOR) { 436 jdkAttribute = java.text.NumberFormat.Field.GROUPING_SEPARATOR; 437 } else if (icuAttribute == NumberFormat.Field.INTEGER) { 438 jdkAttribute = java.text.NumberFormat.Field.INTEGER; 439 } else if (icuAttribute == NumberFormat.Field.PERCENT) { 440 jdkAttribute = java.text.NumberFormat.Field.PERCENT; 441 } else if (icuAttribute == NumberFormat.Field.PERMILLE) { 442 jdkAttribute = java.text.NumberFormat.Field.PERMILLE; 443 } else if (icuAttribute == NumberFormat.Field.SIGN) { 444 jdkAttribute = java.text.NumberFormat.Field.SIGN; 445 } 446 447 return jdkAttribute; 448 } 449 450 } 451