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

com.github.mygreen.cellformatter.lang.MessageResolver Maven / Gradle / Ivy

There is a newer version: 0.12
Show newest version
package com.github.mygreen.cellformatter.lang;

import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.ResourceBundle;
import java.util.concurrent.ConcurrentHashMap;

/**
 * メッセージソースを管理するクラス。
 * 

ロケールを指定した場合、そのロケールで存在しないキーがあるときに、標準の値を返す。 * * @version 0.10 * @since 0.5 * @author T.TSUCHIE * */ public class MessageResolver { /** * 解決するリソース名。 *

リソースバンドル名の形式。 */ private final String resourceName; /** * デフォルトのメッセージがない場合を許可するかどうか。 */ private final boolean allowedNoDefault; /** * クラスパスのルートにあるユーザ定義のメッセージソースも読み込むかどうか指定します。 */ private final boolean appendUserResource; /** * デフォルトのメッセージ情報 */ private MessageResource defaultResource; /** * ロケールごとのメッセージリソースの取得 */ private Map resources; /** * リソース名を指定してインスタンスを生成する。 * @param resourceName リソース名。形式は、{@link ResourceBundle}の名称。 */ public MessageResolver(final String resourceName) { this(resourceName, false, false); } /** * リソース名を指定してインスタンスを生成する。 * @param resourceName リソース名。形式は、{@link ResourceBundle}の名称。 * @param allowedNoDefault デフォルトのメッセージがない場合を許可するかどうか。 * @param appendUserResouce クラスパスのルートにあるユーザ定義のメッセージソースも読み込むかどうか指定します。 * 引数resourceNameの値が {@literal sample.SampleMessages}のとき、クラスパスのルート上にある「SampleMessages」を読み込みます。 */ public MessageResolver(final String resourceName, final boolean allowedNoDefault, final boolean appendUserResouce) { this.resourceName = resourceName; this.allowedNoDefault = allowedNoDefault; this.appendUserResource = appendUserResouce; this.defaultResource = loadDefaultResource(allowedNoDefault, appendUserResouce); this.resources = new ConcurrentHashMap<>(); } private String getPropertyPath() { final String baseName = getResourceName().replaceAll("\\.", "/"); String path = new StringBuilder() .append("/") .append(baseName) .append(".properties") .toString(); return path; } private String[] getPropertyPath(final Locale locale) { final List list = new ArrayList<>(); final String baseName = getResourceName().replaceAll("\\.", "/"); if(Utils.isNotEmpty(locale.getLanguage())) { String path = new StringBuilder() .append("/") .append(baseName) .append("_").append(locale.getLanguage()) .append(".properties") .toString(); list.add(path); } if(Utils.isNotEmpty(locale.getLanguage()) && Utils.isNotEmpty(locale.getCountry())) { String path = new StringBuilder() .append("/") .append(baseName) .append("_").append(locale.getLanguage()) .append("_").append(locale.getCountry()) .append(".properties") .toString(); list.add(path); } Collections.reverse(list); return list.toArray(new String[list.size()]); } /** * プロパティファイルから取得する。 *

プロパティ名を補完する。 * @param path プロパティファイルのパス名 * @param allowedNoDefault デフォルトのメッセージがない場合を許可するかどうか。 * @param appendUserResource クラスパスのルートにあるユーザ定義のメッセージソースも読み込むかどうか指定します。 * @return */ private MessageResource loadDefaultResource(final boolean allowedNoDefault, final boolean appendUserResource) { final String path = getPropertyPath(); Properties props = new Properties(); try { props.load(new InputStreamReader(MessageResolver.class.getResourceAsStream(path), "UTF-8")); } catch (NullPointerException | IOException e) { if(allowedNoDefault) { return MessageResource.NULL_OBJECT; } else { throw new RuntimeException("fail default properties. :" + path, e); } } final MessageResource resource = new MessageResource(); final Enumeration keys = props.propertyNames(); while(keys.hasMoreElements()) { String key = (String) keys.nextElement(); String value = props.getProperty(key); resource.addMessage(key, value); } // ユーザのリソースの読み込み if(appendUserResource) { resource.addMessage(loadUserResource(path)); } return resource; } /** * 指定したロケールのリソースを取得する。 *

該当するロケールのリソースが存在しない場合は、デフォルトのリソースを返す。 * @param locale ロケールがnullの場合は、デフォルトのリソースを返す。 * @return */ MessageResource loadResource(final Locale locale) { if(locale == null) { return defaultResource; } if(resources.containsKey(locale)) { return resources.get(locale); } MessageResource localeResource = null; synchronized (resources) { for(String path : getPropertyPath(locale)) { try { final Properties props = new Properties(); props.load(new InputStreamReader(MessageResolver.class.getResourceAsStream(path), "UTF-8")); localeResource = new MessageResource(); final Enumeration keys = props.propertyNames(); while(keys.hasMoreElements()) { String key = (String) keys.nextElement(); String value = props.getProperty(key); localeResource.addMessage(key, value); } // ユーザのリソースの読み込み if(appendUserResource) { localeResource.addMessage(loadUserResource(path)); } break; } catch(NullPointerException | IOException e) { continue; } } if(localeResource == null) { // 該当するリソースが見つからない場合は、デフォルトの値を返す。 localeResource = defaultResource; } resources.put(locale, localeResource); } return localeResource; } /** * * @param basePath 基準となるプロパティファイルパス。「/」区切りで、拡張子、ロケール名が付いている。 * @return 読み込んだメッセージソース。存在しない場合は、{@link MessageResource#NULL_OBJECT}を返す。 */ private MessageResource loadUserResource(final String basePath) { // ファイル名の切り出し final int index = basePath.lastIndexOf("/"); if(index <= 0) { return MessageResource.NULL_OBJECT; } final String userPropertyPath = "/" + basePath.substring(index+1); try { Properties props = new Properties(); props.load(new InputStreamReader(MessageResolver.class.getResourceAsStream(userPropertyPath), "UTF-8")); final MessageResource resource = new MessageResource(); final Enumeration keys = props.propertyNames(); while(keys.hasMoreElements()) { String key = (String) keys.nextElement(); String value = props.getProperty(key); resource.addMessage(key, value); } return resource; } catch(NullPointerException | IOException e) { return MessageResource.NULL_OBJECT; } } /** * リソース名の取得。 * @return */ public String getResourceName() { return resourceName; } /** * デフォルトのメッセージ情報がない場合を許可するかどうか。 * @return */ public boolean isAllowedNoDefault() { return allowedNoDefault; } /** * キーを指定してメッセージを取得する。 * @param key メッセージキー * @return 存在しないキーの場合、nullを返す。 */ public String getMessage(final String key) { return defaultResource.getMessage(key); } /** * ロケールとキーを指定してメッセージを取得する。 *

ロケールに該当する値を取得する。 * @param locale ロケール * @param key メッセージキー * @return 該当するロケールのメッセージが見つからない場合は、デフォルトのリソースから取得する。 */ public String getMessage(final MSLocale locale, final String key) { if(locale == null) { return loadResource(null).getMessage(key); } else { return loadResource(locale.getLocale()).getMessage(key); } } /** * ロケールとキーを指定してメッセージを取得する。 * @param locale ロケール * @param key メッセージキー * @param defaultValue * @return 該当するロケールのメッセージが見つからない場合は、引数で指定した'defaultValue'の値を返す。 */ public String getMessage(final MSLocale locale, final String key, final String defaultValue) { String message = getMessage(locale, key); return message == null ? defaultValue : message; } /** * ロケールとキーを指定してメッセージを取得する。 *

ロケールに該当する値を取得する。 * @param locale ロケール * @param key メッセージキー * @return 該当するロケールのメッセージが見つからない場合は、デフォルトのリソースから取得する。 */ public String getMessage(final Locale locale, final String key) { return loadResource(locale).getMessage(key); } /** * 値がnullの場合、defaultValueの値を返す。 * @param locale ロケール * @param key メッセージキー * @param defaultValue * @return 該当するロケールのメッセージが見つからない場合は、引数で指定した'defaultValue'の値を返す。 */ public String getMessage(final Locale locale, final String key, final String defaultValue) { String message = getMessage(locale, key); return message == null ? defaultValue : message; } /** * 書式のロケールを優先して、キーに対するメッセージを取得する。 * formatLocaleがnullのとき、runtimeLocaleから値を取得する。 * * @since 0.10 * @param formatLocale 書式に指定されているロケール。nullの場合がある。 * @param runtimeLocale 実行時のロケール。 * @param key メッセージキー * @return 該当するロケールのメッセージが見つからない場合は、デフォルトのリソースから取得する。 */ public String getMessage(final MSLocale formatLocale, Locale runtimeLocale, final String key) { if(formatLocale != null) { return getMessage(formatLocale, key); } else { return getMessage(runtimeLocale, key); } } /** * 書式のロケールを優先して、キーに対するメッセージを取得する。 * formatLocaleがnullのとき、runtimeLocaleから値を取得する。 * * @since 0.10 * @param formatLocale 書式に指定されているロケール。nullの場合がある。 * @param runtimeLocale 実行時のロケール。 * @param key メッセージキー * @param defaultValue * @return 該当するロケールのメッセージが見つからない場合は、引数で指定した'defaultValue'の値を返す。 */ public String getMessage(final MSLocale formatLocale, Locale runtimeLocale, final String key, final String defaultValue) { if(formatLocale != null) { return getMessage(formatLocale, key, defaultValue); } else { return getMessage(runtimeLocale, key, defaultValue); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy