home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 November / Chip_1998-11_cd.bin / tema / Cafe / main.bin / NumberFormat.java < prev    next >
Text File  |  1997-10-01  |  19KB  |  497 lines

  1. /*
  2.  * @(#)NumberFormat.java    1.26 97/07/17
  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-1997 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.util.MissingResourceException;
  35. import java.text.resources.*;
  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.  * You can also use forms of the <code>parse</code> and <code>format</code>
  100.  * methods with <code>ParsePosition</code> and <code>FieldPosition</code> to
  101.  * allow you to:
  102.  * <ul>
  103.  * <li> progressively parse through pieces of a string
  104.  * <li> align the decimal point and other areas
  105.  * </ul>
  106.  * For example, you can align numbers in two ways:
  107.  * <ol>
  108.  * <li> If you are using a monospaced font with spacing for alignment,
  109.  *      you can pass the <code>FieldPosition</code> in your format call, with
  110.  *      <code>field</code> = <code>INTEGER_FIELD</code>. On output,
  111.  *      <code>getEndIndex</code> will be set to the offset between the
  112.  *      last character of the integer and the decimal. Add
  113.  *      (desiredSpaceCount - getEndIndex) spaces at the front of the string.
  114.  *
  115.  * <li> If you are using proportional fonts,
  116.  *      instead of padding with spaces, measure the width
  117.  *      of the string in pixels from the start to <code>getEndIndex</code>. 
  118.  *      Then move the pen by
  119.  *      (desiredPixelWidth - widthToAlignmentPoint) before drawing the text.
  120.  *      It also works where there is no decimal, but possibly additional
  121.  *      characters at the end, e.g. with parentheses in negative
  122.  *      numbers: "(12)" for -12.
  123.  * </ol>
  124.  *
  125.  * @see          DecimalFormat
  126.  * @see          ChoiceFormat
  127.  * @version      1.22 29 Jan 1997
  128.  * @author       Mark Davis
  129.  */
  130. public abstract class NumberFormat extends Format implements Cloneable {
  131.  
  132.     /**
  133.      * Field constant used to construct a FieldPosition object. Signifies that
  134.      * the position of the integer part of a formatted number should be returned.
  135.      * @see java.text.FieldPosition
  136.      */
  137.     public static final int INTEGER_FIELD = 0;
  138.  
  139.     /**
  140.      * Field constant used to construct a FieldPosition object. Signifies that
  141.      * the position of the fraction part of a formatted number should be returned.
  142.      * @see java.text.FieldPosition
  143.      */
  144.     public static final int FRACTION_FIELD = 1;
  145.  
  146.  
  147.     public final StringBuffer format(Object number,
  148.                                      StringBuffer toAppendTo,
  149.                                      FieldPosition pos)
  150.     {
  151.         if (number instanceof Double || number instanceof Float) {
  152.             return format(((Number)number).doubleValue(), toAppendTo, pos);
  153.         }
  154.         else if (number instanceof Number) {
  155.             return format(((Number)number).longValue(), toAppendTo, pos);
  156.         }
  157.         else {
  158.             throw new IllegalArgumentException("Cannot format given Object as a Number");
  159.         }
  160.     }
  161.  
  162.     public final Object parseObject(String source,
  163.                                     ParsePosition parsePosition)
  164.     {
  165.         return parse(source, parsePosition);
  166.     }
  167.  
  168.    /**
  169.      * Specialization of format.
  170.      * @see java.text.Format#format
  171.      */
  172.     public final String format (double number) {
  173.         return format(number,new StringBuffer(),
  174.                       new FieldPosition(0)).toString();
  175.     }
  176.  
  177.    /**
  178.      * Specialization of format.
  179.      * @see java.text.Format#format
  180.      */
  181.     public final String format (long number) {
  182.         return format(number,new StringBuffer(),
  183.                       new FieldPosition(0)).toString();
  184.     }
  185.  
  186.    /**
  187.      * Specialization of format.
  188.      * @see java.text.Format#format
  189.      */
  190.     public abstract StringBuffer format(double number,
  191.                                         StringBuffer toAppendTo,
  192.                                         FieldPosition pos);
  193.  
  194.    /**
  195.      * Specialization of format.
  196.      * @see java.text.Format#format
  197.      */
  198.     public abstract StringBuffer format(long number,
  199.                                         StringBuffer toAppendTo,
  200.                                         FieldPosition pos);
  201.  
  202.    /**
  203.      * Returns a Long if possible (e.g. within range [Long.MIN_VALUE,
  204.      * Long.MAX_VALUE], and with no decimals), otherwise a Double.
  205.      * If IntegerOnly is set, will stop at a decimal
  206.      * point (or equivalent; e.g. for rational numbers "1 2/3", will stop
  207.      * after the 1).
  208.      * Does not throw an exception; if no object can be parsed, index is
  209.      * unchanged!
  210.      * @see java.text.NumberFormat#isParseIntegerOnly
  211.      * @see java.text.Format#parseObject
  212.      * @return A Long or Double object with the parsed value, or
  213.      * null if the parse failed.
  214.      */
  215.     public abstract Number parse(String text, ParsePosition parsePosition);
  216.  
  217.     /**
  218.      * Convenience method.
  219.      *
  220.      * @exception ParseException if the specified string is invalid.
  221.      * @see #format
  222.      */
  223.     public Number parse(String text) throws ParseException {
  224.         ParsePosition parsePosition = new ParsePosition(0);
  225.         Number result = parse(text, parsePosition);
  226.         if (parsePosition.index == 0) {
  227.             throw new ParseException("Unparseable number: \"" + text + "\"", 0);
  228.         }
  229.         return result;
  230.     }
  231.  
  232.     /**
  233.      * Returns true if this format will parse numbers as integers only.
  234.      * For example in the English locale, with ParseIntegerOnly true, the
  235.      * string "1234." would be parsed as the integer value 1234 and parsing
  236.      * would stop at the "." character.  Of course, the exact format accepted
  237.      * by the parse operation is locale dependant and determined by sub-classes
  238.      * of NumberFormat.
  239.      */
  240.     public boolean isParseIntegerOnly() {
  241.         return parseIntegerOnly;
  242.     }
  243.  
  244.     /**
  245.      * Sets whether or not numbers should be parsed as integers only.
  246.      * @see #isParseIntegerOnly
  247.      */
  248.     public void setParseIntegerOnly(boolean value) {
  249.         parseIntegerOnly = value;
  250.     }
  251.  
  252.     //============== Locale Stuff =====================
  253.  
  254.     /**
  255.      * Returns the default number format for the current default locale.
  256.      * The default format is one of the styles provided by the other
  257.      * factory methods: getNumberInstance, getCurrencyInstance or getPercentInstance.
  258.      * Exactly which one is locale dependant.
  259.      */
  260.     public final static NumberFormat getInstance() {
  261.         return getInstance(Locale.getDefault(), NUMBERSTYLE);
  262.     }
  263.  
  264.     /**
  265.      * Returns the default number format for the specified locale.
  266.      * The default format is one of the styles provided by the other
  267.      * factory methods: getNumberInstance, getCurrencyInstance or getPercentInstance.
  268.      * Exactly which one is locale dependant.
  269.      */
  270.     public static NumberFormat getInstance(Locale inLocale) {
  271.         return getInstance(inLocale, NUMBERSTYLE);
  272.     }
  273.  
  274.     /**
  275.      * Returns a general-purpose number format for the current default locale.
  276.      */
  277.     public final static NumberFormat getNumberInstance() {
  278.         return getInstance(Locale.getDefault(), NUMBERSTYLE);
  279.     }
  280.  
  281.     /**
  282.      * Returns a general-purpose number format for the specified locale.
  283.      */
  284.     public static NumberFormat getNumberInstance(Locale inLocale) {
  285.         return getInstance(inLocale, NUMBERSTYLE);
  286.     }
  287.  
  288.     /**
  289.      * Returns a currency format for the current default locale.
  290.      */
  291.     public final static NumberFormat getCurrencyInstance() {
  292.         return getInstance(Locale.getDefault(), CURRENCYSTYLE);
  293.     }
  294.  
  295.     /**
  296.      * Returns a currency format for the specified locale.
  297.      */
  298.     public static NumberFormat getCurrencyInstance(Locale inLocale) {
  299.         return getInstance(inLocale, CURRENCYSTYLE);
  300.     }
  301.  
  302.     /**
  303.      * Returns a percentage format for the current default locale.
  304.      */
  305.     public final static NumberFormat getPercentInstance() {
  306.         return getInstance(Locale.getDefault(), PERCENTSTYLE);
  307.     }
  308.  
  309.     /**
  310.      * Returns a percentage format for the specified locale.
  311.      */
  312.  
  313.     public static NumberFormat getPercentInstance(Locale inLocale) {
  314.         return getInstance(inLocale, PERCENTSTYLE);
  315.     }
  316.  
  317.  
  318.     /**
  319.      * Get the set of Locales for which NumberFormats are installed
  320.      * @return available locales
  321.      */
  322.     public static Locale[] getAvailableLocales() {
  323.         return LocaleData.getAvailableLocales("NumberPatterns");
  324.     }
  325.  
  326.     /**
  327.      * Overrides hashCode
  328.      */
  329.     public int hashCode() {
  330.         return maxIntegerDigits * 37 + maxFractionDigits;
  331.         // just enough fields for a reasonable distribution
  332.     }
  333.  
  334.     /**
  335.      * Overrides equals
  336.      */
  337.     public boolean equals(Object obj) {
  338.         if (this == obj)
  339.             return true;
  340.         if (getClass() != obj.getClass())
  341.             return false;
  342.         NumberFormat other = (NumberFormat) obj;
  343.         return (maxIntegerDigits == other.maxIntegerDigits
  344.             && minIntegerDigits == other.minIntegerDigits
  345.             && maxFractionDigits == other.maxFractionDigits
  346.             && minFractionDigits == other.minFractionDigits
  347.             && parseIntegerOnly == other.parseIntegerOnly);
  348.     }
  349.  
  350.     /**
  351.      * Overrides Cloneable
  352.      */
  353.     public Object clone()
  354.     {
  355.         NumberFormat other = (NumberFormat) super.clone();
  356.         return other;
  357.     }
  358.  
  359.     /**
  360.      * Returns true if grouping is used in this format. For example, in the
  361.      * English locale, with grouping on, the number 1234567 might be formatted
  362.      * as "1,234,567". The grouping separator as well as the size of each group
  363.      * is locale dependant and is determined by sub-classes of NumberFormat.
  364.      * @see #setGroupingUsed
  365.      */
  366.     public boolean isGroupingUsed() {
  367.         return groupingUsed;
  368.     }
  369.  
  370.     /**
  371.      * Set whether or not grouping will be used in this format.
  372.      * @see #isGroupingUsed
  373.      */
  374.     public void setGroupingUsed(boolean newValue) {
  375.         groupingUsed = newValue;
  376.     }
  377.  
  378.     /**
  379.      * Returns the maximum number of digits allowed in the integer portion of a
  380.      * number.
  381.      * @see #setMaximumIntegerDigits
  382.      */
  383.     public int getMaximumIntegerDigits() {
  384.         return maxIntegerDigits;
  385.     }
  386.  
  387.     /**
  388.      * Sets the maximum number of digits allowed in the integer portion of a
  389.      * number. maximumIntegerDigits must be >= minimumIntegerDigits.  If the
  390.      * new value for maximumIntegerDigits is less than the current value
  391.      * of minimumIntegerDigits, then minimumIntegerDigits will also be set to
  392.      * the new value.
  393.  
  394.      * @see #getMaximumIntegerDigits
  395.      */
  396.     public void setMaximumIntegerDigits(int newValue) {
  397.         maxIntegerDigits = (byte) Math.max(0,Math.min(newValue,127));
  398.         if (minIntegerDigits > maxIntegerDigits)
  399.             minIntegerDigits = maxIntegerDigits;
  400.     }
  401.  
  402.     /**
  403.      * Returns the minimum number of digits allowed in the integer portion of a
  404.      * number.
  405.      * @see #setMinimumIntegerDigits
  406.      */
  407.     public int getMinimumIntegerDigits() {
  408.         return minIntegerDigits;
  409.     }
  410.  
  411.     /**
  412.      * Sets the minimum number of digits allowed in the integer portion of a
  413.      * number. minimumIntegerDigits must be <= maximumIntegerDigits.  If the
  414.      * new value for minimumIntegerDigits exceeds the current value
  415.      * of maximumIntegerDigits, then maximumIntegerDigits will also be set to
  416.      * the new value
  417.      * @see #getMinimumIntegerDigits
  418.      */
  419.     public void setMinimumIntegerDigits(int newValue) {
  420.         minIntegerDigits = (byte) Math.max(0,Math.min(newValue,127));
  421.         if (minIntegerDigits > maxIntegerDigits)
  422.             maxIntegerDigits = minIntegerDigits;
  423.     }
  424.  
  425.     /**
  426.      * Returns the maximum number of digits allowed in the fraction portion of a
  427.      * number.
  428.      * @see #setMaximumFractionDigits
  429.      */
  430.     public int getMaximumFractionDigits() {
  431.         return maxFractionDigits;
  432.     }
  433.  
  434.     /**
  435.      * Sets the maximum number of digits allowed in the fraction portion of a
  436.      * number. maximumFractionDigits must be >= minimumFractionDigits.  If the
  437.      * new value for maximumFractionDigits is less than the current value
  438.      * of minimumFractionDigits, then minimumFractionDigits will also be set to
  439.      * the new value.
  440.      * @see #getMaximumFractionDigits
  441.      */
  442.     public void setMaximumFractionDigits(int newValue) {
  443.         maxFractionDigits = (byte) Math.max(0,Math.min(newValue,127));
  444.         if (maxFractionDigits < minFractionDigits)
  445.             minFractionDigits = maxFractionDigits;
  446.     }
  447.  
  448.     /**
  449.      * Returns the minimum number of digits allowed in the fraction portion of a
  450.      * number.
  451.      * @see #setMinimumFractionDigits
  452.      */
  453.     public int getMinimumFractionDigits() {
  454.         return minFractionDigits;
  455.     }
  456.  
  457.     /**
  458.      * Sets the minimum number of digits allowed in the fraction portion of a
  459.      * number. minimumFractionDigits must be <= maximumFractionDigits.  If the
  460.      * new value for minimumFractionDigits exceeds the current value
  461.      * of maximumFractionDigits, then maximumIntegerDigits will also be set to
  462.      * the new value
  463.      * @see #getMinimumFractionDigits
  464.      */
  465.     public void setMinimumFractionDigits(int newValue) {
  466.         minFractionDigits = (byte) Math.max(0,Math.min(newValue,127));
  467.         if (maxFractionDigits < minFractionDigits)
  468.             maxFractionDigits = minFractionDigits;
  469.     }
  470.  
  471.     // =======================privates===============================
  472.  
  473.     private static NumberFormat getInstance(Locale desiredLocale,
  474.                                            int choice)
  475.     {
  476.         ResourceBundle resource = ResourceBundle.getBundle
  477.                                   ("java.text.resources.LocaleElements",
  478.                                    desiredLocale);
  479.         String[] numberStrings = resource.getStringArray("NumberPatterns");
  480.  
  481.         return new DecimalFormat(numberStrings[choice],
  482.                                  new DecimalFormatSymbols(desiredLocale));
  483.     }
  484.  
  485.     // Constants used by factory methods to specify a style of format.
  486.     private static final int NUMBERSTYLE = 0;
  487.     private static final int CURRENCYSTYLE = 1;
  488.     private static final int PERCENTSTYLE = 2;
  489.  
  490.     private boolean groupingUsed = true;
  491.     private byte    maxIntegerDigits = 40;
  492.     private byte    minIntegerDigits = 1;
  493.     private byte    maxFractionDigits = 3;    // invariant, >= minFractionDigits
  494.     private byte    minFractionDigits = 0;
  495.     private boolean parseIntegerOnly = false;
  496. }
  497.