@Override
  public AttributedCharacterIterator formatToCharacterIterator(Object object) {
    if (!(object instanceof Number)) {
      throw new IllegalArgumentException();
    }
    Number number = (Number) object;
    String text = null;
    StringBuffer attributes = new StringBuffer();

    if (number instanceof BigInteger) {
      BigInteger valBigInteger = (BigInteger) number;
      if (valBigInteger.compareTo(new BigInteger(String.valueOf(Long.MAX_VALUE))) > 0) {
        throw (new UnsupportedOperationException(
            "Number too big. BigInteger > Long.MAX_VALUE not yet supported."));
      }
      text =
          NativeDecimalFormat.format(this.addr, valBigInteger.longValue(), null, null, attributes);
    } else if (number instanceof BigDecimal) {
      BigDecimal valBigDecimal = (BigDecimal) number;
      if (valBigDecimal.compareTo(new BigDecimal(String.valueOf(Double.MAX_VALUE))) > 0) {
        throw (new UnsupportedOperationException(
            "Number too big. BigDecimal > Double.MAX_VALUE not yet supported."));
      }
      text =
          NativeDecimalFormat.format(
              this.addr, valBigDecimal.doubleValue(), null, null, attributes);
    } else {
      double dv = number.doubleValue();
      long lv = number.longValue();
      if (dv == lv) {
        text = NativeDecimalFormat.format(this.addr, lv, null, null, attributes);
      } else {
        text = NativeDecimalFormat.format(this.addr, dv, null, null, attributes);
      }
    }

    AttributedString as = new AttributedString(text.toString());

    String[] attrs = attributes.toString().split(";");
    // add NumberFormat field attributes to the AttributedString
    int size = attrs.length / 3;
    if (size * 3 != attrs.length) {
      return as.getIterator();
    }
    for (int i = 0; i < size; i++) {
      Format.Field attribute = getField(attrs[3 * i]);
      as.addAttribute(
          attribute,
          attribute,
          Integer.parseInt(attrs[3 * i + 1]),
          Integer.parseInt(attrs[3 * i + 2]));
    }

    // return the CharacterIterator from AttributedString
    return as.getIterator();
  }
  @Override
  public StringBuffer format(Object value, StringBuffer buffer, FieldPosition field) {

    if (!(value instanceof Number)) {
      throw new IllegalArgumentException();
    }
    if (buffer == null || field == null) {
      throw new NullPointerException();
    }

    String fieldType = null;
    if (field != null) {
      fieldType = getFieldType(field.getFieldAttribute());
    }

    Number number = (Number) value;

    if (number instanceof BigInteger) {
      BigInteger valBigInteger = (BigInteger) number;
      String result =
          NativeDecimalFormat.format(
              this.addr, valBigInteger.toString(10), field, fieldType, null, 0);
      return buffer.append(result);
    } else if (number instanceof BigDecimal) {
      BigDecimal valBigDecimal = (BigDecimal) number;
      String result =
          NativeDecimalFormat.format(
              this.addr,
              valBigDecimal.unscaledValue().toString(10),
              field,
              fieldType,
              null,
              valBigDecimal.scale());
      return buffer.append(result);
    } else {
      double dv = number.doubleValue();
      long lv = number.longValue();
      if (dv == lv) {
        String result = NativeDecimalFormat.format(this.addr, lv, field, fieldType, null);
        return buffer.append(result);
      }
      String result = NativeDecimalFormat.format(this.addr, dv, field, fieldType, null);
      return buffer.append(result);
    }
  }
 public void applyPattern(String pattern) {
   if (pattern == null) {
     throw new NullPointerException("pattern was null");
   }
   try {
     NativeDecimalFormat.applyPatternImpl(this.addr, false, pattern);
   } catch (RuntimeException re) {
     throw new IllegalArgumentException("applying pattern failed for pattern: " + pattern, re);
   }
 }
  @Override
  public StringBuffer format(double value, StringBuffer buffer, FieldPosition field) {

    if (buffer == null) {
      throw new NullPointerException();
    }

    String fieldType = null;

    if (field != null) {
      fieldType = getFieldType(field.getFieldAttribute());
    }

    String result = NativeDecimalFormat.format(this.addr, value, field, fieldType, null);

    buffer.append(result.toCharArray(), 0, result.length());

    return buffer;
  }
 @Override
 public boolean isParseIntegerOnly() {
   return NativeDecimalFormat.getAttribute(
           this.addr, UNumberFormatAttribute.UNUM_PARSE_INT_ONLY.ordinal())
       != 0;
 }
 public boolean isDecimalSeparatorAlwaysShown() {
   return NativeDecimalFormat.getAttribute(
           this.addr, UNumberFormatAttribute.UNUM_DECIMAL_ALWAYS_SHOWN.ordinal())
       != 0;
 }
 public void setPositiveSuffix(String value) {
   NativeDecimalFormat.setTextAttribute(
       this.addr, UNumberFormatTextAttribute.UNUM_POSITIVE_SUFFIX.ordinal(), value);
 }
 public void setMultiplier(int value) {
   NativeDecimalFormat.setAttribute(
       this.addr, UNumberFormatAttribute.UNUM_MULTIPLIER.ordinal(), value);
 }
 @Override
 public void setMinimumFractionDigits(int value) {
   NativeDecimalFormat.setAttribute(
       this.addr, UNumberFormatAttribute.UNUM_MIN_FRACTION_DIGITS.ordinal(), value);
 }
 public void setGroupingSize(int value) {
   NativeDecimalFormat.setAttribute(
       this.addr, UNumberFormatAttribute.UNUM_GROUPING_SIZE.ordinal(), value);
 }
 @Override
 public int getMinimumFractionDigits() {
   return NativeDecimalFormat.getAttribute(
       this.addr, UNumberFormatAttribute.UNUM_MIN_FRACTION_DIGITS.ordinal());
 }
 @Override
 public Number parse(String string, ParsePosition position) {
   return NativeDecimalFormat.parse(addr, string, position);
 }
 public String toPattern() {
   return NativeDecimalFormat.toPatternImpl(this.addr, false);
 }
 public String toLocalizedPattern() {
   return NativeDecimalFormat.toPatternImpl(this.addr, true);
 }
 @Override
 public boolean isGroupingUsed() {
   return NativeDecimalFormat.getAttribute(
           this.addr, UNumberFormatAttribute.UNUM_GROUPING_USED.ordinal())
       != 0;
 }
 public void setDecimalSeparatorAlwaysShown(boolean value) {
   int i = value ? -1 : 0;
   NativeDecimalFormat.setAttribute(
       this.addr, UNumberFormatAttribute.UNUM_DECIMAL_ALWAYS_SHOWN.ordinal(), i);
 }
 @Override
 public int getMinimumIntegerDigits() {
   return NativeDecimalFormat.getAttribute(
       this.addr, UNumberFormatAttribute.UNUM_MIN_INTEGER_DIGITS.ordinal());
 }
 @Override
 public void setGroupingUsed(boolean value) {
   int i = value ? -1 : 0;
   NativeDecimalFormat.setAttribute(
       this.addr, UNumberFormatAttribute.UNUM_GROUPING_USED.ordinal(), i);
 }
 public int getGroupingSize() {
   return NativeDecimalFormat.getAttribute(
       this.addr, UNumberFormatAttribute.UNUM_GROUPING_SIZE.ordinal());
 }
 @Override
 public void setMinimumIntegerDigits(int value) {
   NativeDecimalFormat.setAttribute(
       this.addr, UNumberFormatAttribute.UNUM_MIN_INTEGER_DIGITS.ordinal(), value);
 }
 public int getMultiplier() {
   return NativeDecimalFormat.getAttribute(
       this.addr, UNumberFormatAttribute.UNUM_MULTIPLIER.ordinal());
 }
 public void setNegativePrefix(String value) {
   NativeDecimalFormat.setTextAttribute(
       this.addr, UNumberFormatTextAttribute.UNUM_NEGATIVE_PREFIX.ordinal(), value);
 }
 public String getNegativePrefix() {
   return NativeDecimalFormat.getTextAttribute(
       this.addr, UNumberFormatTextAttribute.UNUM_NEGATIVE_PREFIX.ordinal());
 }
 @Override
 public void setParseIntegerOnly(boolean value) {
   int i = value ? -1 : 0;
   NativeDecimalFormat.setAttribute(
       this.addr, UNumberFormatAttribute.UNUM_PARSE_INT_ONLY.ordinal(), i);
 }
 public String getPositiveSuffix() {
   return NativeDecimalFormat.getTextAttribute(
       this.addr, UNumberFormatTextAttribute.UNUM_POSITIVE_SUFFIX.ordinal());
 }