/* ******************************************************************************* * Copyright (C) 2008, International Business Machines Corporation and * * others. All Rights Reserved. * ******************************************************************************* */ package com.ibm.icu.impl.jdkadapter; import java.math.RoundingMode; import java.text.AttributedCharacterIterator; import java.text.AttributedString; import java.text.CharacterIterator; import java.text.DecimalFormatSymbols; import java.text.FieldPosition; import java.text.ParsePosition; import java.util.Currency; import java.util.HashMap; import java.util.Map; import java.util.Set; import com.ibm.icu.text.DecimalFormat; import com.ibm.icu.text.NumberFormat; /** * DecimalFormatICU is an adapter class which wraps ICU4J DecimalFormat and * implements java.text.DecimalFormat APIs. */ public class DecimalFormatICU extends java.text.DecimalFormat { private static final long serialVersionUID = 6441573352964019403L; private DecimalFormat fIcuDecfmt; private DecimalFormatICU(DecimalFormat icuDecfmt) { fIcuDecfmt = icuDecfmt; } public static java.text.DecimalFormat wrap(DecimalFormat icuDecfmt) { return new DecimalFormatICU(icuDecfmt); } public DecimalFormat unwrap() { return fIcuDecfmt; } // Methods overriding java.text.DecimalFormat @Override public void applyLocalizedPattern(String pattern) { fIcuDecfmt.applyLocalizedPattern(pattern); } @Override public void applyPattern(String pattern) { fIcuDecfmt.applyPattern(pattern); } @Override public Object clone() { DecimalFormatICU other = (DecimalFormatICU)super.clone(); other.fIcuDecfmt = (DecimalFormat)fIcuDecfmt.clone(); return other; } @Override public boolean equals(Object obj) { if (obj instanceof DecimalFormatICU) { return ((DecimalFormatICU)obj).fIcuDecfmt.equals(fIcuDecfmt); } return false; } @Override public StringBuffer format(double number, StringBuffer result, FieldPosition fieldPosition) { return fIcuDecfmt.format(number, result, fieldPosition); } @Override public StringBuffer format(long number, StringBuffer result, FieldPosition fieldPosition) { return fIcuDecfmt.format(number, result, fieldPosition); } @Override public AttributedCharacterIterator formatToCharacterIterator(Object obj) { AttributedCharacterIterator aci = fIcuDecfmt.formatToCharacterIterator(obj); // Create a new AttributedString StringBuilder sb = new StringBuilder(aci.getEndIndex() - aci.getBeginIndex()); char c = aci.first(); while (true) { sb.append(c); c = aci.next(); if (c == CharacterIterator.DONE) { break; } } AttributedString resstr = new AttributedString(sb.toString()); // Mapping attributes Map attributes = null; int index = aci.getBeginIndex(); int residx = 0; while (true) { if (aci.setIndex(index) == CharacterIterator.DONE) { break; } attributes = aci.getAttributes(); if (attributes != null) { int end = aci.getRunLimit(); Map jdkAttributes = new HashMap(); Set keys = attributes.keySet(); for (AttributedCharacterIterator.Attribute key : keys) { AttributedCharacterIterator.Attribute jdkKey = mapAttribute(key); Object jdkVal = attributes.get(key); if (jdkVal instanceof AttributedCharacterIterator.Attribute) { jdkVal = mapAttribute((AttributedCharacterIterator.Attribute)jdkVal); } jdkAttributes.put(jdkKey, jdkVal); } int resend = residx + (end - index); resstr.addAttributes(jdkAttributes, residx, resend); index = end; residx = resend; } } return resstr.getIterator(); } @Override public Currency getCurrency() { com.ibm.icu.util.Currency icuCurrency = fIcuDecfmt.getCurrency(); if (icuCurrency == null) { return null; } return Currency.getInstance(icuCurrency.getCurrencyCode()); } @Override public DecimalFormatSymbols getDecimalFormatSymbols() { return DecimalFormatSymbolsICU.wrap(fIcuDecfmt.getDecimalFormatSymbols()); } @Override public int getGroupingSize() { return fIcuDecfmt.getGroupingSize(); } @Override public int getMaximumFractionDigits() { return fIcuDecfmt.getMaximumFractionDigits(); } @Override public int getMaximumIntegerDigits() { return fIcuDecfmt.getMaximumIntegerDigits(); } @Override public int getMinimumFractionDigits() { return fIcuDecfmt.getMinimumFractionDigits(); } @Override public int getMinimumIntegerDigits() { return fIcuDecfmt.getMinimumIntegerDigits(); } @Override public int getMultiplier() { return fIcuDecfmt.getMultiplier(); } @Override public String getNegativePrefix() { return fIcuDecfmt.getNegativePrefix(); } @Override public String getNegativeSuffix() { return fIcuDecfmt.getNegativeSuffix(); } @Override public String getPositivePrefix() { return fIcuDecfmt.getPositivePrefix(); } @Override public String getPositiveSuffix() { return fIcuDecfmt.getPositiveSuffix(); } @Override public RoundingMode getRoundingMode() { int icuMode = fIcuDecfmt.getRoundingMode(); RoundingMode mode = RoundingMode.UP; switch (icuMode) { case com.ibm.icu.math.BigDecimal.ROUND_CEILING: mode = RoundingMode.CEILING; break; case com.ibm.icu.math.BigDecimal.ROUND_DOWN: mode = RoundingMode.DOWN; break; case com.ibm.icu.math.BigDecimal.ROUND_FLOOR: mode = RoundingMode.FLOOR; break; case com.ibm.icu.math.BigDecimal.ROUND_HALF_DOWN: mode = RoundingMode.HALF_DOWN; break; case com.ibm.icu.math.BigDecimal.ROUND_HALF_EVEN: mode = RoundingMode.HALF_EVEN; break; case com.ibm.icu.math.BigDecimal.ROUND_HALF_UP: mode = RoundingMode.HALF_UP; break; case com.ibm.icu.math.BigDecimal.ROUND_UNNECESSARY: mode = RoundingMode.UNNECESSARY; break; case com.ibm.icu.math.BigDecimal.ROUND_UP: mode = RoundingMode.UP; break; } return mode; } @Override public int hashCode() { return fIcuDecfmt.hashCode(); } @Override public boolean isDecimalSeparatorAlwaysShown() { return fIcuDecfmt.isDecimalSeparatorAlwaysShown(); } @Override public boolean isParseBigDecimal() { return fIcuDecfmt.isParseBigDecimal(); } @Override public Number parse(String text, ParsePosition pos) { return fIcuDecfmt.parse(text, pos); } @Override public void setCurrency(Currency currency) { if (currency == null) { fIcuDecfmt.setCurrency(null); } else { fIcuDecfmt.setCurrency(com.ibm.icu.util.Currency.getInstance(currency.getCurrencyCode())); } } @Override public void setDecimalFormatSymbols(DecimalFormatSymbols newSymbols) { com.ibm.icu.text.DecimalFormatSymbols icuDecfs = null; if (newSymbols instanceof DecimalFormatSymbolsICU) { icuDecfs = ((DecimalFormatSymbolsICU)newSymbols).unwrap(); } else { icuDecfs = fIcuDecfmt.getDecimalFormatSymbols(); Currency currency = newSymbols.getCurrency(); if (currency == null) { icuDecfs.setCurrency(null); } else { icuDecfs.setCurrency(com.ibm.icu.util.Currency.getInstance(currency.getCurrencyCode())); } // Copy symbols icuDecfs.setCurrencySymbol(newSymbols.getCurrencySymbol()); icuDecfs.setDecimalSeparator(newSymbols.getDecimalSeparator()); icuDecfs.setDigit(newSymbols.getDigit()); icuDecfs.setExponentSeparator(newSymbols.getExponentSeparator()); icuDecfs.setGroupingSeparator(newSymbols.getGroupingSeparator()); icuDecfs.setInfinity(newSymbols.getInfinity()); icuDecfs.setInternationalCurrencySymbol(newSymbols.getInternationalCurrencySymbol()); icuDecfs.setMinusSign(newSymbols.getMinusSign()); icuDecfs.setMonetaryDecimalSeparator(newSymbols.getMonetaryDecimalSeparator()); icuDecfs.setNaN(newSymbols.getNaN()); icuDecfs.setPatternSeparator(newSymbols.getPatternSeparator()); icuDecfs.setPercent(newSymbols.getPercent()); icuDecfs.setPerMill(newSymbols.getPerMill()); icuDecfs.setZeroDigit(newSymbols.getZeroDigit()); } fIcuDecfmt.setDecimalFormatSymbols(icuDecfs); } @Override public void setDecimalSeparatorAlwaysShown(boolean newValue) { if (fIcuDecfmt != null) { fIcuDecfmt.setDecimalSeparatorAlwaysShown(newValue); } } @Override public void setGroupingSize(int newValue) { if (fIcuDecfmt != null) { fIcuDecfmt.setGroupingSize(newValue); } } @Override public void setMaximumFractionDigits(int newValue) { if (fIcuDecfmt != null) { fIcuDecfmt.setMaximumFractionDigits(newValue); } } @Override public void setMaximumIntegerDigits(int newValue) { if (fIcuDecfmt != null) { fIcuDecfmt.setMaximumIntegerDigits(newValue); } } @Override public void setMinimumFractionDigits(int newValue) { if (fIcuDecfmt != null) { fIcuDecfmt.setMinimumFractionDigits(newValue); } } @Override public void setMinimumIntegerDigits(int newValue) { if (fIcuDecfmt != null) { fIcuDecfmt.setMinimumIntegerDigits(newValue); } } @Override public void setMultiplier(int newValue) { fIcuDecfmt.setMultiplier(newValue); } @Override public void setNegativePrefix(String newValue) { fIcuDecfmt.setNegativePrefix(newValue); } @Override public void setNegativeSuffix(String newValue) { fIcuDecfmt.setNegativeSuffix(newValue); } @Override public void setParseBigDecimal(boolean newValue) { fIcuDecfmt.setParseBigDecimal(newValue); } @Override public void setPositivePrefix(String newValue) { fIcuDecfmt.setPositivePrefix(newValue); } @Override public void setPositiveSuffix(String newValue) { fIcuDecfmt.setPositiveSuffix(newValue); } @Override public void setRoundingMode(RoundingMode roundingMode) { if (roundingMode.equals(RoundingMode.CEILING)) { fIcuDecfmt.setRoundingMode(com.ibm.icu.math.BigDecimal.ROUND_CEILING); } else if (roundingMode.equals(RoundingMode.DOWN)) { fIcuDecfmt.setRoundingMode(com.ibm.icu.math.BigDecimal.ROUND_DOWN); } else if (roundingMode.equals(RoundingMode.FLOOR)) { fIcuDecfmt.setRoundingMode(com.ibm.icu.math.BigDecimal.ROUND_FLOOR); } else if (roundingMode.equals(RoundingMode.HALF_DOWN)) { fIcuDecfmt.setRoundingMode(com.ibm.icu.math.BigDecimal.ROUND_HALF_DOWN); } else if (roundingMode.equals(RoundingMode.HALF_EVEN)) { fIcuDecfmt.setRoundingMode(com.ibm.icu.math.BigDecimal.ROUND_HALF_EVEN); } else if (roundingMode.equals(RoundingMode.HALF_UP)) { fIcuDecfmt.setRoundingMode(com.ibm.icu.math.BigDecimal.ROUND_HALF_UP); } else if (roundingMode.equals(RoundingMode.UNNECESSARY)) { fIcuDecfmt.setRoundingMode(com.ibm.icu.math.BigDecimal.ROUND_UNNECESSARY); } else if (roundingMode.equals(RoundingMode.UP)) { fIcuDecfmt.setRoundingMode(com.ibm.icu.math.BigDecimal.ROUND_UP); } else { throw new IllegalArgumentException("Invalid rounding mode was specified."); } } @Override public String toLocalizedPattern() { return fIcuDecfmt.toLocalizedPattern(); } @Override public String toPattern() { return fIcuDecfmt.toPattern(); } // Methods overriding java.text.NumberFormat @Override public boolean isGroupingUsed() { return fIcuDecfmt.isGroupingUsed(); } @Override public boolean isParseIntegerOnly() { return fIcuDecfmt.isParseIntegerOnly(); } @Override public void setGroupingUsed(boolean newValue) { if (fIcuDecfmt != null) { fIcuDecfmt.setGroupingUsed(newValue); } } @Override public void setParseIntegerOnly(boolean value) { fIcuDecfmt.setParseIntegerOnly(value); } private static AttributedCharacterIterator.Attribute mapAttribute(AttributedCharacterIterator.Attribute icuAttribute) { AttributedCharacterIterator.Attribute jdkAttribute = icuAttribute; if (icuAttribute == NumberFormat.Field.CURRENCY) { jdkAttribute = java.text.NumberFormat.Field.CURRENCY; } else if (icuAttribute == NumberFormat.Field.DECIMAL_SEPARATOR) { jdkAttribute = java.text.NumberFormat.Field.DECIMAL_SEPARATOR; } else if (icuAttribute == NumberFormat.Field.EXPONENT) { jdkAttribute = java.text.NumberFormat.Field.EXPONENT; } else if (icuAttribute == NumberFormat.Field.EXPONENT_SIGN) { jdkAttribute = java.text.NumberFormat.Field.EXPONENT_SIGN; } else if (icuAttribute == NumberFormat.Field.EXPONENT_SYMBOL) { jdkAttribute = java.text.NumberFormat.Field.EXPONENT_SYMBOL; } else if (icuAttribute == NumberFormat.Field.FRACTION) { jdkAttribute = java.text.NumberFormat.Field.FRACTION; } else if (icuAttribute == NumberFormat.Field.GROUPING_SEPARATOR) { jdkAttribute = java.text.NumberFormat.Field.GROUPING_SEPARATOR; } else if (icuAttribute == NumberFormat.Field.INTEGER) { jdkAttribute = java.text.NumberFormat.Field.INTEGER; } else if (icuAttribute == NumberFormat.Field.PERCENT) { jdkAttribute = java.text.NumberFormat.Field.PERCENT; } else if (icuAttribute == NumberFormat.Field.PERMILLE) { jdkAttribute = java.text.NumberFormat.Field.PERMILLE; } else if (icuAttribute == NumberFormat.Field.SIGN) { jdkAttribute = java.text.NumberFormat.Field.SIGN; } return jdkAttribute; } }