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