001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018 package org.apache.commons.math.fraction; 019 020 import java.io.Serializable; 021 import java.text.FieldPosition; 022 import java.text.NumberFormat; 023 import java.text.ParsePosition; 024 import java.util.Locale; 025 026 import org.apache.commons.math.exception.NullArgumentException; 027 import org.apache.commons.math.exception.util.LocalizedFormats; 028 029 /** 030 * Common part shared by both {@link FractionFormat} and {@link BigFractionFormat}. 031 * @version $Revision: 983921 $ $Date: 2010-08-10 12:46:06 +0200 (mar. 10 ao??t 2010) $ 032 * @since 2.0 033 */ 034 public abstract class AbstractFormat extends NumberFormat implements Serializable { 035 036 /** Serializable version identifier. */ 037 private static final long serialVersionUID = -6981118387974191891L; 038 039 /** The format used for the denominator. */ 040 protected NumberFormat denominatorFormat; 041 042 /** The format used for the numerator. */ 043 protected NumberFormat numeratorFormat; 044 045 /** 046 * Create an improper formatting instance with the default number format 047 * for the numerator and denominator. 048 */ 049 protected AbstractFormat() { 050 this(getDefaultNumberFormat()); 051 } 052 053 /** 054 * Create an improper formatting instance with a custom number format for 055 * both the numerator and denominator. 056 * @param format the custom format for both the numerator and denominator. 057 */ 058 protected AbstractFormat(final NumberFormat format) { 059 this(format, (NumberFormat) format.clone()); 060 } 061 062 /** 063 * Create an improper formatting instance with a custom number format for 064 * the numerator and a custom number format for the denominator. 065 * @param numeratorFormat the custom format for the numerator. 066 * @param denominatorFormat the custom format for the denominator. 067 */ 068 protected AbstractFormat(final NumberFormat numeratorFormat, 069 final NumberFormat denominatorFormat) { 070 this.numeratorFormat = numeratorFormat; 071 this.denominatorFormat = denominatorFormat; 072 } 073 074 /** 075 * Create a default number format. The default number format is based on 076 * {@link NumberFormat#getNumberInstance(java.util.Locale)} with the only 077 * customizing is the maximum number of BigFraction digits, which is set to 0. 078 * @return the default number format. 079 */ 080 protected static NumberFormat getDefaultNumberFormat() { 081 return getDefaultNumberFormat(Locale.getDefault()); 082 } 083 084 /** 085 * Create a default number format. The default number format is based on 086 * {@link NumberFormat#getNumberInstance(java.util.Locale)} with the only 087 * customizing is the maximum number of BigFraction digits, which is set to 0. 088 * @param locale the specific locale used by the format. 089 * @return the default number format specific to the given locale. 090 */ 091 protected static NumberFormat getDefaultNumberFormat(final Locale locale) { 092 final NumberFormat nf = NumberFormat.getNumberInstance(locale); 093 nf.setMaximumFractionDigits(0); 094 nf.setParseIntegerOnly(true); 095 return nf; 096 } 097 098 /** 099 * 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 }