FileDocCategorySizeDatePackage
LocaleBean.javaAPI DocExample12996Thu Jun 28 16:14:16 BST 2001com.ora.jsp.beans.locale

LocaleBean.java

package com.ora.jsp.beans.locale;

import java.io.*;
import java.text.*;
import java.util.*;

/**
 * This class contains a number of methods for dealing with
 * localized content. It's used by the com.ora.jsp.tags.generic
 * localization tag handler classes, but can also be used
 * stand-alone.
 *
 * @author Hans Bergsten, Gefion software <hans@gefionsoftware.com>
 * @version 1.0
 */
public class LocaleBean implements Serializable {
    private Locale locale;
    private Locale[] requestLocales;
    private ResourceBundle bundle;
    private String supportedLangs;
    private String bundleName;
    private String language;
    private NumberFormat numberFormat;
    private DateFormat dateFormat;
    private String charset;
    private Hashtable parameters;
    
    /**
     * Returns a Locale. The Locale is constructed based on the
     * language property, if set. If not, the Locale determined
     * based on the Accept-Language header (the requestLocales
     * property) is returned, if set. If the Locale found this way
     * matches one of the supported languages, it's returned.
     * Otherwise the Locale for first language in the list of supported
     * languages is returned.
     */
    public Locale getLocale() {
        if (locale == null) {
            if (language != null && isSupportedLang(language)) {
                locale = toLocale(language);
            }
            else if (requestLocales != null) {
                locale = getSupportedLocale(requestLocales);
            }
            if (locale == null) {
                locale = getDefaultLocale();
            }
        }
        return locale;
    }

    /**
     * Sets the set of locales received with the request, and
     * resets the currently selected locale if the new set
     * is different from the current set. This is done so that
     * all possible locale sources will be evaluated again the
     * next time the locale property is retrieved.
     */
    public void setRequestLocales(Locale[] locales) {
        if (requestLocales != null && !isEqual(requestLocales, locales)) {
            resetLocale();
        }
        requestLocales = locales;
    }
    
    /**
     * Sets the set of supported languages, provided as a comma
     * separated list of country/language codes. This is a
     * mandatory property.
     * <p>
     * Resets the currently selected locale if the new set
     * is different from the current set. This is done so that
     * all possible locale sources will be evaluated again the
     * next time the locale property is retrieved.
     */
    public void setSupportedLangs(String supportedLangs) {
        if (this.supportedLangs != null && 
            !this.supportedLangs.equals(supportedLangs)) {
            resetLocale();
        }
        this.supportedLangs = supportedLangs;
    }
    
    /**
     * Returns the language code for the currently selected
     * locale.
     */
    public String getLanguage() {
        if (language == null) {
            language = toLanguage(getLocale());
        }
        return language;
    }
    
    /**
     * Sets the user selected language/country code.
     * <p>
     * Resets the currently selected locale if the new language
     * is different from the current. This is done so that
     * all possible locale sources will be evaluated again the
     * next time the locale property is retrieved.
     */
    public void setLanguage(String language) {
        if (this.language != null && !language.equals(this.language)) {
            resetLocale();
        }
        this.language = language;
    }
    
    /**
     * Sets the bundle name.
     * <p>
     * Resets the current ResourceBundle so that a new will
     * be created with the new bundle name the
     * next time the ResourceBundle is retrieved.
     */
    public void setBundleName(String bundleName) {
        if (this.bundleName != null && !bundleName.equals(this.bundleName)) {
            resetBundle();
        }
        this.bundleName = bundleName;
    }
    
    /**
     * Sets the charset used to parse request parameters.
     */
    public void setCharset(String charset) {
        this.charset = charset;
    }
    
    /**
     * Returns the specified number String converted to a
     * double, parsed as defined by the currently selected locale.
     */
    public double getDouble(String number) throws ParseException {
        return getNumber(number).doubleValue();
    }
        
    /**
     * Returns the specified number String converted to a
     * float, parsed as defined by the currently selected locale.
     */
    public float getFloat(String number) throws ParseException {
        return getNumber(number).floatValue();
    }
        
    /**
     * Returns the specified number String converted to a
     * int, parsed as defined by the currently selected locale.
     */
    public int getInt(String number) throws ParseException {
        return getNumber(number).intValue();
    }
        
    /**
     * Returns the specified number String converted to a
     * long, parsed as defined by the currently selected locale.
     */
    public long getLong(String number) throws ParseException {
        return getNumber(number).longValue();
    }
        
    /**
     * Returns the specified date String converted to a
     * Date, parsed as defined by the currently selected locale.
     */
    public Date getDate(String date) throws ParseException {
        if (dateFormat == null) {
            dateFormat = DateFormat.getDateInstance(dateFormat.FULL, getLocale());
        }
        return dateFormat.parse(date);
    }
    
    /**
     * Returns the specified number converted to a
     * String, formatted as defined by the currently selected locale.
     */
    public String getNumberString(double number) {
        if (numberFormat == null) {
            numberFormat = NumberFormat.getNumberInstance(getLocale());
        }
        return numberFormat.format(number);
    }
        
    /**
     * Returns the specified Date converted to a
     * String, formatted as defined by the currently selected locale.
     */
    public String getDateString(Date date) {
        if (dateFormat == null) {
            dateFormat = DateFormat.getDateInstance(dateFormat.FULL, getLocale());
        }
        return dateFormat.format(date);
    }
    
