py.una.pol.karaku.util.I18nHelper.java Source code

Java tutorial

Introduction

Here is the source code for py.una.pol.karaku.util.I18nHelper.java

Source

/*-
 * Copyright (c)
 *
 *       2012-2014, Facultad Politcnica, Universidad Nacional de Asuncin.
 *       2012-2014, Facultad de Ciencias Mdicas, Universidad Nacional de Asuncin.
 *       2012-2013, Centro Nacional de Computacin, Universidad Nacional de Asuncin.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301  USA
 */
package py.una.pol.karaku.util;

import static py.una.pol.karaku.util.Checker.notNull;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;
import javax.annotation.Nonnull;
import javax.annotation.PostConstruct;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import py.una.pol.karaku.configuration.KarakuBaseConfiguration;
import py.una.pol.karaku.configuration.PropertiesUtil;
import py.una.pol.karaku.model.DisplayName;

/**
 * Clase que sirve como punto de acceso nico para la internacionalizacion.
 * 
 * <p>
 * Versin 3 le agrega cadenas parametrizadas, ver
 * {@link #getString(String, Object...)}
 * </p>
 * 
 * @author Arturo Volpe
 * @since 1.0
 * @version 3
 */
public class I18nHelper {

    private static List<ResourceBundle> bundles;

    private static WeakReference<I18nHelper> weakSingleton;

    public static final String I18N_LENIENT = "karaku.i18n.lenient";

    private boolean lenient;

    private static ApplicationContext context;

    @Autowired
    private PropertiesUtil util;

    /**
     * @param context
     *            context para setear
     */
    @Autowired
    protected void setContext(ApplicationContext context) {

        setStaticContext(context);
    }

    /**
     * @return weakSingleton
     */
    public static WeakReference<I18nHelper> getWeakSingleton() {

        return weakSingleton;
    }

    /**
     * @param weakSingleton
     *            weakSingleton para setear
     */
    protected static void setWeakSingleton(WeakReference<I18nHelper> weakSingleton) {

        I18nHelper.weakSingleton = weakSingleton;
    }

    @PostConstruct
    public void initialize() {

        lenient = util.getBoolean(I18N_LENIENT, true);
        String value = util.get(KarakuBaseConfiguration.LANGUAGE_BUNDLES_KEY);
        getSingleton().initializeBundles(Arrays.asList(value.split("\\s+")));
    }

    private static void setStaticContext(ApplicationContext newContext) {

        context = newContext;
    }

    /**
     * Retorna el {@link I18nHelper} que actualmente esta siendo utilizado por
     * la aplicacin.
     * 
     * @return
     */
    public static I18nHelper getSingleton() {

        if (weakSingleton != null) {
            return weakSingleton.get();
        }

        synchronized (I18nHelper.class) {
            if (weakSingleton == null) {
                weakSingleton = new WeakReference<I18nHelper>(context.getBean(I18nHelper.class));
            }
        }
        return weakSingleton.get();
    }

    protected Locale getLocale() {

        return new Locale("es", "PY");
    }

    protected static List<ResourceBundle> getBundles() {

        return bundles;
    }

    protected synchronized void initializeBundles(List<String> bundlesLocation) {

        notNull(bundlesLocation, "Can't initialize bundles without bundles paths");

        bundles = new ArrayList<ResourceBundle>(bundlesLocation.size());
        for (String bundle : bundlesLocation) {
            if ("".equals(bundle)) {
                continue;
            }
            ResourceBundle toAdd = ResourceBundle.getBundle(bundle, getLocale());
            bundles.add(toAdd);
        }
    }

    private String findInBundles(String key) {

        String toRet = getStringOrNull(key);
        if (toRet != null) {
            return toRet;
        }
        if (!lenient) {
            return key;
        }
        return key + "&&&";
    }

    protected String getStringOrNull(String key) {

        if (bundles == null) {
            initialize();
        }

        for (ResourceBundle bundle : getBundles()) {
            if (bundle.containsKey(key)) {

                return bundle.getString(key);
            }
        }
        return null;
    }

