blob: 918e5e172df15b64d704fb0bb5f3ecacd12b086f [file] [log] [blame]
Raymonddee08492015-04-02 10:43:13 -07001/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package org.apache.commons.math.fraction;
19
20import java.io.Serializable;
21import java.math.BigInteger;
22import java.text.FieldPosition;
23import java.text.NumberFormat;
24import java.text.ParseException;
25import java.text.ParsePosition;
26import java.util.Locale;
27
28import org.apache.commons.math.MathRuntimeException;
29import org.apache.commons.math.exception.util.LocalizedFormats;
30
31/**
32 * Formats a BigFraction number in proper format or improper format.
33 * <p>
34 * The number format for each of the whole number, numerator and,
35 * denominator can be configured.
36 * </p>
37 *
38 * @since 2.0
39 * @version $Revision: 983921 $ $Date: 2010-08-10 12:46:06 +0200 (mar. 10 août 2010) $
40 */
41public class BigFractionFormat extends AbstractFormat implements Serializable {
42
43 /** Serializable version identifier */
44 private static final long serialVersionUID = -2932167925527338976L;
45
46 /**
47 * Create an improper formatting instance with the default number format
48 * for the numerator and denominator.
49 */
50 public BigFractionFormat() {
51 }
52
53 /**
54 * Create an improper formatting instance with a custom number format for
55 * both the numerator and denominator.
56 * @param format the custom format for both the numerator and denominator.
57 */
58 public BigFractionFormat(final NumberFormat format) {
59 super(format);
60 }
61
62 /**
63 * Create an improper formatting instance with a custom number format for
64 * the numerator and a custom number format for the denominator.
65 * @param numeratorFormat the custom format for the numerator.
66 * @param denominatorFormat the custom format for the denominator.
67 */
68 public BigFractionFormat(final NumberFormat numeratorFormat,
69 final NumberFormat denominatorFormat) {
70 super(numeratorFormat, denominatorFormat);
71 }
72
73 /**
74 * Get the set of locales for which complex formats are available. This
75 * is the same set as the {@link NumberFormat} set.
76 * @return available complex format locales.
77 */
78 public static Locale[] getAvailableLocales() {
79 return NumberFormat.getAvailableLocales();
80 }
81
82 /**
83 * This static method calls formatBigFraction() on a default instance of
84 * BigFractionFormat.
85 *
86 * @param f BigFraction object to format
87 * @return A formatted BigFraction in proper form.
88 */
89 public static String formatBigFraction(final BigFraction f) {
90 return getImproperInstance().format(f);
91 }
92
93 /**
94 * Returns the default complex format for the current locale.
95 * @return the default complex format.
96 */
97 public static BigFractionFormat getImproperInstance() {
98 return getImproperInstance(Locale.getDefault());
99 }
100
101 /**
102 * Returns the default complex format for the given locale.
103 * @param locale the specific locale used by the format.
104 * @return the complex format specific to the given locale.
105 */
106 public static BigFractionFormat getImproperInstance(final Locale locale) {
107 return new BigFractionFormat(getDefaultNumberFormat(locale));
108 }
109
110 /**
111 * Returns the default complex format for the current locale.
112 * @return the default complex format.
113 */
114 public static BigFractionFormat getProperInstance() {
115 return getProperInstance(Locale.getDefault());
116 }
117
118 /**
119 * Returns the default complex format for the given locale.
120 * @param locale the specific locale used by the format.
121 * @return the complex format specific to the given locale.
122 */
123 public static BigFractionFormat getProperInstance(final Locale locale) {
124 return new ProperBigFractionFormat(getDefaultNumberFormat(locale));
125 }
126
127 /**
128 * Formats a {@link BigFraction} object to produce a string. The BigFraction is
129 * output in improper format.
130 *
131 * @param BigFraction the object to format.
132 * @param toAppendTo where the text is to be appended
133 * @param pos On input: an alignment field, if desired. On output: the
134 * offsets of the alignment field
135 * @return the value passed in as toAppendTo.
136 */
137 public StringBuffer format(final BigFraction BigFraction,
138 final StringBuffer toAppendTo, final FieldPosition pos) {
139
140 pos.setBeginIndex(0);
141 pos.setEndIndex(0);
142
143 getNumeratorFormat().format(BigFraction.getNumerator(), toAppendTo, pos);
144 toAppendTo.append(" / ");
145 getDenominatorFormat().format(BigFraction.getDenominator(), toAppendTo, pos);
146
147 return toAppendTo;
148 }
149
150 /**
151 * Formats an object and appends the result to a StringBuffer.
152 * <code>obj</code> must be either a {@link BigFraction} object or a
153 * {@link BigInteger} object or a {@link Number} object. Any other type of
154 * object will result in an {@link IllegalArgumentException} being thrown.
155 *
156 * @param obj the object to format.
157 * @param toAppendTo where the text is to be appended
158 * @param pos On input: an alignment field, if desired. On output: the
159 * offsets of the alignment field
160 * @return the value passed in as toAppendTo.
161 * @see java.text.Format#format(java.lang.Object, java.lang.StringBuffer, java.text.FieldPosition)
162 * @throws IllegalArgumentException is <code>obj</code> is not a valid type.
163 */
164 @Override
165 public StringBuffer format(final Object obj,
166 final StringBuffer toAppendTo, final FieldPosition pos) {
167
168 final StringBuffer ret;
169 if (obj instanceof BigFraction) {
170 ret = format((BigFraction) obj, toAppendTo, pos);
171 } else if (obj instanceof BigInteger) {
172 ret = format(new BigFraction((BigInteger) obj), toAppendTo, pos);
173 } else if (obj instanceof Number) {
174 ret = format(new BigFraction(((Number) obj).doubleValue()),
175 toAppendTo, pos);
176 } else {
177 throw MathRuntimeException.createIllegalArgumentException(
178 LocalizedFormats.CANNOT_FORMAT_OBJECT_TO_FRACTION);
179 }
180
181 return ret;
182 }
183
184 /**
185 * Parses a string to produce a {@link BigFraction} object.
186 * @param source the string to parse
187 * @return the parsed {@link BigFraction} object.
188 * @exception ParseException if the beginning of the specified string
189 * cannot be parsed.
190 */
191 @Override
192 public BigFraction parse(final String source) throws ParseException {
193 final ParsePosition parsePosition = new ParsePosition(0);
194 final BigFraction result = parse(source, parsePosition);
195 if (parsePosition.getIndex() == 0) {
196 throw MathRuntimeException.createParseException(
197 parsePosition.getErrorIndex(),
198 LocalizedFormats.UNPARSEABLE_FRACTION_NUMBER, source);
199 }
200 return result;
201 }
202
203 /**
204 * Parses a string to produce a {@link BigFraction} object.
205 * This method expects the string to be formatted as an improper BigFraction.
206 * @param source the string to parse
207 * @param pos input/ouput parsing parameter.
208 * @return the parsed {@link BigFraction} object.
209 */
210 @Override
211 public BigFraction parse(final String source, final ParsePosition pos) {
212 final int initialIndex = pos.getIndex();
213
214 // parse whitespace
215 parseAndIgnoreWhitespace(source, pos);
216
217 // parse numerator
218 final BigInteger num = parseNextBigInteger(source, pos);
219 if (num == null) {
220 // invalid integer number
221 // set index back to initial, error index should already be set
222 // character examined.
223 pos.setIndex(initialIndex);
224 return null;
225 }
226
227 // parse '/'
228 final int startIndex = pos.getIndex();
229 final char c = parseNextCharacter(source, pos);
230 switch (c) {
231 case 0 :
232 // no '/'
233 // return num as a BigFraction
234 return new BigFraction(num);
235 case '/' :
236 // found '/', continue parsing denominator
237 break;
238 default :
239 // invalid '/'
240 // set index back to initial, error index should be the last
241 // character examined.
242 pos.setIndex(initialIndex);
243 pos.setErrorIndex(startIndex);
244 return null;
245 }
246
247 // parse whitespace
248 parseAndIgnoreWhitespace(source, pos);
249
250 // parse denominator
251 final BigInteger den = parseNextBigInteger(source, pos);
252 if (den == null) {
253 // invalid integer number
254 // set index back to initial, error index should already be set
255 // character examined.
256 pos.setIndex(initialIndex);
257 return null;
258 }
259
260 return new BigFraction(num, den);
261 }
262
263 /**
264 * Parses a string to produce a <code>BigInteger</code>.
265 * @param source the string to parse
266 * @param pos input/ouput parsing parameter.
267 * @return a parsed <code>BigInteger</code> or null if string does not
268 * contain a BigInteger at the specified position
269 */
270 protected BigInteger parseNextBigInteger(final String source,
271 final ParsePosition pos) {
272
273 final int start = pos.getIndex();
274 int end = (source.charAt(start) == '-') ? (start + 1) : start;
275 while((end < source.length()) &&
276 Character.isDigit(source.charAt(end))) {
277 ++end;
278 }
279
280 try {
281 BigInteger n = new BigInteger(source.substring(start, end));
282 pos.setIndex(end);
283 return n;
284 } catch (NumberFormatException nfe) {
285 pos.setErrorIndex(start);
286 return null;
287 }
288
289 }
290
291}