Package ariba.util.formatter

Source Code of ariba.util.formatter.DoubleFormatter

/*
    Copyright 1996-2008 Ariba, Inc.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at
        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.

    $Id: //ariba/platform/util/core/ariba/util/formatter/DoubleFormatter.java#7 $
*/

package ariba.util.formatter;

import ariba.util.core.Assert;
import ariba.util.core.Fmt;
import ariba.util.core.StringUtil;
import java.text.DecimalFormat;
import java.text.Format;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.ParsePosition;
import java.util.Locale;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
    <code>DoubleFormatter</code> is a subclass of <code>Formatter</code> which
    is responsible for formatting, parsing, and comparing <code>double</code>
    values and/or <code>Double</code> objects.

    @aribaapi documented
*/
public class DoubleFormatter extends DecimalFormatterCommon
{
    /*-----------------------------------------------------------------------
        Constants
      -----------------------------------------------------------------------*/

    /**
        Our Java class name.

        @aribaapi private
    */
    public static final String ClassName = "ariba.util.formatter.DoubleFormatter";

    private static final String CanonicalPattern =
        "+#,##0.0###################;-#,##0.0###################";
   
    private static final String CanonicalPositivePrefix = "+";

    private static final String CanonicalPercentSign = "%";

    /*-----------------------------------------------------------------------
        Fields
      -----------------------------------------------------------------------*/

        // the cache of DecimalFormat instances
    private static final DoubleFormatter factory = new DoubleFormatter();


    /*-----------------------------------------------------------------------
        Constructor
      -----------------------------------------------------------------------*/

    /**
        Creates a new <code>DoubleFormatter</code>.

        @aribaapi private
    */
    public DoubleFormatter ()
    {
    }
   

    /*-----------------------------------------------------------------------
        Static Formatting
      -----------------------------------------------------------------------*/

    /**
        Returns a formatted string for the given <code>Double</code> in the
        default locale.  By default, a precision of zero is used.

        @param  object the <code>Double</code> to format into a string
        @return        a string representation of the <code>Double</code>,
                       or empty string if the <code>Double</code> is null
        @aribaapi documented
    */
    public static String getStringValue (Double object)
    {
        return getStringValue(object, 0, 0, null, getDefaultLocale());
    }

    /**
        Returns a formatted string for the given <code>Double</code> in the
        given locale.  By default, a precision of zero is used.  The
        <code>locale</code> parameter must be non-null.

        @param  object the <code>Double</code> to format into a string
        @param  locale the <code>Locale</code> to use for formatting
        @return        a string representation of the <code>Double</code>,
                       or empty string if the <code>Double</code> is null
        @aribaapi documented
    */
    public static String getStringValue (Double object, Locale locale)
    {
        return getStringValue(object, 0, 0, null, locale);
    }

    /**
        Returns a formatted string for the given <code>Double</code> in the
        default locale.  The <code>precision</code> parameter is used to
        determine how many fractional digits are shown.

        @param  object    the <code>Double</code> to format into a string
        @param  precision the number of fractional digits to show
        @return           a string representation of the <code>Double</code>,
                          or empty string if the <code>Double</code> is null
        @aribaapi documented
    */
    public static String getStringValue (Double object, int precision)
    {
        return getStringValue(object, precision, precision, null, getDefaultLocale());
    }

    /**
        Returns a formatted string for the given <code>Double</code> in the
        given locale.  The <code>precision</code> parameter is used to
        determine how many fractional digits are shown.  The
        <code>locale</code> parameter must be non-null.

        @param  object    the <code>Double</code> to format into a string
        @param  precision the number of fractional digits to show
        @param  locale    the <code>Locale</code> to use for formatting
        @return           a string representation of the <code>Double</code>,
                          or empty string if the <code>Double</code> is null
        @aribaapi documented
    */
    public static String getStringValue (Double object, int precision, Locale locale)
    {
        return trimString(getStringValue(object, precision, precision, null, locale),
                          locale);
    }

