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