    /**
     * Returns the text resource for the specified key,
     * with the best match for the currently selected locale.
     */
    public String getText(String resourceName) {
        if (bundle == null) {
            bundle = ResourceBundle.getBundle(bundleName, getLocale());
        }
        return bundle.getString(resourceName);
    }
    
    /**
     * Returns a version of the specified page name with 
     * a language/country suffix for the currently selected locale.
     */
    public String getPageName(String basePageName) {
        StringBuffer pageName = new StringBuffer();
        Locale locale = getLocale();
        if (locale.equals(getDefaultLocale())) {
            pageName.append(basePageName);
        }
        else {
            String suffix = getLocale().toString();
            int extPos = basePageName.indexOf(".");
            if (extPos != -1) {
                pageName.append(basePageName.substring(0, extPos)).
                    append("_").append(suffix).
                    append(basePageName.substring(extPos));
            }
            else {
                pageName.append(basePageName).
                    append("_").append(suffix);
            }
        }
        return pageName.toString();
    }
    
    /**
     * Sets the parameter list.
     */
    public void setParameters(Hashtable parameters) {
        this.parameters = parameters;
    }
    
    /**
     * Returns an array of all values for the specified parameter,
     * parsed using the currently specified charset.
     */
    public String[] getParameterValues(String parameter) 
        throws UnsupportedEncodingException {
        String[] values = null;
        if (parameters != null) {
            String[] encodedValues = (String[]) parameters.get(parameter);
            if (encodedValues != null) {
                values = new String[encodedValues.length];
                for (int i = 0; i < encodedValues.length; i++) {
                    values[i] = getDecodedValue(encodedValues[i]);
                }
            }
        }
        return values;
    }
    
    /**
     * Returns an Enumeration of all parameter names.
     */
    public Enumeration getParameterNames() {
        if (parameters == null) {
            parameters = new Hashtable();
        }
        return parameters.keys();
    }
    
    /**
     * Returns the first all value for the specified parameter,
     * parsed using the currently specified charset.
     */
    public String getParameter(String parameter) 
        throws UnsupportedEncodingException {
        String firstValue = null;
        String[] values = getParameterValues(parameter);
        if (values != null && values.length > 0) {
            firstValue = values[0];
        }
        return firstValue;
    }
    
    /**
     * Resets the ResourceBundle.
     */
    private void resetBundle() {
        bundle = null;
    }
    
    /**
     * Resets all locale dependent variables.
     */
    private void resetLocale() {
        locale = null;
        numberFormat = null;
        dateFormat = null;
        bundle = null;
    }
    
    /**
     * Returns true if the the specifed Locale arrays contains
     * exactly the same locale information.
     */
    private boolean isEqual(Locale[] arr1, Locale[] arr2) {
        boolean isEqual = true;
        if (arr1.length != arr2.length) {
            isEqual = false;
        }
        else {
            for (int i = 1; i < arr1.length; i++) {
                if (!arr1[i].equals(arr2[i])) {
                    isEqual = false;
                    break;
                }
            }
        }
        return isEqual;
    }

    /**
     * Returns true if the specified languge is a supported language.
     */
    private boolean isSupportedLang(String language) {
        return supportedLangs.indexOf(language) != -1;
    }
    
    /**
     * Returns a Locale for the default language.
     */
    private Locale getDefaultLocale() {
        StringTokenizer st = new StringTokenizer(supportedLangs, ",");
        String defaultLang = st.nextToken().trim();
        return toLocale(defaultLang);
    }
    
    /**
     * Returns a Locale for the specifed language/country code.
     */
    private Locale toLocale(String language) {
        Locale locale = null;
        int countrySeparator = language.indexOf("-");
        if (countrySeparator != -1) {
            locale = new Locale(language.substring(0, countrySeparator),
                language.substring(countrySeparator + 1));
        }
        else {
            locale = new Locale(language, "");
        }
        return locale;
    }
    
    /**
     * Returns the language/country code for the specified Locale.
     */
    private String toLanguage(Locale locale) {
        String language = locale.getLanguage();
        String country = locale.getCountry();
        if (country != null && country.length() > 0) {
            language = language + "-" + country;
        }
        return language;
    }

    /**
     * Returns the first Locale that matches a supported
     * language, or the default Locale if no match.
     */
    private Locale getSupportedLocale(Locale[] locales) {
        Locale locale = getDefaultLocale();
        for (int i = 0; i < locales.length; i++) {
            if (isSupportedLang(toLanguage(locales[i]))) {
                locale = locales[i];
                break;
            }
        }
        return locale;
    }
    
    /**
     * Returns the specified String as a Number, parsed based on
     * the currently selected locale.
     */
    private Number getNumber(String number) throws ParseException {
        if (numberFormat == null) {
            numberFormat = NumberFormat.getNumberInstance(getLocale());
        }
        return numberFormat.parse(number);
    }
    
    /**
     * This method returns a new String created from the specified String, 
     * encoded as 8859_1 converted to the currently set charset.
     */
    private String getDecodedValue(String value) 
        throws UnsupportedEncodingException {
        if (charset == null) {
            return value;
        }
        return new String(value.getBytes("8859_1"), charset);
    }
}