    /**
        Returns a formatted string for the given <code>Double</code> in the
        given locale.  The <code>precision</code> parameter is used to
        determine how many fractional digits are shown.  The
        <code>locale</code> parameter must be non-null.

        @param object the <code>Double</code> to format into a string
        @param minPrecision the minimum number of fractional digits to show
        @param maxPrecision the maximum number of fractional digits to show
        @param locale the <code>Locale</code> to use for formatting
        @return a string representation of the <code>Double</code>,
                or empty string if the <code>Double</code> is null
        @aribaapi documented
    */
    public static String getStringValue (
        Double object,
        int    minPrecision,
        int    maxPrecision,
        Locale locale)
    {
        return getStringValue(object, minPrecision, maxPrecision, null, locale);
    }

    /**
        Returns a formatted string for the given <code>Double</code> in the
        given locale.  The <code>precision</code> parameter is used to
        determine how many fractional digits are shown.  The
        <code>locale</code> parameter must be non-null.

        @param object the <code>Double</code> to format into a string
        @param minPrecision the minimum number of fractional digits to show
        @param maxPrecision the maximum number of fractional digits to show
        @param pattern the DecimalFormat pattern to use for formatting
        @param locale the <code>Locale</code> to use for formatting
        @return a string representation of the <code>Double</code>,
                or empty string if the <code>Double</code> is null
        @aribaapi documented
        @see java.text.DecimalFormat
    */
    public static String getStringValue (
        Double object,
        int    minPrecision,
        int    maxPrecision,
        String pattern,
        Locale locale)
    {
        if (object == null) {
            return "";
        }

        double d = object.doubleValue();
        return getStringValue(d, minPrecision, maxPrecision, pattern, locale);
    }

    /**
        Returns a formatted string for the given <code>double</code> in the
        default locale.  By default, a precision of zero is used.

        @param  value the <code>double</code> to format into a string
        @return       a string representation of the <code>double</code>
        @aribaapi documented
    */
    public static String getStringValue (double value)
    {
        return getStringValue(value, 0, 0, null, getDefaultLocale());
    }

    /**
        Returns a formatted string for the given <code>double</code> in the
        given locale.  By default, a precision of zero is used.  The
        <code>locale</code> parameter must be non-null.

        @param  value  the <code>double</code> to format into a string
        @param  locale the <code>Locale</code> to use for formatting
        @return        a string representation of the <code>double</code>
        @aribaapi documented
    */
    public static String getStringValue (double value, Locale locale)
    {
        return getStringValue(value, 0, 0, null, locale);
    }

    /**
        Returns a formatted string for the given <code>double</code> in the
        default locale.  The <code>precision</code> parameter is used to
        determine how many fractional digits are shown.

        @param  value     the <code>double</code> to format into a string
        @param  precision the number of fractional digits to show
        @return           a string representation of the <code>double</code>
        @aribaapi documented
    */
    public static String getStringValue (double value, int precision)
    {
        return getStringValue(value, precision, precision, null, getDefaultLocale());
    }

    /**
        Returns a formatted string for the given <code>double</code> in the
        given locale.  The <code>precision</code> parameter is used to
        determine how many fractional digits are shown.  The
        <code>locale</code> parameter must be non-null.

        @param  value     the <code>double</code> to format into a string
        @param  precision the number of fractional digits to show
        @param  locale    the <code>Locale</code> to use for formatting
        @return           a string representation of the <code>double</code>
        @aribaapi documented
    */
    public static String getStringValue (double value, int precision, Locale locale)
    {
        Assert.that(locale != null, "invalid null Locale");
        return getStringValue(value, precision, precision, null, locale);
    }

    /**
        Returns a formatted string for the given <code>double</code> in the
        default locale.

        @param  value     the <code>double</code> to format into a string
        @param  minPrecision the minimum number of fractional digits to show
        @param  maxPrecision the maximum number of fractional digits to show
        @return           a string representation of the <code>double</code>
        @aribaapi documented
    */
    public static String getStringValue (double value, int minPrecision, int maxPrecision)
    {
        return getStringValue(
            value, minPrecision, maxPrecision, null, getDefaultLocale());
    }

    /**
        Returns a formatted string for the given <code>double</code> in the
        given <code>locale</code>.

        @param  value the <code>double</code> to format into a string
        @param  minPrecision the minimum number of fractional digits to show
        @param  maxPrecision the maximum number of fractional digits to show
        @param  locale the <code>Locale</code> to use for formatting
        @return a string representation of the <code>double</code>
        @aribaapi documented
    */
    public static String getStringValue (
        double value,
        int    minPrecision,
        int    maxPrecision,
        Locale locale)
    {
        return getStringValue(value, minPrecision, maxPrecision, null, locale);
    }

