private String formatNumber()

in core/cocoon-core/src/main/java/org/apache/cocoon/transformation/I18nTransformer.java [1985:2131]


    private String formatNumber(Map params) throws SAXException {
        if (params == null) {
            throw new SAXException(
                    this.getClass().getName()
                    + ": i18n:number - error in element attributes."
            );
        }

        // from pattern
        String srcPattern = (String)params.get(I18N_SRC_PATTERN_ATTRIBUTE);
        // to pattern
        String pattern = (String)params.get(I18N_PATTERN_ATTRIBUTE);
        // the number value
        String value = (String)params.get(I18N_VALUE_ATTRIBUTE);

        if (value == null) return "";
        // type
        String type = (String)params.get(I18N_TYPE_ATTRIBUTE);

        // fraction-digits
        int fractionDigits = -1;
        try {
            String fd = (String)params.get(I18N_FRACTION_DIGITS_ATTRIBUTE);
            if (fd != null)
                fractionDigits = Integer.parseInt(fd);
        } catch (NumberFormatException nfe) {
            getLogger().warn("Error in number format with fraction-digits", nfe);
        }

        // parsed number
        Number numberValue;

        // locale, may be switched locale
        Locale loc = getLocale(params, I18N_LOCALE_ATTRIBUTE);
        Locale srcLoc = getLocale(params, I18N_SRC_LOCALE_ATTRIBUTE);
        // currency locale
        Locale currencyLoc = getLocale(params, CURRENCY_LOCALE_ATTRIBUTE);
        // decimal and grouping locale
        Locale dgLoc = null;
        if (currencyLoc != null) {
            // the reasoning here is: if there is a currency locale, then start from that
            // one but take certain properties (like decimal and grouping seperation symbols)
            // from the default locale (this happens further on).
            dgLoc = loc;
            loc = currencyLoc;
        }

        // src format
        DecimalFormat from_fmt = (DecimalFormat)NumberFormat.getInstance(srcLoc);
        int int_currency = 0;

        // src-pattern overwrites locale format
        if (srcPattern != null) {
            from_fmt.applyPattern(srcPattern);
        }

        // to format
        DecimalFormat to_fmt;
        char dec = from_fmt.getDecimalFormatSymbols().getDecimalSeparator();
        int decAt = 0;
        boolean appendDec = false;

        if (type == null || type.equals( I18N_NUMBER_ELEMENT )) {
            to_fmt = (DecimalFormat)NumberFormat.getInstance(loc);
            to_fmt.setMaximumFractionDigits(309);
            for (int i = value.length() - 1;
                 i >= 0 && value.charAt(i) != dec; i--, decAt++) {
            }

            if (decAt < value.length())to_fmt.setMinimumFractionDigits(decAt);
            decAt = 0;
            for (int i = 0; i < value.length() && value.charAt(i) != dec; i++) {
                if (Character.isDigit(value.charAt(i))) {
                    decAt++;
                }
            }

            to_fmt.setMinimumIntegerDigits(decAt);
            if (value.charAt(value.length() - 1) == dec) {
                appendDec = true;
            }
        } else if (type.equals( I18N_CURRENCY_ELEMENT )) {
            to_fmt = (DecimalFormat)NumberFormat.getCurrencyInstance(loc);
        } else if (type.equals( I18N_INT_CURRENCY_ELEMENT )) {
            to_fmt = (DecimalFormat)NumberFormat.getCurrencyInstance(loc);
            int_currency = 1;
            for (int i = 0; i < to_fmt.getMaximumFractionDigits(); i++) {
                int_currency *= 10;
            }
        } else if ( type.equals( I18N_CURRENCY_NO_UNIT_ELEMENT ) ) {
            DecimalFormat tmp = (DecimalFormat) NumberFormat.getCurrencyInstance( loc );
            to_fmt = (DecimalFormat) NumberFormat.getInstance( loc );
            to_fmt.setMinimumFractionDigits(tmp.getMinimumFractionDigits());
            to_fmt.setMaximumFractionDigits(tmp.getMaximumFractionDigits());
        } else if ( type.equals( I18N_INT_CURRENCY_NO_UNIT_ELEMENT ) ) {
            DecimalFormat tmp = (DecimalFormat) NumberFormat.getCurrencyInstance( loc );
            int_currency = 1;
            for ( int i = 0; i < tmp.getMaximumFractionDigits(); i++ )
                int_currency *= 10;
            to_fmt = (DecimalFormat) NumberFormat.getInstance( loc );
            to_fmt.setMinimumFractionDigits(tmp.getMinimumFractionDigits());
            to_fmt.setMaximumFractionDigits(tmp.getMaximumFractionDigits());
        } else if (type.equals( I18N_PERCENT_ELEMENT )) {
            to_fmt = (DecimalFormat)NumberFormat.getPercentInstance(loc);
        } else {
            throw new SAXException("&lt;i18n:number>: unknown type: " + type);
        }

        if(fractionDigits > -1) {
            to_fmt.setMinimumFractionDigits(fractionDigits);
            to_fmt.setMaximumFractionDigits(fractionDigits);
        }

        if(dgLoc != null) {
            DecimalFormat df = (DecimalFormat)NumberFormat.getCurrencyInstance(dgLoc);
            DecimalFormatSymbols dfsNew = df.getDecimalFormatSymbols();
            DecimalFormatSymbols dfsOrig = to_fmt.getDecimalFormatSymbols();
            dfsOrig.setDecimalSeparator(dfsNew.getDecimalSeparator());
            dfsOrig.setMonetaryDecimalSeparator(dfsNew.getMonetaryDecimalSeparator());
            dfsOrig.setGroupingSeparator(dfsNew.getGroupingSeparator());
            to_fmt.setDecimalFormatSymbols(dfsOrig);
        }

        // pattern overwrites locale format
        if (pattern != null) {
            to_fmt.applyPattern(pattern);
        }

        try {
            numberValue = from_fmt.parse(value);
            if (int_currency > 0) {
                numberValue = new Double(numberValue.doubleValue() / int_currency);
            } else {
                // what?
            }
        } catch (ParseException pe) {
            throw new SAXException(this.getClass().getName() + "i18n:number - parsing error.", pe);
        }

        // we have all necessary data here: do formatting.
        String result = to_fmt.format(numberValue);
        if (appendDec) result = result + dec;
        if (getLogger().isDebugEnabled()) {
            getLogger().debug("i18n:number result: " + result);
        }
        return result;
    }