/*
* Copyright 1990-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 only, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License version 2 for more details (a copy is
* included at /legal/license.txt).
*
* You should have received a copy of the GNU General Public License
* version 2 along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 or visit www.sun.com if you need additional
* information or have any questions.
*/
package com.sun.j2me.global;
import java.util.Calendar;
import java.util.Hashtable;
import javax.microedition.global.Formatter;
import javax.microedition.global.ResourceManager;
import javax.microedition.global.ResourceException;
import javax.microedition.global.UnsupportedLocaleException;
import com.sun.j2me.log.Logging;
import com.sun.j2me.log.LogChannels;
/**
* This class actually realizes most of the methods of
* {@link javax.microedition.global.Formatter}. Specifically, these are:
* <ul>
* <li> {@link #formatDateTime(Calendar, int)}
* <li> {@link #formatCurrency(double)}
* <li> {@link #formatCurrency(double, String)}
* <li> {@link #formatNumber(double)}
* <li> {@link #formatNumber(double, int)}
* <li> {@link #formatNumber(long)}
* <li> {@link #formatPercentage(long number)}
* <li> {@link #formatPercentage(float, int)}
* </ul>
*/
public class FormatterImpl implements CommonFormatter {
/**
* Current FormatterImpl locale code.
*/
private String locale;
/**
* Formatting symbols for locale.
*/
private NumberFormatSymbols symbols = null;
/**
* Formatting symbols cache.
*/
private static Hashtable symbols_cache = new Hashtable();
/**
* Resource ID for the Number Format Symbol Resource
*/
private static int NUMBER_FORMAT_SYMBOL_RESOURCE_ID = 0x7ffffffe;
/**
* Resource ID for the DateTime Format Symbol Resource
*/
private static int DATETIME_FORMAT_SYMBOL_RESOURCE_ID = 0x7ffffffd;
/**
* Constructs a formatter implementation for the specified locale.
*
* @param locale desired FormatterImpl locale.
* @throws UnsupportedLocaleException The exception
* is thrown when locale isn't supported.
*/
public FormatterImpl(String locale) throws UnsupportedLocaleException {
int locale_index = LocaleHelpers.indexInSupportedLocales(locale,
Formatter.getSupportedLocales());
if (locale_index == -1) {
throw new UnsupportedLocaleException("Locale \""
+ locale +
"\" unsupported.");
}
this.locale = locale;
}
/**
* Creates and returns a set of symbols for number formatting.
*
* @return <code>NumberFormatSymbols</code> instance for current locale
*/
private NumberFormatSymbols getNumberFormatSymbols() {
if (symbols == null) {
symbols = (NumberFormatSymbols)symbols_cache.get(locale);
if (symbols == null) {
try {
ResourceManager rm = ResourceManager.getManager(
ResourceManager.DEVICE, locale);
symbols = (NumberFormatSymbols)rm.getResource(
NUMBER_FORMAT_SYMBOL_RESOURCE_ID);
} catch (NullPointerException npe_ignore) {
/* intentionally ignored */
if (Logging.REPORT_LEVEL <= Logging.ERROR) {
Logging.report(Logging.ERROR, LogChannels.LC_JSR238,
"Base name or locale is null");
}
} catch (IllegalArgumentException iae_ignore) {
/* intentionally ignored */
if (Logging.REPORT_LEVEL <= Logging.ERROR) {
Logging.report(Logging.ERROR, LogChannels.LC_JSR238,
"Locale identifier is not valid" + locale);
}
} catch (ResourceException re_ignore) {
/* intentionally ignored */
if (Logging.REPORT_LEVEL <= Logging.ERROR) {
Logging.report(Logging.ERROR, LogChannels.LC_JSR238,
"No resources are found or the resource file is invalid");
}
} catch (UnsupportedLocaleException ule_ignore) {
/* intentionally ignored */
if (Logging.REPORT_LEVEL <= Logging.ERROR) {
Logging.report(Logging.ERROR, LogChannels.LC_JSR238,
"Locale is not listed in the meta-information file"
+ locale);
}
}
if (symbols == null) {
if (Logging.REPORT_LEVEL <= Logging.WARNING) {
Logging.report(Logging.WARNING, LogChannels.LC_JSR238,
"Using neutral locale symbols for locale: "
+ locale);
}
symbols = new NumberFormatSymbols();
}
}
symbols_cache.put(locale, symbols);
}
return symbols;
}
// JAVADOC COMMENT ELIDED
public String formatDateTime(Calendar dateTime, int style) {
try {
ResourceManager rm = ResourceManager.getManager(
ResourceManager.DEVICE, locale);
DateFormatSymbols symbols = (DateFormatSymbols)rm.getResource(
DATETIME_FORMAT_SYMBOL_RESOURCE_ID);
DateTimeFormat dtf = new DateTimeFormat(style, symbols);
NumberFormat nf = new NumberFormat(NumberFormat.INTEGERSTYLE,
getNumberFormatSymbols());
return dtf.format(dateTime, nf);
} catch (NullPointerException npe_ignore) {
/* intentionally ignored */
if (Logging.REPORT_LEVEL <= Logging.WARNING) {
Logging.report(Logging.WARNING, LogChannels.LC_JSR238,
"Base name or locale is null");
}
} catch (IllegalArgumentException iae_ignore) {
/* intentionally ignored */
if (Logging.REPORT_LEVEL <= Logging.WARNING) {
Logging.report(Logging.WARNING, LogChannels.LC_JSR238,
"locale identifier is not valid" + locale);
}
} catch (ResourceException re_ignore) {
/* intentionally ignored */
if (Logging.REPORT_LEVEL <= Logging.WARNING) {
Logging.report(Logging.WARNING, LogChannels.LC_JSR238,
"No resources are found or the resource file is invalid");
}
} catch (UnsupportedLocaleException ule_ignore) {
/* intentionally ignored */
if (Logging.REPORT_LEVEL <= Logging.WARNING) {
Logging.report(Logging.WARNING, LogChannels.LC_JSR238,
"Locale is not listed in the meta-information file"
+ locale);
}
}
return "";
}
// JAVADOC COMMENT ELIDED
public String formatCurrency(double number) {
NumberFormat nf = new NumberFormat(NumberFormat.CURRENCYSTYLE,
getNumberFormatSymbols());
if (Double.isInfinite(number) ||
Double.isNaN(number)) {
String oldSymbol = nf.setCurrencySymbol("");
String formatted = nf.format(number);
nf.setCurrencySymbol(oldSymbol);
return formatted;
} else {
return nf.format(number);
}
}
// JAVADOC COMMENT ELIDED
public String formatCurrency(double number, String currencyCode) {
NumberFormat nf = new NumberFormat(NumberFormat.CURRENCYSTYLE,
getNumberFormatSymbols());
String symbol = "";
if (!(Double.isInfinite(number) ||
Double.isNaN(number))) {
symbol = nf.getCurrencySymbolForCode(currencyCode);
if (symbol == null) {
symbol = currencyCode;
}
}
String oldSymbol = nf.setCurrencySymbol(symbol);
String formatted = nf.format(number);
nf.setCurrencySymbol(oldSymbol);
return formatted;
}
// JAVADOC COMMENT ELIDED
public String formatNumber(double number) {
NumberFormat nf = new NumberFormat(NumberFormat.NUMBERSTYLE,
getNumberFormatSymbols());
return nf.format(number);
}
// JAVADOC COMMENT ELIDED
public String formatNumber(double number, int decimals) {
NumberFormat nf = new NumberFormat(NumberFormat.NUMBERSTYLE,
getNumberFormatSymbols());
nf.setMinimumFractionDigits(decimals);
nf.setMaximumFractionDigits(decimals);
return nf.format(number);
}
/**
* Formats an integer using locale-specific rules. The result may include
* grouping separators.
*
* @param number the number to format
* @return formatted integer number
*/
public String formatNumber(long number) {
NumberFormat nf = new NumberFormat(NumberFormat.INTEGERSTYLE,
getNumberFormatSymbols());
return nf.format(number);
}
// JAVADOC COMMENT ELIDED
public String formatPercentage(long number) {
NumberFormat nf = new NumberFormat(NumberFormat.PERCENTSTYLE,
getNumberFormatSymbols());
nf.setMultiplier(1);
return nf.format(number);
}
// JAVADOC COMMENT ELIDED
public String formatPercentage(float number, int decimals) {
NumberFormat nf = new NumberFormat(NumberFormat.PERCENTSTYLE,
getNumberFormatSymbols());
nf.setMinimumFractionDigits(1);
nf.setMaximumFractionDigits(decimals);
return nf.format(number);
}
}