     /**
        Returns a formatted string for the given <code>double</code> in the
        given <code>locale</code>.

        @param  value the <code>double</code> to format into a string
        @param  minPrecision the minimum number of fractional digits to show
        @param  maxPrecision the maximum number of fractional digits to show
        @param  pattern the DecimalFormat pattern to use for formatting
        @param  locale the <code>Locale</code> to use for formatting
        @return a string representation of the <code>double</code>
        @aribaapi documented
        @see java.text.DecimalFormat
    */
    public static String getStringValue (
        double value,
        int    minPrecision,
        int    maxPrecision,
        String pattern,
        Locale locale)
     {
         return getStringValue(value, minPrecision, maxPrecision, pattern, locale, true);
     }

    /**
        Returns a formatted string for the given <code>double</code> in the
        given <code>locale</code>.

        @param  value the <code>double</code> to format into a string
        @param  minPrecision the minimum number of fractional digits to show
        @param  maxPrecision the maximum number of fractional digits to show
        @param  pattern the DecimalFormat pattern to use for formatting
        @param  locale the <code>Locale</code> to use for formatting
        @param  trim true if leading and trailing zeros should be removed.
        @return a string representation of the <code>double</code>
        @aribaapi documented
        @see java.text.DecimalFormat
    */
    public static String getStringValue (
        double value,
        int    minPrecision,
        int    maxPrecision,
        String pattern,
        Locale locale,
        boolean trim)
    {
            // locale must be non-null
        Assert.that(locale != null, "invalid null Locale");

        DecimalFormat fmt = null;
        try
        {
            fmt = acquireDecimalFormat(locale, pattern);
            // for now, we force at least one digit for the integral part
            fmt.setMinimumIntegerDigits(1);
            fmt.setMinimumFractionDigits(minPrecision);
            fmt.setMaximumFractionDigits(maxPrecision);
            String formattedValue = fmt.format(value);
            return trim ? trimString(formattedValue, locale) : formattedValue;
        }
        finally
        {
            releaseDecimalFormat(fmt,locale, pattern);
        }
    }


    /*-----------------------------------------------------------------------
        Static Parsing
      -----------------------------------------------------------------------*/

    /**
        Tries to parse the given string as a <code>double</code> in the
        default locale.

        @param     string the string to parse as a <code>double</code>
        @return           a <code>double</code> value derived from the string
        @exception        ParseException if the string cannot be parsed as a
                          <code>double</code>
        @aribaapi documented
    */
    public static double parseDouble (String string)
      throws ParseException
    {
        return parseDouble(string, null, getDefaultLocale());
    }

    /**
        Tries to parse the given string as a <code>double</code> in the given
        locale.  The <code>locale</code> parameter must be non-null.

        @param     string the string to parse as a <code>double</code>
        @param     locale the <code>Locale</code> to use for parsing
        @return           a <code>double</code> value derived from the string
        @exception        ParseException if the string cannot be parsed as an
                          <code>double</code>
        @aribaapi documented
    */
    public static double parseDouble (String string, Locale locale)
      throws ParseException
    {
        return parseDouble(string, locale, false);
    }

    /**
        Tries to parse the given string as a <code>double</code> in the given
        locale.  The <code>locale</code> parameter must be non-null.

        @param     string the string to parse as a <code>double</code>
        @param     locale the <code>Locale</code> to use for parsing
        @return           a <code>double</code> value derived from the string
        @exception        ParseException if the string cannot be parsed as an
                          <code>double</code>
        @aribaapi documented
    */
    public static double parseDouble (String string, Locale locale, boolean strict)
      throws ParseException
    {
        return parseDouble(string, null, locale, strict);
    }

    /**
        Tries to parse the given string as a <code>double</code> in the given
        locale.  The <code>locale</code> parameter must be non-null.

        @param     string the string to parse as a <code>double</code>
        @param     pattern the DecimalFormat pattern to use for parsing
        @param     locale the <code>Locale</code> to use for parsing
        @return           a <code>double</code> value derived from the string
        @exception        ParseException if the string cannot be parsed as an
                          <code>double</code>
        @aribaapi documented
        @see java.text.DecimalFormat
    */
    public static double parseDouble (String string, String pattern, Locale locale)
      throws ParseException
    {
        return parseDouble(string, pattern, locale, false);
    }

