View Javadoc

1   /*
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  
18  package org.apache.commons.math.fraction;
19  
20  import java.io.Serializable;
21  import java.text.FieldPosition;
22  import java.text.NumberFormat;
23  import java.text.ParsePosition;
24  import java.util.Locale;
25  
26  import org.apache.commons.math.MathRuntimeException;
27  
28  /**
29   * Common part shared by both {@link FractionFormat} and {@link BigFractionFormat}.
30   * @version $Revision: 780674 $ $Date: 2009-06-01 11:10:55 -0400 (Mon, 01 Jun 2009) $
31   * @since 2.0
32   */
33  public abstract class AbstractFormat extends NumberFormat implements Serializable {
34  
35      /** Serializable version identifier. */
36      private static final long serialVersionUID = -6981118387974191891L;
37  
38      /** The format used for the denominator. */
39      protected NumberFormat denominatorFormat;
40  
41      /** The format used for the numerator. */
42      protected NumberFormat numeratorFormat;
43  
44      /**
45       * Create an improper formatting instance with the default number format
46       * for the numerator and denominator.  
47       */
48      protected AbstractFormat() {
49          this(getDefaultNumberFormat());
50      }
51  
52      /**
53       * Create an improper formatting instance with a custom number format for
54       * both the numerator and denominator.
55       * @param format the custom format for both the numerator and denominator.
56       */
57      protected AbstractFormat(final NumberFormat format) {
58          this(format, (NumberFormat) format.clone());
59      }
60  
61      /**
62       * Create an improper formatting instance with a custom number format for
63       * the numerator and a custom number format for the denominator.
64       * @param numeratorFormat the custom format for the numerator.
65       * @param denominatorFormat the custom format for the denominator.
66       */
67      protected AbstractFormat(final NumberFormat numeratorFormat,
68                               final NumberFormat denominatorFormat) {
69          this.numeratorFormat   = numeratorFormat;
70          this.denominatorFormat = denominatorFormat;
71      }
72  
73      /**
74       * Create a default number format.  The default number format is based on
75       * {@link NumberFormat#getNumberInstance(java.util.Locale)} with the only
76       * customizing is the maximum number of BigFraction digits, which is set to 0.  
77       * @return the default number format.
78       */
79      protected static NumberFormat getDefaultNumberFormat() {
80          return getDefaultNumberFormat(Locale.getDefault());
81      }
82  
83      /**
84       * Create a default number format.  The default number format is based on
85       * {@link NumberFormat#getNumberInstance(java.util.Locale)} with the only
86       * customizing is the maximum number of BigFraction digits, which is set to 0.  
87       * @param locale the specific locale used by the format.
88       * @return the default number format specific to the given locale.
89       */
90      protected static NumberFormat getDefaultNumberFormat(final Locale locale) {
91          final NumberFormat nf = NumberFormat.getNumberInstance(locale);
92          nf.setMaximumFractionDigits(0);
93          nf.setParseIntegerOnly(true);
94          return nf;
95      }
96  
97      /**
98       * Access the denominator format.
99       * @return the denominator format.
100      */
101     public NumberFormat getDenominatorFormat() {
102         return denominatorFormat;
103     }
104 
105     /**
106      * Access the numerator format.
107      * @return the numerator format.
108      */
109     public NumberFormat getNumeratorFormat() {
110         return numeratorFormat;
111     }
112 
113     /**
114      * Modify the denominator format.
115      * @param format the new denominator format value.
116      * @throws IllegalArgumentException if <code>format</code> is
117      *         <code>null</code>.
118      */
119     public void setDenominatorFormat(final NumberFormat format) {
120         if (format == null) {
121             throw MathRuntimeException.createIllegalArgumentException(
122                 "denominator format can not be null");
123         }
124         this.denominatorFormat = format;
125     }
126 
127     /**
128      * Modify the numerator format.
129      * @param format the new numerator format value.
130      * @throws IllegalArgumentException if <code>format</code> is
131      *         <code>null</code>.
132      */
133     public void setNumeratorFormat(final NumberFormat format) {
134         if (format == null) {
135             throw MathRuntimeException.createIllegalArgumentException(
136                 "numerator format can not be null");
137         }
138         this.numeratorFormat = format;
139     }
140 
141     /**
142      * Parses <code>source</code> until a non-whitespace character is found.
143      * @param source the string to parse
144      * @param pos input/ouput parsing parameter.  On output, <code>pos</code>
145      *        holds the index of the next non-whitespace character.
146      */
147     protected static void parseAndIgnoreWhitespace(final String source,
148                                                    final ParsePosition pos) {
149         parseNextCharacter(source, pos);
150         pos.setIndex(pos.getIndex() - 1);
151     }
152 
153     /**
154      * Parses <code>source</code> until a non-whitespace character is found.
155      * @param source the string to parse
156      * @param pos input/ouput parsing parameter.
157      * @return the first non-whitespace character.
158      */
159     protected static char parseNextCharacter(final String source,
160                                              final ParsePosition pos) {
161          int index = pos.getIndex();
162          final int n = source.length();
163          char ret = 0;
164 
165          if (index < n) {
166              char c;
167              do {
168                  c = source.charAt(index++);
169              } while (Character.isWhitespace(c) && index < n);
170              pos.setIndex(index);
171          
172              if (index < n) {
173                  ret = c;
174              }
175          }
176          
177          return ret;
178     }
179 
180     /**
181      * Formats a double value as a fraction and appends the result to a StringBuffer. 
182      *
183      * @param value the double value to format
184      * @param buffer StringBuffer to append to
185      * @param position On input: an alignment field, if desired. On output: the
186      *            offsets of the alignment field
187      * @return a reference to the appended buffer
188      * @see #format(Object, StringBuffer, FieldPosition)
189      */
190     @Override
191     public StringBuffer format(final double value,
192                                final StringBuffer buffer, final FieldPosition position) {
193         return format(Double.valueOf(value), buffer, position);
194     }
195 
196     
197     /**
198      * Formats a long value as a fraction and appends the result to a StringBuffer. 
199      *
200      * @param value the long value to format
201      * @param buffer StringBuffer to append to
202      * @param position On input: an alignment field, if desired. On output: the
203      *            offsets of the alignment field
204      * @return a reference to the appended buffer
205      * @see #format(Object, StringBuffer, FieldPosition)
206      */
207     @Override
208     public StringBuffer format(final long value,
209                                final StringBuffer buffer, final FieldPosition position) {
210         return format(Long.valueOf(value), buffer, position);
211     }
212 
213 }