home *** CD-ROM | disk | FTP | other *** search
/ Java 1.2 How-To / JavaHowTo.iso / 3rdParty / jbuilder / unsupported / JDK1.2beta3 / SOURCE / SRC.ZIP / java / text / NumberFormat.java < prev    next >
Encoding:
Java Source  |  1998-03-20  |  19.5 KB  |  545 lines

  1. /*
  2.  * @(#)NumberFormat.java    1.32 98/03/18
  3.  *
  4.  * (C) Copyright Taligent, Inc. 1996 - All Rights Reserved
  5.  * (C) Copyright IBM Corp. 1996 - All Rights Reserved
  6.  *
  7.  * Portions copyright (c) 1996-1998 Sun Microsystems, Inc. All Rights Reserved.
  8.  *
  9.  *   The original version of this source code and documentation is copyrighted
  10.  * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
  11.  * materials are provided under terms of a License Agreement between Taligent
  12.  * and Sun. This technology is protected by multiple US and International
  13.  * patents. This notice and attribution to Taligent may not be removed.
  14.  *   Taligent is a registered trademark of Taligent, Inc.
  15.  *
  16.  * Permission to use, copy, modify, and distribute this software
  17.  * and its documentation for NON-COMMERCIAL purposes and without
  18.  * fee is hereby granted provided that this copyright notice
  19.  * appears in all copies. Please refer to the file "copyright.html"
  20.  * for further important copyright and licensing information.
  21.  *
  22.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
  23.  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  24.  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  25.  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
  26.  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
  27.  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
  28.  *
  29.  */
  30.  
  31. package java.text;
  32. import java.util.Locale;
  33. import java.util.ResourceBundle;
  34. import java.text.resources.*;
  35. import java.util.Hashtable;
  36.  
  37. /**
  38.  * <code>NumberFormat</code> is the abstract base class for all number
  39.  * formats. This class provides the interface for formatting and parsing
  40.  * numbers. <code>NumberFormat</code> also provides methods for determining
  41.  * which locales have number formats, and what their names are.
  42.  *
  43.  * <p>
  44.  * <code>NumberFormat</code> helps you to format and parse numbers for any locale.
  45.  * Your code can be completely independent of the locale conventions for
  46.  * decimal points, thousands-separators, or even the particular decimal
  47.  * digits used, or whether the number format is even decimal.
  48.  *
  49.  * <p>
  50.  * To format a number for the current Locale, use one of the factory
  51.  * class methods:
  52.  * <blockquote>
  53.  * <pre>
  54.  *  myString = NumberFormat.getInstance().format(myNumber);
  55.  * </pre>
  56.  * </blockquote>
  57.  * If you are formatting multiple numbers, it is
  58.  * more efficient to get the format and use it multiple times so that
  59.  * the system doesn't have to fetch the information about the local
  60.  * language and country conventions multiple times.
  61.  * <blockquote>
  62.  * <pre>
  63.  * NumberFormat nf = NumberFormat.getInstance();
  64.  * for (int i = 0; i < a.length; ++i) {
  65.  *     output.println(nf.format(myNumber[i]) + "; ");
  66.  * }
  67.  * </pre>
  68.  * </blockquote>
  69.  * To format a number for a different Locale, specify it in the
  70.  * call to <code>getInstance</code>.
  71.  * <blockquote>
  72.  * <pre>
  73.  * NumberFormat nf = NumberFormat.getInstance(Locale.FRENCH);
  74.  * </pre>
  75.  * </blockquote>
  76.  * You can also use a <code>NumberFormat</code> to parse numbers:
  77.  * <blockquote>
  78.  * <pre>
  79.  * myNumber = nf.parse(myString);
  80.  * </pre>
  81.  * </blockquote>
  82.  * Use <code>getInstance</code> or <code>getNumberInstance</code> to get the
  83.  * normal number format. Use <code>getCurrencyInstance</code> to get the
  84.  * currency number format. And use <code>getPercentInstance</code> to get a
  85.  * format for displaying percentages. With this format, a fraction like
  86.  * 0.53 is displayed as 53%.
  87.  *
  88.  * <p>
  89.  * You can also control the display of numbers with such methods as
  90.  * <code>setMinimumFractionDigits</code>.
  91.  * If you want even more control over the format or parsing,
  92.  * or want to give your users more control,
  93.  * you can try casting the <code>NumberFormat</code> you get from the factory methods
  94.  * to a <code>DecimalNumberFormat</code>. This will work for the vast majority
  95.  * of locales; just remember to put it in a <code>try</code> block in case you
  96.  * encounter an unusual one.
  97.  *
  98.  * <p>
  99.  * NumberFormat and DecimalFormat are designed such that some controls
  100.  * work for formatting and others work for parsing.  The following is
  101.  * the detailed description for each these control methods,
  102.  * <p>
  103.  * setParseIntegerOnly : only affects parsing, e.g.
  104.  * if true,  "3456.78" -> 3456 (and leaves the parse position just after index 6)
  105.  * if false, "3456.78" -> 3456.78 (and leaves the parse position just after index 8)
  106.  * This is independent of formatting.  If you want to not show a decimal point
  107.  * where there might be no digits after the decimal point, use
  108.  * setDecimalSeparatorAlwaysShown.
  109.  * <p>
  110.  * setDecimalSeparatorAlwaysShown : only affects formatting, and only where
  111.  * there might be no digits after the decimal point, such as with a pattern
  112.  * like "#,##0.##", e.g.,
  113.  * if true,  3456.00 -> "3,456."
  114.  * if false, 3456.00 -> "3456"
  115.  * This is independent of parsing.  If you want parsing to stop at the decimal
  116.  * point, use setParseIntegerOnly.
  117.  *
  118.  * <p>
  119.  * You can also use forms of the <code>parse</code> and <code>format</code>
  120.  * methods with <code>ParsePosition</code> and <code>FieldPosition</code> to
  121.  * allow you to:
  122.  * <ul>
  123.  * <li> progressively parse through pieces of a string
  124.  * <li> align the decimal point and other areas
  125.  * </ul>
  126.  * For example, you can align numbers in two ways:
  127.  * <ol>
  128.  * <li> If you are using a monospaced font with spacing for alignment,
  129.  *      you can pass the <code>FieldPosition</code> in your format call, with
  130.  *      <code>field</code> = <code>INTEGER_FIELD</code>. On output,
  131.  *      <code>getEndIndex</code> will be set to the offset between the
  132.  *      last character of the integer and the decimal. Add
  133.  *      (desiredSpaceCount - getEndIndex) spaces at the front of the string.
  134.  *
  135.  * <li> If you are using proportional fonts,
  136.  *      instead of padding with spaces, measure the width
  137.  *      of the string in pixels from the start to <code>getEndIndex</code>.
  138.  *      Then move the pen by
  139.  *      (desiredPixelWidth - widthToAlignmentPoint) before drawing the text.
  140.  *      It also works where there is no decimal, but possibly additional
  141.  *      characters at the end, e.g., with parentheses in negative
  142.  *      numbers: "(12)" for -12.
  143.  * </ol>
  144.  *
  145.  * @see          DecimalFormat
  146.  * @see          ChoiceFormat
  147.  * @version      1.22 29 Jan 1997
  148.  * @author       Mark Davis
  149.  * @author       Helena Shih
  150.  */
  151. public abstract class NumberFormat extends Format{
  152.  
  153.     /**
  154.      * Field constant used to construct a FieldPosition object. Signifies that
  155.      * the position of the integer part of a formatted number should be returned.
  156.      * @see java.text.FieldPosition
  157.      */
  158.     public static final int INTEGER_FIELD = 0;
  159.  
  160.     /**
  161.      * Field constant used to construct a FieldPosition object. Signifies that
  162.      * the position of the fraction part of a formatted number should be returned.
  163.      * @see java.text.FieldPosition
  164.      */
  165.     public static final int FRACTION_FIELD = 1;
  166.  
  167.     public final StringBuffer format(Object number,
  168.                                      StringBuffer toAppendTo,
  169.                                      FieldPosition pos)
  170.     {
  171.         if (number instanceof Double || number instanceof Float) {
  172.             return format(((Number)number).doubleValue(), toAppendTo, pos);
  173.         }
  174.         else if (number instanceof Number) {
  175.             return format(((Number)number).longValue(), toAppendTo, pos);
  176.         }
  177.         else {
  178.             throw new IllegalArgumentException("Cannot format given Object as a Number");
  179.         }
  180.     }
  181.  
  182.     public final Object parseObject(String source,
  183.                                     ParsePosition parsePosition)
  184.     {
  185.         return parse(source, parsePosition);
  186.     }
  187.  
  188.    /**
  189.      * Specialization of format.
  190.      * @see java.text.Format#format
  191.      */
  192.     public final String format (double number) {
  193.         return format(number,new StringBuffer(),
  194.                       new FieldPosition(0)).toString();
  195.     }
  196.  
  197.    /**
  198.      * Specialization of format.
  199.      * @see java.text.Format#format
  200.      */
  201.     public final String format (long number) {
  202.         return format(number,new StringBuffer(),
  203.                       new FieldPosition(0)).toString();
  204.     }
  205.  
  206.    /**
  207.      * Specialization of format.
  208.      * @see java.text.Format#format
  209.      */
  210.     public abstract StringBuffer format(double number,
  211.                                         StringBuffer toAppendTo,
  212.                                         FieldPosition pos);
  213.  
  214.    /**
  215.      * Specialization of format.
  216.      * @see java.text.Format#format
  217.      */
  218.     public abstract StringBuffer format(long number,
  219.                                         StringBuffer toAppendTo,
  220.                                         FieldPosition pos);
  221.  
  222.    /**
  223.      * Returns a Long if possible (e.g., within the range [Long.MIN_VALUE,
  224.      * Long.MAX_VALUE] and with no decimals), otherwise a Double.
  225.      * If IntegerOnly is set, will stop at a decimal
  226.      * point (or equivalent; e.g., for rational numbers "1 2/3", will stop
  227.      * after the 1).
  228.      * Does not throw an exception; if no object can be parsed, index is
  229.      * unchanged!
  230.      * @see java.text.NumberFormat#isParseIntegerOnly
  231.      * @see java.text.Format#parseObject
  232.      */
  233.     public abstract Number parse(String text, ParsePosition parsePosition);
  234.  
  235.     /**
  236.      * Convenience method.
  237.      *
  238.      * @exception ParseException if the specified string is invalid.
  239.      * @see #format
  240.      */
  241.     public Number parse(String text) throws ParseException {
  242.         ParsePosition parsePosition = new ParsePosition(0);
  243.         Number result = parse(text, parsePosition);
  244.         if (parsePosition.index == 0) {
  245.             throw new ParseException("Unparseable number: \"" + text + "\"",
  246.                 parsePosition.errorIndex);
  247.         }
  248.         return result;
  249.     }
  250.  
  251.     /**
  252.      * Returns true if this format will parse numbers as integers only.
  253.      * For example in the English locale, with ParseIntegerOnly true, the
  254.      * string "1234." would be parsed as the integer value 1234 and parsing
  255.      * would stop at the "." character.  Of course, the exact format accepted
  256.      * by the parse operation is locale dependant and determined by sub-classes
  257.      * of NumberFormat.
  258.      */
  259.     public boolean isParseIntegerOnly() {
  260.         return parseIntegerOnly;
  261.     }
  262.  
  263.     /**
  264.      * Sets whether or not numbers should be parsed as integers only.
  265.      * @see #isParseIntegerOnly
  266.      */
  267.     public void setParseIntegerOnly(boolean value) {
  268.         parseIntegerOnly = value;
  269.     }
  270.  
  271.     //============== Locale Stuff =====================
  272.  
  273.     /**
  274.      * Returns the default number format for the current default locale.
  275.      * The default format is one of the styles provided by the other
  276.      * factory methods: getNumberInstance, getCurrencyInstance or getPercentInstance.
  277.      * Exactly which one is locale dependant.
  278.      */
  279.     public final static NumberFormat getInstance() {
  280.         return getInstance(Locale.getDefault(), NUMBERSTYLE);
  281.     }
  282.  
  283.     /**
  284.      * Returns the default number format for the specified locale.
  285.      * The default format is one of the styles provided by the other
  286.      * factory methods: getNumberInstance, getCurrencyInstance or getPercentInstance.
  287.      * Exactly which one is locale dependant.
  288.      */
  289.     public static NumberFormat getInstance(Locale inLocale) {
  290.         return getInstance(inLocale, NUMBERSTYLE);
  291.     }
  292.  
  293.     /**
  294.      * Returns a general-purpose number format for the current default locale.
  295.      */
  296.     public final static NumberFormat getNumberInstance() {
  297.         return getInstance(Locale.getDefault(), NUMBERSTYLE);
  298.     }
  299.  
  300.     /**
  301.      * Returns a general-purpose number format for the specified locale.
  302.      */
  303.     public static NumberFormat getNumberInstance(Locale inLocale) {
  304.         return getInstance(inLocale, NUMBERSTYLE);
  305.     }
  306.  
  307.     /**
  308.      * Returns a currency format for the current default locale.
  309.      */
  310.     public final static NumberFormat getCurrencyInstance() {
  311.         return getInstance(Locale.getDefault(), CURRENCYSTYLE);
  312.     }
  313.  
  314.     /**
  315.      * Returns a currency format for the specified locale.
  316.      */
  317.     public static NumberFormat getCurrencyInstance(Locale inLocale) {
  318.         return getInstance(inLocale, CURRENCYSTYLE);
  319.     }
  320.  
  321.     /**
  322.      * Returns a percentage format for the current default locale.
  323.      */
  324.     public final static NumberFormat getPercentInstance() {
  325.         return getInstance(Locale.getDefault(), PERCENTSTYLE);
  326.     }
  327.  
  328.     /**
  329.      * Returns a percentage format for the specified locale.
  330.      */
  331.     public static NumberFormat getPercentInstance(Locale inLocale) {
  332.         return getInstance(inLocale, PERCENTSTYLE);
  333.     }
  334.  
  335.     /**
  336.      * Returns a scientific format for the current default locale.
  337.      */
  338.     /*public*/ final static NumberFormat getScientificInstance() {
  339.         return getInstance(Locale.getDefault(), SCIENTIFICSTYLE);
  340.     }
  341.  
  342.     /**
  343.      * Returns a scientific format for the specified locale.
  344.      */
  345.     /*public*/ static NumberFormat getScientificInstance(Locale inLocale) {
  346.         return getInstance(inLocale, SCIENTIFICSTYLE);
  347.     }
  348.  
  349.  
  350.     /**
  351.      * Get the set of Locales for which NumberFormats are installed
  352.      * @return available locales
  353.      */
  354.     public static Locale[] getAvailableLocales() {
  355.         return LocaleData.getAvailableLocales("NumberPatterns");
  356.     }
  357.  
  358.     /**
  359.      * Overrides hashCode
  360.      */
  361.     public int hashCode() {
  362.         return maxIntegerDigits * 37 + maxFractionDigits;
  363.         // just enough fields for a reasonable distribution
  364.     }
  365.  
  366.     /**
  367.      * Overrides equals
  368.      */
  369.     public boolean equals(Object obj) {
  370.         if (obj == null) return false;
  371.         if (this == obj)
  372.             return true;
  373.         if (getClass() != obj.getClass())
  374.             return false;
  375.         NumberFormat other = (NumberFormat) obj;
  376.         return (maxIntegerDigits == other.maxIntegerDigits
  377.             && minIntegerDigits == other.minIntegerDigits
  378.             && maxFractionDigits == other.maxFractionDigits
  379.             && minFractionDigits == other.minFractionDigits
  380.             && groupingUsed == other.groupingUsed
  381.             && parseIntegerOnly == other.parseIntegerOnly);
  382.     }
  383.  
  384.     /**
  385.      * Overrides Cloneable
  386.      */
  387.     public Object clone()
  388.     {
  389.         NumberFormat other = (NumberFormat) super.clone();
  390.         return other;
  391.     }
  392.  
  393.     /**
  394.      * Returns true if grouping is used in this format. For example, in the
  395.      * English locale, with grouping on, the number 1234567 might be formatted
  396.      * as "1,234,567". The grouping separator as well as the size of each group
  397.      * is locale dependant and is determined by sub-classes of NumberFormat.
  398.      * @see #setGroupingUsed
  399.      */
  400.     public boolean isGroupingUsed() {
  401.         return groupingUsed;
  402.     }
  403.  
  404.     /**
  405.      * Set whether or not grouping will be used in this format.
  406.      * @see #isGroupingUsed
  407.      */
  408.     public void setGroupingUsed(boolean newValue) {
  409.         groupingUsed = newValue;
  410.     }
  411.  
  412.     /**
  413.      * Returns the maximum number of digits allowed in the integer portion of a
  414.      * number.
  415.      * @see #setMaximumIntegerDigits
  416.      */
  417.     public int getMaximumIntegerDigits() {
  418.         return maxIntegerDigits;
  419.     }
  420.  
  421.     /**
  422.      * Sets the maximum number of digits allowed in the integer portion of a
  423.      * number. maximumIntegerDigits must be >= minimumIntegerDigits.  If the
  424.      * new value for maximumIntegerDigits is less than the current value
  425.      * of minimumIntegerDigits, then minimumIntegerDigits will also be set to
  426.      * the new value.
  427.  
  428.      * @see #getMaximumIntegerDigits
  429.      */
  430.     public void setMaximumIntegerDigits(int newValue) {
  431.         maxIntegerDigits = (byte) Math.max(0,Math.min(newValue,308));
  432.         if (minIntegerDigits > maxIntegerDigits)
  433.             minIntegerDigits = maxIntegerDigits;
  434.     }
  435.  
  436.     /**
  437.      * Returns the minimum number of digits allowed in the integer portion of a
  438.      * number.
  439.      * @see #setMinimumIntegerDigits
  440.      */
  441.     public int getMinimumIntegerDigits() {
  442.         return minIntegerDigits;
  443.     }
  444.  
  445.     /**
  446.      * Sets the minimum number of digits allowed in the integer portion of a
  447.      * number. minimumIntegerDigits must be <= maximumIntegerDigits.  If the
  448.      * new value for minimumIntegerDigits exceeds the current value
  449.      * of maximumIntegerDigits, then maximumIntegerDigits will also be set to
  450.      * the new value
  451.      * @see #getMinimumIntegerDigits
  452.      */
  453.     public void setMinimumIntegerDigits(int newValue) {
  454.         minIntegerDigits = (byte) Math.max(0,Math.min(newValue,127));
  455.         if (minIntegerDigits > maxIntegerDigits)
  456.             maxIntegerDigits = minIntegerDigits;
  457.     }
  458.  
  459.     /**
  460.      * Returns the maximum number of digits allowed in the fraction portion of a
  461.      * number.
  462.      * @see #setMaximumFractionDigits
  463.      */
  464.     public int getMaximumFractionDigits() {
  465.         return maxFractionDigits;
  466.     }
  467.  
  468.     /**
  469.      * Sets the maximum number of digits allowed in the fraction portion of a
  470.      * number. maximumFractionDigits must be >= minimumFractionDigits.  If the
  471.      * new value for maximumFractionDigits is less than the current value
  472.      * of minimumFractionDigits, then minimumFractionDigits will also be set to
  473.      * the new value.
  474.      * @see #getMaximumFractionDigits
  475.      */
  476.     public void setMaximumFractionDigits(int newValue) {
  477.         maxFractionDigits = (byte) Math.max(0,Math.min(newValue,340));
  478.         if (maxFractionDigits < minFractionDigits)
  479.             minFractionDigits = maxFractionDigits;
  480.     }
  481.  
  482.     /**
  483.      * Returns the minimum number of digits allowed in the fraction portion of a
  484.      * number.
  485.      * @see #setMinimumFractionDigits
  486.      */
  487.     public int getMinimumFractionDigits() {
  488.         return minFractionDigits;
  489.     }
  490.  
  491.     /**
  492.      * Sets the minimum number of digits allowed in the fraction portion of a
  493.      * number. minimumFractionDigits must be <= maximumFractionDigits.  If the
  494.      * new value for minimumFractionDigits exceeds the current value
  495.      * of maximumFractionDigits, then maximumIntegerDigits will also be set to
  496.      * the new value
  497.      * @see #getMinimumFractionDigits
  498.      */
  499.     public void setMinimumFractionDigits(int newValue) {
  500.         minFractionDigits = (byte) Math.max(0,Math.min(newValue,127));
  501.         if (maxFractionDigits < minFractionDigits)
  502.             maxFractionDigits = minFractionDigits;
  503.     }
  504.  
  505.     // =======================privates===============================
  506.  
  507.     private static NumberFormat getInstance(Locale desiredLocale,
  508.                                            int choice)
  509.     {
  510.     /* try the cache first */
  511.     String[] numberPatterns = (String[])cachedLocaleData.get(desiredLocale);
  512.     if (numberPatterns == null) { /* cache miss */
  513.         ResourceBundle resource = ResourceBundle.getBundle
  514.         ("java.text.resources.LocaleElements", desiredLocale);
  515.         numberPatterns = resource.getStringArray("NumberPatterns");
  516.         /* update cache */
  517.         cachedLocaleData.put(desiredLocale, numberPatterns);
  518.     }
  519.  
  520.         return new DecimalFormat(numberPatterns[choice],
  521.                                  new DecimalFormatSymbols(desiredLocale));
  522.     }
  523.  
  524.     /**
  525.      * Cache to hold the NumberPatterns of a Locale.
  526.      */
  527.     private static final Hashtable cachedLocaleData = new Hashtable(3);
  528.  
  529.     // Constants used by factory methods to specify a style of format.
  530.     private static final int NUMBERSTYLE = 0;
  531.     private static final int CURRENCYSTYLE = 1;
  532.     private static final int PERCENTSTYLE = 2;
  533.     private static final int SCIENTIFICSTYLE = 3;
  534.  
  535.     private boolean groupingUsed = true;
  536.     private byte    maxIntegerDigits = 40;
  537.     private byte    minIntegerDigits = 1;
  538.     private byte    maxFractionDigits = 3;    // invariant, >= minFractionDigits
  539.     private byte    minFractionDigits = 0;
  540.     private boolean parseIntegerOnly = false;
  541.     // Removed "implements Cloneable" clause.  Needs to update serialization
  542.     // ID for backward compatibility.
  543.     static final long serialVersionUID = -2308460125733713944L;
  544. }
  545.