    /**
        Tries to parse the given string as a <code>double</code> in the given
        locale.  The <code>locale</code> parameter must be non-null.

        @param     string the string to parse as a <code>double</code>
        @param     pattern the DecimalFormat pattern to use for parsing
        @param     locale the <code>Locale</code> to use for parsing
        @return           a <code>double</code> value derived from the string
        @exception        ParseException if the string cannot be parsed as an
                          <code>double</code>
        @aribaapi documented
        @see java.text.DecimalFormat
    */
    public static synchronized double parseDouble (
        String string, String pattern, Locale locale, boolean strict)
      throws ParseException
    {
            // locale must be non-null
        Assert.that(locale != null, "invalid null Locale");

        DecimalFormat specifiedFormat = null;
        DecimalFormat canonicalFormat = null;
        try {
            specifiedFormat = acquireDecimalFormat(locale, pattern);
            Number number;
            if (strict) {
                // guard
                assertValidGroupingSeparators(string, specifiedFormat);

                // parse with passed in values
                ParsePosition parsePosition = new ParsePosition(0);
                number = specifiedFormat.parse(string, parsePosition);
                int parseEndIndex = parsePosition.getIndex();
                boolean parsedWithSpecifiedFormat =
                    parseEndIndex == string.length() && number != null;

                // parse with canonical values if previous failed
                boolean parsedWithCanonicalFormat = false;
                if (!parsedWithSpecifiedFormat) {
                    canonicalFormat = acquireDecimalFormat(locale, CanonicalPattern);
                    parsePosition.setIndex(0);
                    number = canonicalFormat.parse(string, parsePosition);
                    parseEndIndex = parsePosition.getIndex();
                    parsedWithCanonicalFormat =
                        parseEndIndex == string.length() && number != null;
                }

                // throw exception if no parse succeeded
                boolean failedParse =
                    !parsedWithSpecifiedFormat && !parsedWithCanonicalFormat;
                if (failedParse) {
                    throw new ParseException(
                        "Parse ended before index [" + string.length() + "], " +
                            "it parsed [" + number + "].",
                        parseEndIndex);
                }
            }
            else {
                number = specifiedFormat.parse(string);
            }
            if (number == null) {
                throw new ParseException("Null parse for [" + string + "]", 0);
            }
            return number.doubleValue();
        }
        catch (Exception e) {
            ParseException parseException = new ParseException("Error parsing double.", 0);
            parseException.initCause(e);
            throw parseException;
        }
        finally
        {
            releaseDecimalFormat(specifiedFormat,locale, pattern);
            // canonicalFormat can be null
            releaseDecimalFormat(canonicalFormat, locale, CanonicalPattern);
        }
    }

    protected static ConcurrentMap<DecimalFormat, Pattern> groupingSeparatorsPatternCache
        = new ConcurrentHashMap();

    protected static final Pattern FractionOnly = Pattern.compile("^\\D*\\.");

    protected static void assertValidGroupingSeparators (
        String inputString, DecimalFormat fmt)
      throws ParseException
    {
        // guard: ensure that we're grouping
       
        int groupingSize = fmt.getGroupingSize();
        String groupingSeparator =
            String.valueOf(fmt.getDecimalFormatSymbols().getGroupingSeparator());
       
        boolean notGrouping =
            !fmt.isGroupingUsed()
            || groupingSize <= 0
            || StringUtil.nullOrEmptyOrBlankString(groupingSeparator)
            || FractionOnly.matcher(inputString).find();
        if (notGrouping) {
            // nothing to check
            return;
        }

        // body
       
        Pattern groupingPattern = groupingSeparatorsPatternCache.get(fmt);
        boolean cacheMiss = groupingPattern == null;

        if (cacheMiss) {
            groupingPattern = createGroupingSeparatorPattern(fmt);
            groupingSeparatorsPatternCache.put(fmt, groupingPattern);

        }

        // verify
        Matcher matcher = groupingPattern.matcher(inputString);
        boolean invalidGroupingSeparators = !matcher.find() || matcher.start() != 0;
        if (invalidGroupingSeparators) {
            throw makeParseException(InvalidCharacterInNumberKey, 0);
        }

        // verified!  Do nothing.
    }

