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