    /**
     * Retorna la cadena internacionalizada de la llave pasada.
     * 
     * <p>
     * Si la cadena pasada es:
     * 
     * <pre>
     *    KEY = El auto con chapa {} fue creado correctamente a las {} horas.
     * </pre>
     * 
     * Se muestran diferentes invocaciones con diferentes resultados:
     * 
     * <pre>
     *    getString("KEY", "ADB 333", "15:00") 
     *    =>   El auto con chapa ADB 333 fue creado correctamente a las 15:00 horas
     * 
     *    getString("KEY")
     *    =>   El auto con chapa {} fue creado correctamente a las {} horas.
     * 
     *    getString("KEY", "123 CCC")
     *    =>   El auto con chapa 123 CCC fue creado correctamente a las {} horas.
     * 
     * </pre>
     * 
     * </p>
     * 
     * <p>
     * La obtencin de las cadenas internacionalizadas se define en
     * {@link #initializeBundles(List)}, el cual recibe una lista de nombres de
     * archivos con cadenas de internacionalizacin, las mismas se defien en
     * <code>karaku.properties</code>.
     * </p>
     * 
     * @param key
     *            llave del archivo de internacionalizacion
     * @param arguments
     *            (since 3.0) argumentos de la cadena parametrizada.
     * @return cadena internacionalizad de acuerdo al locale actual
     */
    public String getString(String key, Object... arguments) {

        return format(findInBundles(key), arguments);
    }

    /**
     * Retorna la cadena internacionalizada de la llave pasada, busca en todos
     * los archivos de internacionalizacion definidos en el karaku.properties.
     * 
     * @param key
     *            llave del archivo de internacionalizacion
     * @return cadena internacionalizad de acuerdo al locale actual
     * @see #getString(String, Object...)
     */
    public static String getMessage(String key) {

        return getSingleton().getString(key);
    }

    /**
     * Invoca al mtodo {@link #getMessage(String)} por cada cadena pasada, y lo
     * agrega a una lista.
     * 
     * @param keys
     *            claves del archivo de internacionalizacin
     * @return lista con los valores internacionalizados.
     */
    public List<String> convertStrings(String string, String... keys) {

        List<String> convert = new ArrayList<String>();
        convert.add(getString(string));
        if (!ArrayUtils.isEmpty(keys)) {
            for (String s : keys) {
                convert.add(getString(s));
            }
        }
        return convert;
    }

    /**
     * Compara una clave con un valor internacionalizado.
     * 
     * @param key
     *            clave del archivo
     * @param value
     *            supuesto valor internacionalizado
     * @return <code>true</code> si es el valor, <code>false</code> en otro
     *         caso.
     */
    public boolean compare(String key, String value) {

        return getString(key).equals(value);
    }

    /**
     * Retorna el valor internacionalizado de una anotacin {@link DisplayName}.
     * 
     * @param displayName
     *            anotacin
     * @return "" si es <code>null</code> o esta vaca, en otro caso del valor
     *         internacionalizado.
     */
    public static String getName(DisplayName displayName) {

        if (displayName == null) {
            return "";
        }
        if (StringUtils.isInvalid(displayName.key())) {
            return "";
        }
        String key = displayName.key();
        char startWith = key.charAt(0);
        char endWith = key.charAt(key.length() - 1);

        if (startWith != '{' && endWith != '}') {
            return getMessage(key);
        }

        return getMessage(displayName.key().substring(1, displayName.key().length() - 1));
    }

    protected String format(@Nonnull String base, Object[] arguments) {

        if (ArrayUtils.isEmpty(arguments)) {
            return base;
        }

        StringBuilder builder = new StringBuilder();
        int templateStart = 0;
        int i = 0;
        while (i < arguments.length) {
            int placeholderStart = base.indexOf("{}", templateStart);
            if (placeholderStart == -1) {
                break;
            }
            builder.append(base.substring(templateStart, placeholderStart));
            builder.append(arguments[i++]);
            templateStart = placeholderStart + 2;
        }
        builder.append(base.substring(templateStart));

        return builder.toString();
    }
}