    protected static Pattern createGroupingSeparatorPattern (DecimalFormat fmt)
    {
        // create regex

        // create negative prefix / positive prefix regex
        char minusChar = fmt.getDecimalFormatSymbols().getMinusSign();
        String localizedMinusSign = String.valueOf(minusChar);
        // StringUtil.escapeRegEx() fails to escape -
        if (!StringUtil.nullOrEmptyOrBlankString(localizedMinusSign)) {
            localizedMinusSign = StringUtil.strcat("\\", localizedMinusSign);
        }
        String canonicalMinusSign = StringUtil.strcat("\\", CanonicalNegativePrefix);
        // make optional negativePrefix
        String negativePrefix = fmt.getNegativePrefix();
        if (!StringUtil.nullOrEmptyOrBlankString(negativePrefix)) {
            negativePrefix = StringUtil.escapeRegEx(negativePrefix);
//            StringUtil.strcat(negativePrefix, "?");
        }
        String positivePrefix = fmt.getPositivePrefix();
        String prefixes = StringUtil.strcat(
            canonicalMinusSign, localizedMinusSign, positivePrefix, CanonicalPositivePrefix, negativePrefix);
        String negativeSigns = Fmt.S("^\\s*[%s]?\\s*", prefixes);

        // create initial ungrouped digits regex
        int groupingSize = fmt.getGroupingSize();
        String firstDigits = Fmt.S("\\d{1,%s}", groupingSize);

        // create additional grouped digits regex
        String groupingSeparator =
            String.valueOf(fmt.getDecimalFormatSymbols().getGroupingSeparator());
        String groupedDigits = Fmt.S("(?:%s\\d{%s})*", groupingSeparator, groupingSize);
//        String finalGroupedDigits = Fmt.S("(?:%s\\D)?", groupedDigits);
       
        // not (digit or grouping separator) or end of string
        String end = Fmt.S("(?:[^\\d%s]|$)", groupingSeparator);

        // create final regex
        String groupingRegex =
            StringUtil.strcat(negativeSigns, firstDigits, groupedDigits, end);

        // compile and done
        return Pattern.compile(groupingRegex);
    }

    public static String getLocalizedPercentSign (Locale locale)
    {
        DecimalFormat format = null;
        try {
            format = acquireDecimalFormat(locale, CanonicalPattern);
            Character ch = format.getDecimalFormatSymbols().getPercent();
            return ch.toString();
        }
        finally {
            releaseDecimalFormat(format, locale, CanonicalPattern);
        }
    }

    public static String getCanonicalPercentSign ()
    {
        return CanonicalPercentSign;
    }

    /**
        Returns a <code>double</code> value derived from the given object in
        the default locale.  If the object is not a <code>Double</code>, it is
        converted to a string and parsed.  Returns <code>0.0</code> if the
        object can't be converted to a <code>double</code>.

        @param  object the object to convert to an <code>double</code> value
        @return        a <code>double</code> derived from the given object
        @aribaapi documented
    */
    public static double getDoubleValue (Object object)
    {
        return getDoubleValue(object, getDefaultLocale());
    }

    /**
        Returns a <code>double</code> value derived from the given object in
        the default locale.  If the object is not a <code>Double</code>, it is
        converted to a string and parsed.  Returns <code>0.0</code> if the
        object can't be converted to a <code>double</code>.

        @param  object the object to convert to an <code>double</code> value
        @param  locale the <code>Locale</code> to use for conversion
        @return        a <code>double</code> derived from the given object
        @aribaapi documented
    */
    public static double getDoubleValue (Object object, Locale locale)
    {
        if (object == null) {
            return 0.0;
        }
        else if (object instanceof Number) {
            return ((Number)object).doubleValue();
        }
        else {
            String string = object.toString();
            try {
                return parseDouble(string, locale);
            }
            catch (ParseException e) {
                return 0.0;
            }
        }
    }


    /*-----------------------------------------------------------------------
        Static Comparison
      -----------------------------------------------------------------------*/

    /**
        Compares two <code>Double</code> objects for sorting purposes.  Returns
        an <code>int</code> value which is less than, equal to, or greater
        than zero depending on whether the first object sorts before, the
        same, or after the second object.

        @param  d1 the first <code>Double</code> to compare
        @param  d2 the second <code>Double</code> to compare
        @return    <code>int</code> value which determines how the two objects
                   should be ordered
        @aribaapi documented
    */
    public static int compareDoubles (Double d1, Double d2)
    {
        if (d1 == d2) {
            return 0;
        }
        else if (d1 == null) {
            return -1;
        }
        else if (d2 == null) {
            return 1;
        }
        else {
            return compareDoubles(d1.doubleValue(), d2.doubleValue());
        }
    }

    /**
        Compares two <code>double</code> values for sorting purposes.  Returns
        an <code>int</code> value which is less than, equal to, or greater
        than zero depending on whether the first value sorts before, the
        same, or after the second value.

        @param  d1 the first <code>double</code> to compare
        @param  d2 the second <code>double</code> to compare
        @return    <code>int</code> value which determines how the two values
                   should be ordered
        @aribaapi documented
    */
    public static int compareDoubles (double d1, double d2)
    {
        if (d1 > d2) {
            return 1;
        }
        else if (d1 < d2) {
            return -1;
        }
        else {
            return 0;
        }
    }


    /*-----------------------------------------------------------------------
        !!! Flexible Double !!!
      -----------------------------------------------------------------------*/

    /**
        Flexible conversion of a string into a Double.  Converts decimal
        format, as well as fractional format like "12 3/8 = 12.375" or "1-3/4
        = 1.75". Also supports localized format: "12,3/4 = 12.75".  If it
        cannot convert, it returns null.

        @aribaapi private
    */
    public static Double flexibleDoubleValue (Object stringValue)
    {
        try {
            double doubleValue;
            String string = stringValue.toString().trim();

            int slashIndex = string.indexOf('/');

                // decimal format
            if (slashIndex == -1) {
                doubleValue = parseDouble(string, null);
            }
                // fractional format
            else {
                String whole = null;
                String numerator = null;
                String denominator = null;

                    // Check for negative
                boolean isNegative = string.startsWith("-");

                    // Replace minus or comma with space delimiter
                string = string.replace('-', ' ');
                string = string.replace(',', ' ');

                    // search for space, for delimiter after whole number
                int spaceIndex = string.lastIndexOf(' ', slashIndex);

                    // fraction only
                if (spaceIndex == -1 || spaceIndex == 0) {
                    numerator = string.substring(0, slashIndex);
                    denominator = string.substring(slashIndex+1);
                }
                    // whole amount as well
                else {
                    whole = string.substring(0, spaceIndex);
                    numerator = string.substring(spaceIndex+1, slashIndex);
                    denominator = string.substring(slashIndex+1);
                }

                Integer integer;
                double wholeValue = 0.0;
                double numeratorValue = 0.0;
                double denominatorValue = 0.0;

                if (whole != null) {
                    integer = Integer.valueOf(whole.trim());
                    wholeValue = integer.doubleValue();
                }
                integer = Integer.valueOf(numerator.trim());
                numeratorValue = integer.doubleValue();
                integer = Integer.valueOf(denominator.trim());
                denominatorValue = integer.doubleValue();

                double d = 0.0;
                if (denominatorValue == 0.0) {
                    d = wholeValue;
                }
                else {
                    d = wholeValue + (numeratorValue / denominatorValue);
                }

                if (isNegative) {
                    d = d * -1.0;
                }

                doubleValue = d;
            }
            return new Double(doubleValue);
        }
        catch (ParseException e) {
            return null;
        }
        catch (NumberFormatException e) {
            return null;
        }
    }


    /*-----------------------------------------------------------------------
        Formatting
      -----------------------------------------------------------------------*/

    /**
        Returns a string representation of the given object in the given
        locale.  The object must be a non-null <code>Double</code>.

        @param  object the <code>Double</code> to format into a string
        @param  locale the <code>Locale</code> to use for formatting
        @return        a string representation of the <code>Double</code>
        @aribaapi documented
    */
    protected String formatObject (Object object, Locale locale)
    {
        Assert.that(object instanceof Double, "invalid type");
        return getStringValue((Double)object, locale);
    }

