1// © 2017 and later: Unicode, Inc. and others. 2// License & terms of use: http://www.unicode.org/copyright.html#License 3package com.ibm.icu.number; 4 5import java.io.IOException; 6import java.math.BigDecimal; 7import java.text.AttributedCharacterIterator; 8import java.text.FieldPosition; 9import java.util.Arrays; 10 11import com.ibm.icu.impl.number.DecimalQuantity; 12import com.ibm.icu.impl.number.MicroProps; 13import com.ibm.icu.impl.number.NumberStringBuilder; 14import com.ibm.icu.text.PluralRules.IFixedDecimal; 15import com.ibm.icu.util.ICUUncheckedIOException; 16 17/** 18 * The result of a number formatting operation. This class allows the result to be exported in several data types, 19 * including a String, an AttributedCharacterIterator, and a BigDecimal. 20 * 21 * @draft ICU 60 22 * @provisional This API might change or be removed in a future release. 23 * @see NumberFormatter 24 */ 25public class FormattedNumber { 26 NumberStringBuilder nsb; 27 DecimalQuantity fq; 28 MicroProps micros; 29 30 FormattedNumber(NumberStringBuilder nsb, DecimalQuantity fq, MicroProps micros) { 31 this.nsb = nsb; 32 this.fq = fq; 33 this.micros = micros; 34 } 35 36 /** 37 * Creates a String representation of the the formatted number. 38 * 39 * @return a String containing the localized number. 40 * @draft ICU 60 41 * @provisional This API might change or be removed in a future release. 42 * @see NumberFormatter 43 */ 44 @Override 45 public String toString() { 46 return nsb.toString(); 47 } 48 49 /** 50 * Append the formatted number to an Appendable, such as a StringBuilder. This may be slightly more efficient than 51 * creating a String. 52 * 53 * <p> 54 * If an IOException occurs when appending to the Appendable, an unchecked {@link ICUUncheckedIOException} is thrown 55 * instead. 56 * 57 * @param appendable 58 * The Appendable to which to append the formatted number string. 59 * @return The same Appendable, for chaining. 60 * @draft ICU 60 61 * @provisional This API might change or be removed in a future release. 62 * @see Appendable 63 * @see NumberFormatter 64 */ 65 public <A extends Appendable> A appendTo(A appendable) { 66 try { 67 appendable.append(nsb); 68 } catch (IOException e) { 69 // Throw as an unchecked exception to avoid users needing try/catch 70 throw new ICUUncheckedIOException(e); 71 } 72 return appendable; 73 } 74 75 /** 76 * Determine the start and end indices of the first occurrence of the given <em>field</em> in the output string. 77 * This allows you to determine the locations of the integer part, fraction part, and sign. 78 * 79 * <p> 80 * If multiple different field attributes are needed, this method can be called repeatedly, or if <em>all</em> field 81 * attributes are needed, consider using getFieldIterator(). 82 * 83 * <p> 84 * If a field occurs multiple times in an output string, such as a grouping separator, this method will only ever 85 * return the first occurrence. Use getFieldIterator() to access all occurrences of an attribute. 86 * 87 * @param fieldPosition 88 * The FieldPosition to populate with the start and end indices of the desired field. 89 * @draft ICU 60 90 * @provisional This API might change or be removed in a future release. 91 * @see com.ibm.icu.text.NumberFormat.Field 92 * @see NumberFormatter 93 */ 94 public void populateFieldPosition(FieldPosition fieldPosition) { 95 populateFieldPosition(fieldPosition, 0); 96 } 97 98 /** 99 * @internal 100 * @deprecated This API is ICU internal only. 101 */ 102 @Deprecated 103 public void populateFieldPosition(FieldPosition fieldPosition, int offset) { 104 nsb.populateFieldPosition(fieldPosition, offset); 105 fq.populateUFieldPosition(fieldPosition); 106 } 107 108 /** 109 * Export the formatted number as an AttributedCharacterIterator. This allows you to determine which characters in 110 * the output string correspond to which <em>fields</em>, such as the integer part, fraction part, and sign. 111 * 112 * <p> 113 * If information on only one field is needed, consider using populateFieldPosition() instead. 114 * 115 * @return An AttributedCharacterIterator, containing information on the field attributes of the number string. 116 * @draft ICU 60 117 * @provisional This API might change or be removed in a future release. 118 * @see com.ibm.icu.text.NumberFormat.Field 119 * @see AttributedCharacterIterator 120 * @see NumberFormatter 121 */ 122 public AttributedCharacterIterator getFieldIterator() { 123 return nsb.getIterator(); 124 } 125 126 /** 127 * Export the formatted number as a BigDecimal. This endpoint is useful for obtaining the exact number being printed 128 * after scaling and rounding have been applied by the number formatting pipeline. 129 * 130 * @return A BigDecimal representation of the formatted number. 131 * @draft ICU 60 132 * @provisional This API might change or be removed in a future release. 133 * @see NumberFormatter 134 */ 135 public BigDecimal toBigDecimal() { 136 return fq.toBigDecimal(); 137 } 138 139 /** 140 * @internal 141 * @deprecated This API is ICU internal only. 142 */ 143 @Deprecated 144 public String getPrefix() { 145 NumberStringBuilder temp = new NumberStringBuilder(); 146 int length = micros.modOuter.apply(temp, 0, 0); 147 length += micros.modMiddle.apply(temp, 0, length); 148 /* length += */ micros.modInner.apply(temp, 0, length); 149 int prefixLength = micros.modOuter.getPrefixLength() + micros.modMiddle.getPrefixLength() 150 + micros.modInner.getPrefixLength(); 151 return temp.subSequence(0, prefixLength).toString(); 152 } 153 154 /** 155 * @internal 156 * @deprecated This API is ICU internal only. 157 */ 158 @Deprecated 159 public String getSuffix() { 160 NumberStringBuilder temp = new NumberStringBuilder(); 161 int length = micros.modOuter.apply(temp, 0, 0); 162 length += micros.modMiddle.apply(temp, 0, length); 163 length += micros.modInner.apply(temp, 0, length); 164 int prefixLength = micros.modOuter.getPrefixLength() + micros.modMiddle.getPrefixLength() 165 + micros.modInner.getPrefixLength(); 166 return temp.subSequence(prefixLength, length).toString(); 167 } 168 169 /** 170 * @internal 171 * @deprecated This API is ICU internal only. 172 */ 173 @Deprecated 174 public IFixedDecimal getFixedDecimal() { 175 return fq; 176 } 177 178 /** 179 * {@inheritDoc} 180 * 181 * @draft ICU 60 182 * @provisional This API might change or be removed in a future release. 183 */ 184 @Override 185 public int hashCode() { 186 // NumberStringBuilder and BigDecimal are mutable, so we can't call 187 // #equals() or #hashCode() on them directly. 188 return Arrays.hashCode(nsb.toCharArray()) ^ Arrays.hashCode(nsb.toFieldArray()) ^ fq.toBigDecimal().hashCode(); 189 } 190 191 /** 192 * {@inheritDoc} 193 * 194 * @draft ICU 60 195 * @provisional This API might change or be removed in a future release. 196 */ 197 @Override 198 public boolean equals(Object other) { 199 if (this == other) 200 return true; 201 if (other == null) 202 return false; 203 if (!(other instanceof FormattedNumber)) 204 return false; 205 // NumberStringBuilder and BigDecimal are mutable, so we can't call 206 // #equals() or #hashCode() on them directly. 207 FormattedNumber _other = (FormattedNumber) other; 208 return Arrays.equals(nsb.toCharArray(), _other.nsb.toCharArray()) 209 ^ Arrays.equals(nsb.toFieldArray(), _other.nsb.toFieldArray()) 210 ^ fq.toBigDecimal().equals(_other.fq.toBigDecimal()); 211 } 212}