/* * Copyright 2004-2012 the Seasar Foundation and the Others. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. See the License for the specific language * governing permissions and limitations under the License. */ package org.seasar.util.message; import java.text.MessageFormat; import java.util.ResourceBundle; import org.seasar.util.io.ResourceBundleUtil; import org.seasar.util.misc.Disposable; import org.seasar.util.misc.DisposableUtil; import static org.seasar.util.lang.StringUtil.*; /** * メッセージコードと引数からメッセージを組み立てるクラスです。 * * @author higa */ public abstract class MessageFormatter { /** メッセージコードの数値部の長さ */ protected static final int CODE_NUMBER_LENGTH = 4; /** メッセージコードに対応するリソースバンドル名の接尾辞 */ protected static final String MESSAGES = "Messages"; /** 初期化済みを示すフラグ */ protected static volatile boolean initialized; /** * メッセージを返します。 * * @param messageCode * メッセージコード * @param args * 引数 * @return メッセージ */ public static String getMessage(final String messageCode, final Object... args) { return getFormattedMessage( messageCode == null ? "" : messageCode, getSimpleMessage(messageCode, args)); } /** * メッセージコードつきのメッセージを返します。 * * @param messageCode * メッセージコード * @param simpleMessage * 引数が展開された単純なメッセージ * @return メッセージコードつきのメッセージ */ public static String getFormattedMessage(final String messageCode, final String simpleMessage) { return "[" + messageCode + "]" + simpleMessage; } /** * 引数を展開してメッセージコードなしの単純なメッセージを返します。 * * @param messageCode * メッセージコード * @param args * 引数 * @return メッセージコードなしの単純なメッセージ */ public static String getSimpleMessage(final String messageCode, final Object... args) { try { final String pattern = getPattern(messageCode); if (pattern != null) { return MessageFormat.format(pattern, args); } return getNoPatternMessage(args); } catch (final Throwable ignore) { return getNoPatternMessage(args); } } /** * メッセージコードに対応するパターン文字列を返します。 * * @param messageCode * メッセージコード * @return パターン文字列 */ protected static String getPattern(final String messageCode) { if (isEmpty(messageCode)) { return null; } final ResourceBundle resourceBundle = getResourceBundle(getSystemName(messageCode)); if (resourceBundle == null) { return null; } final int length = messageCode.length(); if (length > CODE_NUMBER_LENGTH) { final String key = messageCode.charAt(0) + messageCode.substring(length - CODE_NUMBER_LENGTH); final String pattern = ResourceBundleUtil.getString(resourceBundle, key); if (pattern != null) { return pattern; } } return resourceBundle.getString(messageCode); } /** * システム名を返します。 * * @param messageCode * メッセージコード * @return システム名 */ protected static String getSystemName(final String messageCode) { return messageCode.substring( 1, Math.max(1, messageCode.length() - CODE_NUMBER_LENGTH)); } /** * リソースバンドルを返します。 * * @param systemName * システム名 * @return リソースバンドル */ protected static ResourceBundle getResourceBundle(final String systemName) { if (!initialized) { initialize(); } return ResourceBundleUtil.getBundle(systemName + MESSAGES); } /** * パターンを使用しないで引数を並べたメッセージを返します。 * * @param args * 引数 * @return 引数を並べたメッセージ */ protected static String getNoPatternMessage(final Object... args) { if (args == null || args.length == 0) { return ""; } final StringBuilder buffer = new StringBuilder(); for (final Object arg : args) { buffer.append(arg + ", "); } buffer.setLength(buffer.length() - ", ".length()); return new String(buffer); } /** * 初期化します。 */ protected static synchronized void initialize() { if (!initialized) { DisposableUtil.add(new Disposable() { @Override public void dispose() { ResourceBundle.clearCache(); initialized = false; } }); initialized = true; } } }