    /**
        Returns a string representation of the given object in the given
        locale with the given precision.
        The object must be a non-null <code>Double</code>.

        @param  object the <code>Double</code> to format into a string
        @param  precision the number of fractional digits to show
        @param  locale the <code>Locale</code> to use for formatting
        @return        a string representation of the <code>Double</code>
        @aribaapi documented
    */
    public String formatObject (Object object, int precision, Locale locale)
    {
        Assert.that(object instanceof Double, "invalid type");
        return getStringValue((Double)object, precision, locale);
    }

    /*-----------------------------------------------------------------------
        Parsing
      -----------------------------------------------------------------------*/

    /**
        Tries to parse the given string into a <code>Double</code> object in
        the given locale.  The string is assumed to be non-null and trimmed of
        leading and trailing whitespace.

        @param     string the string to parse
        @param     locale the <code>Locale</code> to use for parsing (unused)
        @return           a <code>Double</code> object derived from the string
        @exception        ParseException if the string can't be parsed as a
                          <code>Double</code> object in the given locale
        @aribaapi documented
    */
    protected Object parseString (String string, Locale locale)
      throws ParseException
    {
        return new Double(parseDouble(string, locale));
    }

    /**
        Returns a new <code>Double</code> derived from the given object in the
        given locale.  If the object is not a <code>Double</code>, it is
        converted to a string and parsed.  Returns null if the object can't be
        parsed as a <code>Double</code>.

        @param  object the object to convert to a <code>Double</code>
        @param  locale the <code>Locale</code> to use for conversion (unused)
        @return        a <code>Double</code> derived from the given object
        @aribaapi documented
    */
    public Object getValue (Object object, Locale locale)
    {
        return new Double(getDoubleValue(object, locale));
    }


    /*-----------------------------------------------------------------------
        Comparison
      -----------------------------------------------------------------------*/

    /**
        Compares two objects for sorting purposes in the given locale.  The
        two objects must be non-null <code>Double</code> objects.  Returns a
        value which is less than, equal to, or greater than zero depending on
        whether the first object sorts before, the same, or after the second
        object.  The <code>locale</code> parameter is currently unused.

        @param  o1     the first <code>Double</code> to compare
        @param  o2     the second <code>Double</code> to compare
        @param  locale the <code>Locale</code> to use for comparison (unused)
        @return        <code>int</code> value which determines how the two
                       objects should be ordered
        @aribaapi documented
    */
    protected int compareObjects (Object o1, Object o2, Locale locale)
    {
        Assert.that(o1 instanceof Double, "invalid type");
        Assert.that(o2 instanceof Double, "invalid type");

        return compareDoubles((Double)o1, (Double)o2);
    }


    /*-----------------------------------------------------------------------
        Private Methods
      -----------------------------------------------------------------------*/

    /*-----------------------------------------------------------------------
        Caching
      -----------------------------------------------------------------------*/
    protected Format instantiateFormat (int type, Locale locale, String pattern)
    {
        pattern = (pattern == null) ? "" : pattern;
        DecimalFormat fmt = (DecimalFormat)NumberFormat.getNumberInstance(locale);
        if (!StringUtil.nullOrEmptyString(pattern)) {
            fmt.applyLocalizedPattern(pattern);
        }
        fmt.setGroupingUsed(true);
        return fmt;
    }

    private static DecimalFormat acquireDecimalFormat (Locale locale)
    {
        return acquireDecimalFormat(locale, null);
    }

    private static DecimalFormat acquireDecimalFormat (Locale locale, String pattern)
    {
        return (DecimalFormat)factory.acquireFormat(
                        Formatter.DoubleFormatterType, locale, pattern);
    }

    private static void releaseDecimalFormat (DecimalFormat df,Locale locale)
    {
        releaseDecimalFormat(df, locale, null);
    }

    private static void releaseDecimalFormat (
        DecimalFormat df,Locale locale, String pattern)
    {
        factory.releaseFormat(df, Formatter.DoubleFormatterType,
                                locale, pattern);
    }

}
TOP

Related Classes of ariba.util.formatter.DoubleFormatter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.