Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||||||
ProperFractionFormat |
|
| 3.142857142857143;3.143 |
1 | /* |
|
2 | * Copyright 2005 The Apache Software Foundation. |
|
3 | * |
|
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
|
5 | * you may not use this file except in compliance with the License. |
|
6 | * You may obtain a copy of the License at |
|
7 | * |
|
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
|
9 | * |
|
10 | * Unless required by applicable law or agreed to in writing, software |
|
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
|
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
13 | * See the License for the specific language governing permissions and |
|
14 | * limitations under the License. |
|
15 | */ |
|
16 | package org.apache.commons.math.fraction; |
|
17 | ||
18 | import java.text.FieldPosition; |
|
19 | import java.text.NumberFormat; |
|
20 | import java.text.ParsePosition; |
|
21 | ||
22 | import org.apache.commons.math.util.MathUtils; |
|
23 | ||
24 | /** |
|
25 | * Formats a Fraction number in proper format. The number format for each of |
|
26 | * the whole number, numerator and, denominator can be configured. |
|
27 | * |
|
28 | * @since 1.1 |
|
29 | * @version $Revision$ $Date: 2005-05-21 22:25:44 -0700 (Sat, 21 May 2005) $ |
|
30 | */ |
|
31 | public class ProperFractionFormat extends FractionFormat { |
|
32 | ||
33 | /** Serializable version identifier */ |
|
34 | static final long serialVersionUID = -6337346779577272307L; |
|
35 | ||
36 | /** The format used for the whole number. */ |
|
37 | private NumberFormat wholeFormat; |
|
38 | ||
39 | /** |
|
40 | * Create a proper formatting instance with the default number format for |
|
41 | * the whole, numerator, and denominator. |
|
42 | */ |
|
43 | public ProperFractionFormat() { |
|
44 | 0 | this(getDefaultNumberFormat()); |
45 | 0 | } |
46 | ||
47 | /** |
|
48 | * Create a proper formatting instance with a custom number format for the |
|
49 | * whole, numerator, and denominator. |
|
50 | * @param format the custom format for the whole, numerator, and |
|
51 | * denominator. |
|
52 | */ |
|
53 | public ProperFractionFormat(NumberFormat format) { |
|
54 | 30 | this(format, (NumberFormat)format.clone(), (NumberFormat)format.clone()); |
55 | 30 | } |
56 | ||
57 | /** |
|
58 | * Create a proper formatting instance with a custom number format for each |
|
59 | * of the whole, numerator, and denominator. |
|
60 | * @param wholeFormat the custom format for the whole. |
|
61 | * @param numeratorFormat the custom format for the numerator. |
|
62 | * @param denominatorFormat the custom format for the denominator. |
|
63 | */ |
|
64 | public ProperFractionFormat(NumberFormat wholeFormat, |
|
65 | NumberFormat numeratorFormat, |
|
66 | NumberFormat denominatorFormat) |
|
67 | { |
|
68 | 30 | super(numeratorFormat, denominatorFormat); |
69 | 30 | setWholeFormat(wholeFormat); |
70 | 30 | } |
71 | ||
72 | /** |
|
73 | * Formats a {@link Fraction} object to produce a string. The fraction |
|
74 | * is output in proper format. |
|
75 | * |
|
76 | * @param fraction the object to format. |
|
77 | * @param toAppendTo where the text is to be appended |
|
78 | * @param pos On input: an alignment field, if desired. On output: the |
|
79 | * offsets of the alignment field |
|
80 | * @return the value passed in as toAppendTo. |
|
81 | */ |
|
82 | public StringBuffer format(Fraction fraction, StringBuffer toAppendTo, |
|
83 | FieldPosition pos) { |
|
84 | ||
85 | 10 | pos.setBeginIndex(0); |
86 | 10 | pos.setEndIndex(0); |
87 | ||
88 | 10 | int num = fraction.getNumerator(); |
89 | 10 | int den = fraction.getDenominator(); |
90 | 10 | int whole = num / den; |
91 | 10 | num = num % den; |
92 | ||
93 | 10 | if (whole != 0) { |
94 | 4 | getWholeFormat().format(whole, toAppendTo, pos); |
95 | 4 | toAppendTo.append(' '); |
96 | 4 | num = Math.abs(num); |
97 | } |
|
98 | 10 | getNumeratorFormat().format(num, toAppendTo, pos); |
99 | 10 | toAppendTo.append(" / "); |
100 | 10 | getDenominatorFormat().format(den, toAppendTo, |
101 | pos); |
|
102 | ||
103 | 10 | return toAppendTo; |
104 | } |
|
105 | ||
106 | /** |
|
107 | * Access the whole format. |
|
108 | * @return the whole format. |
|
109 | */ |
|
110 | public NumberFormat getWholeFormat() { |
|
111 | 16 | return wholeFormat; |
112 | } |
|
113 | ||
114 | /** |
|
115 | * Parses a string to produce a {@link Fraction} object. This method |
|
116 | * expects the string to be formatted as a proper fraction. |
|
117 | * @param source the string to parse |
|
118 | * @param pos input/ouput parsing parameter. |
|
119 | * @return the parsed {@link Fraction} object. |
|
120 | */ |
|
121 | public Fraction parse(String source, ParsePosition pos) { |
|
122 | // try to parse improper fraction |
|
123 | 16 | Fraction ret = super.parse(source, pos); |
124 | 16 | if (ret != null) { |
125 | 8 | return ret; |
126 | } |
|
127 | ||
128 | 8 | int initialIndex = pos.getIndex(); |
129 | ||
130 | // parse whitespace |
|
131 | 8 | parseAndIgnoreWhitespace(source, pos); |
132 | ||
133 | // parse whole |
|
134 | 8 | Number whole = getWholeFormat().parse(source, pos); |
135 | 8 | if (whole == null) { |
136 | // invalid integer number |
|
137 | // set index back to initial, error index should already be set |
|
138 | // character examined. |
|
139 | 2 | pos.setIndex(initialIndex); |
140 | 2 | return null; |
141 | } |
|
142 | ||
143 | // parse whitespace |
|
144 | 6 | parseAndIgnoreWhitespace(source, pos); |
145 | ||
146 | // parse numerator |
|
147 | 6 | Number num = getNumeratorFormat().parse(source, pos); |
148 | 6 | if (num == null) { |
149 | // invalid integer number |
|
150 | // set index back to initial, error index should already be set |
|
151 | // character examined. |
|
152 | 2 | pos.setIndex(initialIndex); |
153 | 2 | return null; |
154 | } |
|
155 | ||
156 | // parse '/' |
|
157 | 4 | int startIndex = pos.getIndex(); |
158 | 4 | char c = parseNextCharacter(source, pos); |
159 | 4 | switch (c) { |
160 | case 0 : |
|
161 | // no '/' |
|
162 | // return num as a fraction |
|
163 | 0 | return new Fraction(num.intValue(), 1); |
164 | case '/' : |
|
165 | // found '/', continue parsing denominator |
|
166 | 4 | break; |
167 | default : |
|
168 | // invalid '/' |
|
169 | // set index back to initial, error index should be the last |
|
170 | // character examined. |
|
171 | 0 | pos.setIndex(initialIndex); |
172 | 0 | pos.setErrorIndex(startIndex); |
173 | 0 | return null; |
174 | } |
|
175 | ||
176 | // parse whitespace |
|
177 | 4 | parseAndIgnoreWhitespace(source, pos); |
178 | ||
179 | // parse denominator |
|
180 | 4 | Number den = getDenominatorFormat().parse(source, pos); |
181 | 4 | if (den == null) { |
182 | // invalid integer number |
|
183 | // set index back to initial, error index should already be set |
|
184 | // character examined. |
|
185 | 0 | pos.setIndex(initialIndex); |
186 | 0 | return null; |
187 | } |
|
188 | ||
189 | 4 | int w = whole.intValue(); |
190 | 4 | int n = num.intValue(); |
191 | 4 | int d = den.intValue(); |
192 | 4 | return new Fraction(((Math.abs(w) * d) + n) * MathUtils.sign(w), d); |
193 | } |
|
194 | ||
195 | /** |
|
196 | * Modify the whole format. |
|
197 | * @param format The new whole format value. |
|
198 | * @throws IllegalArgumentException if <code>format</code> is |
|
199 | * <code>null</code>. |
|
200 | */ |
|
201 | public void setWholeFormat(NumberFormat format) { |
|
202 | 34 | if (format == null) { |
203 | 0 | throw new IllegalArgumentException( |
204 | "whole format can not be null."); |
|
205 | } |
|
206 | 34 | this.wholeFormat = format; |
207 | 34 | } |
208 | } |