All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.swak.i18n.aggregate.AggregateResourceBundleMessageSource Maven / Gradle / Ivy

The newest version!
package com.swak.i18n.aggregate;

import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.swak.common.exception.SwakAssert;
import com.swak.common.util.StringPool;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.support.AbstractResourceBasedMessageSource;
import org.springframework.util.ClassUtils;

import java.text.MessageFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author colley.ma
 * @since 3.0.0
 */
@Slf4j
public class AggregateResourceBundleMessageSource extends AbstractResourceBasedMessageSource
        implements BeanClassLoaderAware, InitializingBean {

    private ClassLoader bundleClassLoader;

    private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();

    private ResourceBundleLocator resourceBundleLocator;

    private final boolean aggregate;

    private final Map cachedResourceBundles = new ConcurrentHashMap<>();

    private final Map>> cachedBundleMessageFormats =
            new ConcurrentHashMap<>();

    public AggregateResourceBundleMessageSource(boolean aggregate) {
        setDefaultEncoding(StringPool.UTF8);
        this.aggregate = aggregate;
    }

    public AggregateResourceBundleMessageSource(String[] bundleNames) {
        this(bundleNames, false);
    }

    public AggregateResourceBundleMessageSource(String[] bundleNames, boolean aggregate) {
        SwakAssert.state(ArrayUtils.isNotEmpty(bundleNames), "[Swak-I18n] bundleNames must not be empty");
        super.addBasenames(bundleNames);
        this.aggregate = aggregate;
    }

    protected ClassLoader getBundleClassLoader() {
        return (this.bundleClassLoader != null ? this.bundleClassLoader : this.beanClassLoader);
    }

    public ResourceBundle doGetBundle(Locale locale) {
        ResourceBundle rb = resourceBundleLocator.getResourceBundle(locale);
        if (rb != null) {
            log.debug("[Swak-I18n] {} i18n resource found.", Joiner.on(",").join(getBasenameSet()));
        } else {
            log.warn("[Swak-I18n] {} i18n resource not found.", Joiner.on(",").join(getBasenameSet()));
        }
        return rb;
    }

    protected ResourceBundle getResourceBundle(Locale locale) {
        if (getCacheMillis() >= 0) {
            return doGetBundle(locale);
        } else {
            ResourceBundle bundle = this.cachedResourceBundles.get(locale);
            if (Objects.nonNull(bundle)) {
                return bundle;
            }
            try {
                bundle = doGetBundle(locale);
                if (Objects.nonNull(bundle)) {
                    this.cachedResourceBundles.put(locale, bundle);
                }
                return bundle;
            } catch (MissingResourceException ex) {
                if (log.isWarnEnabled()) {
                    log.warn("[Swak-I18n] ResourceBundle [" + Joiner.on(",").join(getBasenameSet()) + "] " +
                            "not found for MessageSource: " + ex.getMessage());
                }
                return null;
            }
        }
    }

    @Override
    protected MessageFormat resolveCode(String code, Locale locale) {
        ResourceBundle bundle = getResourceBundle(locale);
        if (bundle != null) {
            MessageFormat messageFormat = getMessageFormat(bundle, code, locale);
            if (messageFormat != null) {
                return messageFormat;
            }
        }
        return null;
    }

    protected MessageFormat getMessageFormat(ResourceBundle bundle, String code, Locale locale)
            throws MissingResourceException {
        Map> codeMap = this.cachedBundleMessageFormats.get(bundle);
        Map localeMap = null;
        if (codeMap != null) {
            localeMap = codeMap.get(code);
            if (localeMap != null) {
                MessageFormat result = localeMap.get(locale);
                if (result != null) {
                    return result;
                }
            }
        }
        String msg = getStringOrNull(bundle, code);
        if (msg != null) {
            if (codeMap == null) {
                codeMap = new ConcurrentHashMap<>();
                Map> existing = this.cachedBundleMessageFormats.putIfAbsent(bundle, codeMap);
                if (existing != null) {
                    codeMap = existing;
                }
            }
            if (localeMap == null) {
                localeMap = new ConcurrentHashMap<>();
                Map existing = codeMap.putIfAbsent(code, localeMap);
                if (existing != null) {
                    localeMap = existing;
                }
            }
            MessageFormat result = createMessageFormat(msg, locale);
            localeMap.put(locale, result);
            return result;
        }
        return null;
    }

    protected String getStringOrNull(ResourceBundle bundle, String key) {
        if (bundle.containsKey(key)) {
            try {
                return bundle.getString(key);
            } catch (MissingResourceException ex) {
                // Assume key not found for some other reason
                // -> do NOT throw the exception to allow for checking parent message source.
            }
        }
        return null;
    }

    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        this.bundleClassLoader = classLoader;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        this.resourceBundleLocator = new AggregateResourceBundleLocator(Lists.newArrayList(getBasenameSet()),
                getBundleClassLoader(), aggregate);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy